Зарегистрируйтесь сейчас чтобы найти еще больше друзей, и получить полноценный доступ ко всем функциям сайта!
Для просмотра Вам необходимо авторизоваться Если Вы еще не зарегистрированы, перейдите по ссылке:Зарегистрироваться
x
Хроники Interlude
" V$ o! c5 o# Q8 q; yСборка L2j- m/ p3 e, I* P. A
Обратите внимание: в файле htm стартового NCP обязательно должна быть ссылка на квест:& S0 ^% r' B% i6 Q0 X' [
- STARTED.addQuestDrop(KELTIR_NPC_ID,FANGS_ITEM_ID,DROP_RATE)
Скопировать код Для этого квеста больше ничего не надо. Все необходимое для корректной работы квеста уже добавили. Вот полный текст квеста:
. K, l( V& f( n! Q! e7 I& T! ]8 G }4 ?* g# Y$ j
- if getCount(st) >= 4 :
2 }6 `# b. a4 m3 J% T - completed(st)
' z: J& e8 Y* X* { - return
" p' h, Z* r# C& n1 G) i - ) k) j2 Z* A- ~
- class Quest (JQuest):
6 |" s0 Q) Y- W7 w, O6 U# `( [ - def __init__(self,id,name,descr): JQuest.__init__(self,id,name,descr)
3 j- J s0 z. ^+ w& E - def onEvent (self,event,st):
3 N! v* u$ k# F/ R5 e7 a8 E - id = st.getState()) i- z2 E+ ]' R+ }- m0 e
- if id == CREATED : st.setState(STARTED)
% M$ I7 v d3 {9 g+ G* s% m: ]( }' s - elif id == COMPLETED: pass' M/ s" @) L' c7 ~& u$ d7 p! o: k N
- elif id == STARTED : check(st)5 u; h, c/ y( I. h
- return
; @. S( D' f- @% Q3 H) l+ m) a$ S
5 {# f! s8 g* ~0 S( w- QUEST = Quest(201,"Tutorial", "Tutorial quest")/ ]' z; y x2 Q" x+ s
- CREATED = State('Start', QUEST)" L' ?- w* O4 W0 d- o
- STARTED = State('Started', QUEST)
0 s, e( B2 D1 J1 Z+ g3 F' ` - COMPLETED = State('Completed', QUEST)7 U8 s2 k% O3 _2 m7 t: V% L0 U
9 D% }" G( ~* M% h, H( G- QUEST.setInitialState(CREATED)
5 O1 Z+ N) Q2 L0 W$ A - QUEST.addStartNpc(7056)3 N9 F* P3 T) G( B8 j8 t1 T
- STARTED.addQuestDrop(KELTIR_NPC_ID,FANGS_ITEM_ID,DROP_RATE)
Скопировать код Теперь рассмотрим, как это работает.
) c. q: O- u8 }* ^Игрок подходит к начальному NCP (в данном случае 7056), нажимает на «Quest». Квест будет создан и состояние квеста перейдет к CREATED и игроку будет показана страничка Start.htm с описанием квеста. Тогда метод onEvent, поле открытия странички Start.htm переведет состояние квеста в STARTED и игроку будет показана страничка Started.htm, где будет опсание того, как найти keltirs и .т.д.0 g6 x: {% I0 P& B% V- e7 k$ S
a& _. K1 R3 w8 {$ m; P, P
( n/ q( e. i0 c
При состоянии STARTED будет зарегистрирован дроп «fangs» при убийстве keltirs. Игрок может вернуться к стартовому NCP и спросить о квесте – метод onEvent будет вызван снова. Если у игрока не хватает необходимого количества предметов, то метод check() не переведет квест в следующее состояние и Started.htm будет показана снова. Но если игрок собрал необходимее количество предметов (в данном случае 4 клыка), то метод check() вызовет метод completed() который переведет квест в новое состояние COMPLETED, заберет все клыки, даст карту мира, т.к. это награда за квест, покажет Completed.htm и завершит квест.2 Z* [+ a+ w2 j- q, V- \) J0 t7 v
* `' Y4 w6 C \6 l% {2 S3 _
: O0 ^! G9 H/ gТеперь давайте сделаем наш квест более похожим на то, что он должен из себя представлять." x. u' c3 H. r' L {) ^
Прежде всего у нас есть 3 метода для объявления их в Яве – onTalk, onKill и onEvent. Если методы onTalk и onKill не объявлены, то за них все будет делать метод onEvent, т.е. определять квестовых монстров и вызывать диалоги NCP. Есть примечание, методы onTalk и onKill будут вызывать только диалоги с NCP в зависимости от текущего состояния квеста. Метод onKill будет вызываться только тогда, когда мы убиваем квестового монстра./ M; A6 q" I+ a. T D8 O
4 b E4 E- j+ U6 J( b' `4 t
' D# o) c1 C4 E+ K$ nДавайте рассмотрим как вызывается метод onKill при убийстве keltir в состоянии квеста STARTED:& T) x8 E$ U5 U8 h. B- u
- STARTED.addKillId(KELTIR_NPC_ID)
Скопировать код и метод onKill в классе Quest:* W0 }/ I: F7 J' U" j2 e$ M: W3 t
, D- T& t2 z& L% @/ g- W- class Quest (JQuest):6 i* d' j) |, y: {( _, x
- ...9 y" o8 P! C4 K7 }6 e9 K# A
- def onKill (self,npcId,st):
# J$ ^0 K) k3 Q L - if npcId == KELTIR_NPC_ID:/ ~0 Z+ Y! G5 G' y: |4 a
- n = getCount(st)
& H% Q6 C8 [# M1 L% t - if n == 0:& u, d" {# X' ], o8 z/ c" b
- return "Chat0.htm"
- h: Y/ p( O) A$ X! t" T - elif n == 1:+ T2 K3 m( ?4 Z- X. C- g' U
- return "Chat1.htm"! b1 n% l7 G1 \7 i* S/ g2 K5 F
- elif n >= 4:$ e6 q/ d: q; Z: p; J* a- `
- return "Chat4.htm"6 n# ?" D1 x/ z- e- }
- return "Collected "+str(n)+" of 4 fangs"
* S1 F$ B# l) i2 c- {% j$ v$ q - return
Скопировать код Метод onKill (а так же метод onTalk) имеет следующие параметры:
+ K- a0 O& d5 M V; a% j" n# Z( J5 W* J' }
+ s! }2 a/ V3 i+ S7 M+ }9 B5 j
• self – квест, X) r6 k) B# F q$ T$ n
• npcId – ID NCP, которого мы должны убивать (если это метод onTalk, то ID того NCP, с которым мы должны поговорить).5 G% o# T4 f% \ s
• st – текущее состояние игрока.
* w% E1 y: D) b5 V
- d. q' v3 c$ i$ n y5 A" g9 h, A7 O0 [* x7 m
В этом методе мы проверяем и отмечаем, является ли убитый NCP keltir’ом. В основном эта проверка не нужна, т.к. у нас только KELTIR_NPC_ID.
3 \/ A4 }( ~" o0 V8 i/ u
; B4 A$ y; c/ \3 Y1 C: _6 Y
9 r! }. a) _1 g4 i# qЗатем проверяем количество предметов (в данном случае количество клыков), и если их вообще нет, то возвращаем строку "Chat0.htm", если только один предмет, то возвращаем строку "Chat1.htm", если же предметов 4 или больше, то "Chat4.htm". Если строка возвращена из методов onEvent, onKill или onTalk, то сервер покажет соответствующие htm. В Chat0.htm может иметь следующий текст: «Вы не имеете ни одного клыка, возвращайтесь позже, когда соберете 4 штуки и бла, бла, бла…», в Chat1.htm может быть следующий текст: «У Вас всего 1 клык, по этому соберите еще…». В Chat4.htm – «Вы собрали необходимое количество предметов, возвращайтесь к вашему тренеру, что бы завершить квест…»9 V5 z7 h% Q5 u! i
6 |0 @! M, H# n. ]3 ?
, F6 |, r' D- w. G' S) z
Примечание: если в строка return начинается с "<html>", то будет показана страничка html с текстом, который стоит далее. Так вместо:5 @3 o- k& q7 X: f) W. _: _
return "Chat4.htm"+ i! `& ~ d u5 R
$ R; l6 ]0 v2 `" x, J6 S% a- J3 H- A8 v8 H# G; `( A8 s
можно поставить:! A& l) J( @" ~/ E1 [3 }
- return "<html><body>Return to your trainer to complete the quest</body></html>"
Скопировать код Так же если строка заканчивается без .htm или в начале нет <html>, то текст будет выведен, как системное сообщение в окне чата. В нашем случае мы сделаем так, что бы при каждом убийстве keltik выводилось системное сообщение: «Собрано N из 4-х клыков».
% h( `0 B/ o6 Q- [+ T
: ^) o1 ]& ]: r3 i7 _5 V' k1 G# p$ `( F
Наш код для onKill имеет один недостаток. Он будет постоянно показывать Chat0.htm, Chat1.htm и Chat4.htm, нам же необходимо, что бы Chat0.htm и Chat1.htm показывались только один раз. Как нам это сделать? С помощью переменных." s% C& W: @8 t+ t4 o0 H# W, a R
- f+ M" p _6 z* o9 i
" Y ~ }. s& _0 g* I8 TВ каждом квесте строки могут храниться с помощью переменных. Эти переменные сохраняются в Вашей БД. В каждом методе мы можем назначить, прочитать и удалить переменные. Давайте изменим метод onKill, так что бы каждый диалог вызывался только один раз.( T9 c# p% T* k) C2 ^8 q% T
- def onKill (self,npcId,st):8 `0 L: W2 {# h3 F2 j! M o
- if npcId == KELTIR_NPC_ID:1 c+ ]3 z3 X. T3 ~" y% z9 u2 @
- n = getCount(st)
6 `( n1 p1 I* Y* Y: B: e8 F - if n == 0:3 X. ~4 A& w- J0 o: d
- if st.get('chat0') == None :
$ \7 \: }' x; F2 d# s. Q; e0 ` - st.set("chat0", "true")" g2 F- f4 S$ r1 ]4 y$ Q. S" p2 v& z
- return "Chat0.htm"
# A2 y C6 r7 Q) S4 W( d9 W1 z1 U/ m - elif n == 1:
1 _7 ?2 u' Q! y - if st.get('chat1') == None :2 _* V! R- z( y
- st.set("chat1", "true"). \) m* b% }5 p6 @' o6 F6 a4 g
- return "Chat1.htm"
% v4 Y" ~* c& d2 i. n8 M0 I - elif n >= 4:% [/ ^& a/ i. `
- return "Chat4.htm"
# w- q$ R0 m! l. L - return "Collected "+str(n)+" of 4 fangs"! X% K Z5 }4 v2 n% ~( G, U% |& n% C
- return
Скопировать код Если у игрока нет клыков (n=0), то мы получаем занчение переменной 'chat0'. Когда метод onKill вызван в первый раз, то пока ни каких переменных не имеется и python возвращает значение None. В этом случае объявляется переменная и показывается диалог Chat0.htm. Когда мы убиваем keltir, но не получаем с него клык, функция st.get('chat0') возвращает строку true, а не None. И во второй раз окно с Chat0.htm не появится, но в окне чата появится строчка «Collected 0 of 4 fangs». По тому же принципу сделано и с Chat1.htm.
2 W0 }9 o6 {; a" s. a
# T8 D3 E9 a1 e& F: D l7 _9 l5 p$ R8 c$ B, E
Вот конечный рабочий вариант квеста:
^! E% t C$ I7 }: v. s5 R: M- import sys
2 q2 T' h: Q& k! s - from net.sf.l2j.gameserver.model.quest import State
- l$ b* ~; L+ _9 X - from net.sf.l2j.gameserver.model.quest import QuestState1 k# y g! J( _
- from net.sf.l2j.gameserver.model.quest.jython import QuestJython as JQuest
; I' ]* l1 y- X
# ^1 K+ @0 N* |) B/ M- KELTIR_NPC_ID = 12082
, v1 a/ I4 l# [& B) e - FANGS_ITEM_ID = 1859
) y C& v# j( _5 ?7 K1 E# n - DROP_RATE = 500000
( d1 S0 o. k: V1 k8 B, }* d l6 z
3 n9 L; j6 F$ X' s" b3 ]; v( \0 h( M- WORLD_MAP_ITEM_ID = 16653 o( v$ A8 T( v+ }. v( F
5 H Z7 A% r6 i/ [6 E- def getCount(st) :" N4 s; ~$ R0 s t
- return st.getQuestItemsCount(FANGS_ITEM_ID)8 G7 o) Z* T5 x* R3 H; T
9 S; e& p7 E$ ?" Q# A- def completed(st) :
% R# h, |+ M. J; O - st.setState(COMPLETED)
- V0 O6 D5 ^/ _# m; u" d: } - st.clearQuestDrops()- o5 i, L3 u8 }6 ~+ }0 s8 w
- st.takeItems(FANGS_ITEM_ID,-1)' T: t2 A9 [7 K) A4 }% a( {+ @) {6 ^8 a
- st.giveItems(WORLD_MAP_ITEM_ID,1)) B f& G" U$ _3 {3 X- a# E0 v
- st.exitQuest(False)
/ g4 R& j q3 }7 w - return3 J3 I! E4 G" Q. g8 ~3 i7 |: d
- ' q9 U- z- w- P0 z6 H: a% p
- def check(st) :2 f, T9 F. B7 \$ z
- if getCount(st) >= 4 :* `( B8 F, l( d o8 T4 y
- completed(st)
) G( M8 a$ A! L1 O) G& w1 w9 @& s - return9 r) v9 N% n& v
' N- c* {9 `# Z# F- class Quest (JQuest):# g& j0 ~6 C3 Y& v
& B7 y( V4 s4 |- def __init__(self,id,name,descr): JQuest.__init__(self,id,name,descr)
- F% \: n' ]+ `1 _$ T - + X9 m: ]( h U3 x) ]( M
- def onEvent (self,event,st):
$ s8 l0 W, t, M/ q! q$ {+ Q5 q - id = st.getState()
Q/ C1 N! w# L9 ?* v - if id == CREATED : st.setState(STARTED) o/ P* x; O8 h, L" l. S
- elif id == COMPLETED: pass
, e O- F" }: D0 p1 k8 ~ - elif id == STARTED : check(st)
c" H# s$ D& x+ i/ H2 S - return
& a$ T$ i* G% |
( \4 ]8 B6 [ P0 I" h% S- def onKill (self,npcId,st):
m# ^8 j( m, k/ _" c9 Y9 R, l) Z) o - if npcId == KELTIR_NPC_ID:
J& O( b7 q+ H1 G5 O - n = getCount(st)( u8 l3 i9 h; Y! M
- if n == 0:" p" Y- X8 J2 y, O7 E
- if st.get('chat0') == None :
. {8 b& {" }; n. N7 T6 w/ s - st.set("chat0", "true")
y& [) k$ K1 k# q$ i5 o - return "Chat0.htm"% f0 @) h" H* c, t
- elif n == 1:
5 U) _9 u0 W2 T, y! P - if st.get('chat1') == None :
& c; v5 p- M/ Q - st.set("chat1", "true")) k% m! G2 c& H3 v/ {
- return "Chat1.htm"
9 W% x5 Q" F0 c. _ - elif n >= 4:
8 Q/ ]9 `, K; d0 Q6 O - return "Chat4.htm"
( ?7 V3 L) B1 }7 l# i - return "Collect "+str(n)+" of 4 fangs"7 c( c; J: P" G% O
- return
& d! T+ n7 }5 V! K4 v9 ` - [! X; `( M: U; b4 `
- QUEST = Quest(201, "Tutorial", "Tutorial quest")
3 q) G6 V$ F& v: g) e! m - CREATED = State('Start', QUEST)
1 s, \; b5 s. p1 z - STARTED = State('Started', QUEST)
- e: f. ^' Y# q4 \$ j7 Z! N4 E) C7 T - COMPLETED = State('Completed', QUEST)/ W: K4 A$ f% j
! K- Y) F; W: z' H- QUEST.setInitialState(CREATED), t. s; M* M4 n9 c6 @. z6 \
- QUEST.addStartNpc(7056). n5 {0 T: m" l$ P0 J
- QUEST.addStartNpc(7012)
9 A" K9 R! V/ q - QUEST.addStartNpc(7009)
* @) u5 d, V9 b4 y9 {3 r - QUEST.addStartNpc(7011)
" Z# n$ U! P9 T# `0 u" d* h
- _$ @( o- ]8 n7 u: C! Z' q: u- STARTED.addQuestDrop(KELTIR_NPC_ID,FANGS_ITEM_ID,DROP_RATE)
4 S8 `' V3 h/ | - STARTED.addKillId(KELTIR_NPC_ID) @3 S k. R: u! ^! M: D
- STARTED.addTalkId(7056)4 g |$ n% b5 ^, y% q9 u9 Y
- STARTED.addTalkI d(7012). p+ c# b; g, Y
- STARTED.addTalkId(7009)
. @ F# K5 y2 [0 n1 J( y - STARTED.addTalkId(7011)
Скопировать код % w- R2 l+ _3 ]; V* W
, @4 ~4 s* k9 x+ e" b |