Зарегистрируйтесь сейчас чтобы найти еще больше друзей, и получить полноценный доступ ко всем функциям сайта!
Для просмотра Вам необходимо авторизоваться Если Вы еще не зарегистрированы, перейдите по ссылке:Зарегистрироваться
x
Хроники Interlude2 Q+ E$ H# y0 J/ W+ ^) D
Сборка L2j
6 _) ~0 H7 X% @' `Обратите внимание: в файле htm стартового NCP обязательно должна быть ссылка на квест:
+ u# U" [: s, c' T- STARTED.addQuestDrop(KELTIR_NPC_ID,FANGS_ITEM_ID,DROP_RATE)
Скопировать код Для этого квеста больше ничего не надо. Все необходимое для корректной работы квеста уже добавили. Вот полный текст квеста:8 h6 q: h5 f! H
" P# a* W( b' B! _- if getCount(st) >= 4 :
/ D% c. W+ B# t7 U3 Z7 T - completed(st)
! o9 c5 Z) m; Y M- a0 w( p - return$ T, r% W0 y: Q2 a0 x0 ?8 y
* B7 \* z- e1 o8 |( ^3 a) F- class Quest (JQuest):
" E' V4 @; ~. s3 \ - def __init__(self,id,name,descr): JQuest.__init__(self,id,name,descr)4 | b. z/ A6 Z" @7 B
- def onEvent (self,event,st):* G6 J5 n: p' \
- id = st.getState()
0 W" j m; z$ q" P' B/ w$ j - if id == CREATED : st.setState(STARTED)
( ^$ W) D5 K8 E( Z- L7 L3 |: y - elif id == COMPLETED: pass
+ Q0 P9 C7 B8 V5 u - elif id == STARTED : check(st)
) H/ L: D2 p( u E; k `) Y; Q# j - return
- j8 E6 [8 h1 L5 c& r$ e5 p9 H
5 L" B1 }) k- K F3 B* J- QUEST = Quest(201,"Tutorial", "Tutorial quest")
! _% [% |, K. i# w9 z$ _ - CREATED = State('Start', QUEST)
& d4 ]8 }& a2 S8 _ - STARTED = State('Started', QUEST)
! u. `0 n2 d& _$ q5 W - COMPLETED = State('Completed', QUEST)$ x; L- c! r, k: O. r' P3 |$ T# \
- 8 R& x# c: L6 V8 x6 \% R( r4 }! ?6 g
- QUEST.setInitialState(CREATED)2 T5 c' m, m0 i' R! i0 H5 d% d1 ~
- QUEST.addStartNpc(7056)+ h" |& K; _& S Y" i$ }' y
- STARTED.addQuestDrop(KELTIR_NPC_ID,FANGS_ITEM_ID,DROP_RATE)
Скопировать код Теперь рассмотрим, как это работает.) n2 j8 l( n" U( z1 {- I
Игрок подходит к начальному NCP (в данном случае 7056), нажимает на «Quest». Квест будет создан и состояние квеста перейдет к CREATED и игроку будет показана страничка Start.htm с описанием квеста. Тогда метод onEvent, поле открытия странички Start.htm переведет состояние квеста в STARTED и игроку будет показана страничка Started.htm, где будет опсание того, как найти keltirs и .т.д.5 K# B. V$ R' P6 z
8 L0 o0 Q& o& q7 M8 H
6 Y: u- m6 }7 T8 O) l
При состоянии STARTED будет зарегистрирован дроп «fangs» при убийстве keltirs. Игрок может вернуться к стартовому NCP и спросить о квесте – метод onEvent будет вызван снова. Если у игрока не хватает необходимого количества предметов, то метод check() не переведет квест в следующее состояние и Started.htm будет показана снова. Но если игрок собрал необходимее количество предметов (в данном случае 4 клыка), то метод check() вызовет метод completed() который переведет квест в новое состояние COMPLETED, заберет все клыки, даст карту мира, т.к. это награда за квест, покажет Completed.htm и завершит квест.
8 Y/ C! ]& V6 B) O5 b: h2 \9 F$ J& J) n( F
& }6 a5 c% B; w$ h: l5 D
Теперь давайте сделаем наш квест более похожим на то, что он должен из себя представлять.+ I1 H- w1 R/ t. d7 j) I
Прежде всего у нас есть 3 метода для объявления их в Яве – onTalk, onKill и onEvent. Если методы onTalk и onKill не объявлены, то за них все будет делать метод onEvent, т.е. определять квестовых монстров и вызывать диалоги NCP. Есть примечание, методы onTalk и onKill будут вызывать только диалоги с NCP в зависимости от текущего состояния квеста. Метод onKill будет вызываться только тогда, когда мы убиваем квестового монстра.# o' L0 k+ I. o% [
9 F+ \7 |, s# i/ X Y4 d
6 [0 E8 |# `& O! t- d. }( h$ A* d
Давайте рассмотрим как вызывается метод onKill при убийстве keltir в состоянии квеста STARTED:) _8 T" L" I; d& h% `& V3 l
- STARTED.addKillId(KELTIR_NPC_ID)
Скопировать код и метод onKill в классе Quest:
3 L$ a) v' }! A& K3 F( I8 T9 t6 v4 R/ E2 n% \" s% F4 l; b* Y
- class Quest (JQuest):2 K2 {/ L" c# S/ N
- ..., Z0 m7 K- y. y* e* f# `1 Q3 o
- def onKill (self,npcId,st):( @, v4 ~9 r' X
- if npcId == KELTIR_NPC_ID:" X. x$ E( N0 b9 _- ^" N3 T9 }2 z
- n = getCount(st)( e7 z6 g$ Q$ R7 q3 s b
- if n == 0:+ v0 [$ q1 C0 c
- return "Chat0.htm"
* v& I6 e6 s9 [% _ A& J* \: E% ~ - elif n == 1:, E2 g0 k0 w' t" a; n0 C
- return "Chat1.htm"
+ X# x2 ]! Z* p1 h% e( z* _8 p6 K0 e - elif n >= 4:& k) B* E, h1 {1 z
- return "Chat4.htm"
& f1 F7 g# |6 E - return "Collected "+str(n)+" of 4 fangs"
0 Y. \' X" ~* [- ?+ }0 A - return
Скопировать код Метод onKill (а так же метод onTalk) имеет следующие параметры:5 ~+ N& K. G! M) u
" Z$ e/ \$ D6 p
1 x$ E* T+ z+ y' g* F0 n9 ~- m6 G
• self – квест
8 h0 |6 q& Q' z5 B: u' F* Z• npcId – ID NCP, которого мы должны убивать (если это метод onTalk, то ID того NCP, с которым мы должны поговорить).
0 M B6 O9 n/ ?; N8 L3 \• st – текущее состояние игрока.
+ V B9 [. Y, A. g9 Z8 u) g) z; k! C+ E
8 C* _4 ~4 a6 R( Z" w9 [
В этом методе мы проверяем и отмечаем, является ли убитый NCP keltir’ом. В основном эта проверка не нужна, т.к. у нас только KELTIR_NPC_ID.: s: N- G: r- M
- y1 ~, j. w* q- g2 |( C; t
: m- F. B I; y' a" f4 P
Затем проверяем количество предметов (в данном случае количество клыков), и если их вообще нет, то возвращаем строку "Chat0.htm", если только один предмет, то возвращаем строку "Chat1.htm", если же предметов 4 или больше, то "Chat4.htm". Если строка возвращена из методов onEvent, onKill или onTalk, то сервер покажет соответствующие htm. В Chat0.htm может иметь следующий текст: «Вы не имеете ни одного клыка, возвращайтесь позже, когда соберете 4 штуки и бла, бла, бла…», в Chat1.htm может быть следующий текст: «У Вас всего 1 клык, по этому соберите еще…». В Chat4.htm – «Вы собрали необходимое количество предметов, возвращайтесь к вашему тренеру, что бы завершить квест…»3 V2 Q5 K1 H/ t) ~/ y
$ N" j" G5 j. d" W* `+ e& Z
! Y3 E+ Q) P& b! |
Примечание: если в строка return начинается с "<html>", то будет показана страничка html с текстом, который стоит далее. Так вместо:
( S6 p, k8 a9 y# rreturn "Chat4.htm". l% V( R1 o" J3 u" p: Y
! p5 h3 w& x8 j% O
0 `/ |* `6 ?% f4 U! Q) S- d; }можно поставить:& U k5 {% I( t1 w
- return "<html><body>Return to your trainer to complete the quest</body></html>"
Скопировать код Так же если строка заканчивается без .htm или в начале нет <html>, то текст будет выведен, как системное сообщение в окне чата. В нашем случае мы сделаем так, что бы при каждом убийстве keltik выводилось системное сообщение: «Собрано N из 4-х клыков».1 r2 A/ m9 }- p& b) d
: x9 ~) m y5 n8 h0 A0 I* a
1 k/ F6 m5 l+ U% Q, h
Наш код для onKill имеет один недостаток. Он будет постоянно показывать Chat0.htm, Chat1.htm и Chat4.htm, нам же необходимо, что бы Chat0.htm и Chat1.htm показывались только один раз. Как нам это сделать? С помощью переменных.
6 Z* \' J( b, y) g0 Q; A
1 [$ h8 m$ z4 h8 R7 d. B) ?
2 q3 \% W. P+ r E; V2 y* yВ каждом квесте строки могут храниться с помощью переменных. Эти переменные сохраняются в Вашей БД. В каждом методе мы можем назначить, прочитать и удалить переменные. Давайте изменим метод onKill, так что бы каждый диалог вызывался только один раз." S4 D, J. ?/ u. T/ W$ Q
- def onKill (self,npcId,st):, ?+ H) w- {: P9 @/ D( ~
- if npcId == KELTIR_NPC_ID:
8 c f+ k3 m" u2 |* \ q - n = getCount(st)( p1 X. c9 s" E9 b V) U8 P3 k
- if n == 0:
?, H8 {* J- G" c5 W - if st.get('chat0') == None :8 Z+ f5 Q' \5 }/ g
- st.set("chat0", "true"). {5 s5 V8 K% Z7 j% A8 g
- return "Chat0.htm"1 O4 }0 n( S4 q7 d: f5 j/ u
- elif n == 1:
! z# Z9 Q4 ]9 m# }0 S3 S3 C& U& O9 v9 | - if st.get('chat1') == None :
. ]$ x5 p6 B9 i% `+ `3 Y+ y - st.set("chat1", "true")( g* A" {3 u" Z2 q5 Q
- return "Chat1.htm"9 d0 a+ p% l# R6 T6 S
- elif n >= 4:3 S( S" E9 f; `; p6 j" V) ?
- return "Chat4.htm"4 j5 p: m3 E" [5 u- z. O* O8 j- g
- return "Collected "+str(n)+" of 4 fangs"
+ Y9 l! U. ^$ A9 p4 F% y/ B" {1 G - return
Скопировать код Если у игрока нет клыков (n=0), то мы получаем занчение переменной 'chat0'. Когда метод onKill вызван в первый раз, то пока ни каких переменных не имеется и python возвращает значение None. В этом случае объявляется переменная и показывается диалог Chat0.htm. Когда мы убиваем keltir, но не получаем с него клык, функция st.get('chat0') возвращает строку true, а не None. И во второй раз окно с Chat0.htm не появится, но в окне чата появится строчка «Collected 0 of 4 fangs». По тому же принципу сделано и с Chat1.htm.' y( n! M( g* @+ F$ S' l
3 s! O- a( m$ s5 y/ W: C
" V) }& Q- m: U0 ^; b! P" s% x
Вот конечный рабочий вариант квеста:% r* R% q, M! Y; ?. D" E& ]
- import sys9 a% u, H+ \4 J$ j( X5 m
- from net.sf.l2j.gameserver.model.quest import State
l2 p0 K: c5 s4 S - from net.sf.l2j.gameserver.model.quest import QuestState4 g) d7 P2 u7 n& I
- from net.sf.l2j.gameserver.model.quest.jython import QuestJython as JQuest
' b4 K" o& g8 W+ j& H5 S9 B/ S2 k - 3 a Q+ R+ `! m( E* U, Z
- KELTIR_NPC_ID = 12082
7 {$ C# e! t, Q8 u: R! C$ I - FANGS_ITEM_ID = 1859
0 ]! T! w# f* m- W) q+ [, Z - DROP_RATE = 500000
2 G4 E$ q# s& L+ B - & `. o+ |' B' `. x5 ~- f
- WORLD_MAP_ITEM_ID = 1665
+ S( x) `% A1 w1 e! b; v6 `: F
* f& n$ r2 S/ h- def getCount(st) :
. u6 @& t, P) u0 P - return st.getQuestItemsCount(FANGS_ITEM_ID)" J' R+ w8 u2 C$ V/ I+ J; S: y, [
- ' x1 f0 q. A) W) W! x) D' D8 o) p
- def completed(st) :( @: k4 r% N; Q0 t0 W
- st.setState(COMPLETED)% }' d+ t/ F% G3 ^0 @" P% Z
- st.clearQuestDrops()
# `! K C- J- X/ M- c# }' r - st.takeItems(FANGS_ITEM_ID,-1)% q9 R2 F7 g# ^: e8 f( `0 d$ t
- st.giveItems(WORLD_MAP_ITEM_ID,1)
% a+ e1 K3 W5 N! v% i - st.exitQuest(False), j, P9 u- X0 H$ t: E2 Y. H
- return. { o8 I& _' s1 E) x
/ v# o+ J1 V8 w$ ~- def check(st) :( B; D- I$ Y8 ~0 o
- if getCount(st) >= 4 :1 W# J" t0 ?9 V; ?- p( ^/ s
- completed(st)' Z5 {9 t J: ]1 `5 s. x2 k" P
- return/ {# y+ d( ~$ d; L
- + B8 u5 {& K T1 P( x1 Q9 H1 J
- class Quest (JQuest):2 W. U8 c' _# t e/ C
- 4 y5 ]& ]0 |" s9 w6 [& b* {
- def __init__(self,id,name,descr): JQuest.__init__(self,id,name,descr); P1 L1 I; A7 T
$ V% m8 M0 l9 l& n/ I, q# f7 F- def onEvent (self,event,st):6 V! \( r+ H" i& X! i
- id = st.getState(), g0 F, L7 n. w6 A1 A* f4 ?
- if id == CREATED : st.setState(STARTED)4 N) I& x# {) y" d- \9 {. {: g
- elif id == COMPLETED: pass
! k9 b1 H5 W: a% A& Y: |% D& o7 X) J - elif id == STARTED : check(st)2 ~, F! _8 \3 i# o
- return
3 j2 M! r6 e- ^: A2 s9 d
% o4 P ]& K' M; s7 e' @5 A) U- def onKill (self,npcId,st):& R2 n4 A0 i( H5 |
- if npcId == KELTIR_NPC_ID:
. y+ k# ~7 S" V1 z, V$ R - n = getCount(st)
, ]. A" i( m' u8 S) K0 i5 k1 C- Q - if n == 0:9 P8 i: [+ w$ b- t
- if st.get('chat0') == None :
" x& [( d4 e# g$ p o5 `) b% Q C8 e - st.set("chat0", "true")( k' I9 m: I2 j; N
- return "Chat0.htm"
# I# r- S: ? I+ t7 F$ L - elif n == 1:6 `+ z6 e1 x/ d7 P; H! z
- if st.get('chat1') == None :
$ n/ }% O& l* t4 `, o; {0 B - st.set("chat1", "true")! V, f, d _- d4 a" S" _/ m
- return "Chat1.htm": g3 J3 [6 K. n; r+ _" Y5 D
- elif n >= 4:
% I( R0 \4 E8 \! v; d6 W$ e - return "Chat4.htm"
: D" Y5 r( Z+ L! m7 d0 Z - return "Collect "+str(n)+" of 4 fangs"8 h* ?0 K# e& |2 S
- return
, v4 f Z( K% z; q
2 K% n4 l r) Z3 G& V$ I/ L1 \: b- QUEST = Quest(201, "Tutorial", "Tutorial quest")" L& c6 J* e$ D2 ?% H+ I
- CREATED = State('Start', QUEST)
: _7 `1 V) W z" H$ Z - STARTED = State('Started', QUEST)
/ e; G6 l: j- ^ - COMPLETED = State('Completed', QUEST)4 P: V. H5 T6 d8 h: r
- * W+ H, @2 q6 ~% I7 p+ T
- QUEST.setInitialState(CREATED)7 `# Y6 z8 p+ Z5 D8 E& ?
- QUEST.addStartNpc(7056)6 j% H2 \% I0 O4 S0 T8 _
- QUEST.addStartNpc(7012)
: T: O% A* L' o8 S- v- ]. g& l - QUEST.addStartNpc(7009) M5 E- C) e9 \+ k) u, X
- QUEST.addStartNpc(7011)1 k' E! P& j; u' c
3 _* g% Q9 v. u- STARTED.addQuestDrop(KELTIR_NPC_ID,FANGS_ITEM_ID,DROP_RATE)
- L- S' F; o# q8 m. N - STARTED.addKillId(KELTIR_NPC_ID)
& t! n( K, m% B - STARTED.addTalkId(7056)
% w. D# W w, w) T* Q* V3 f - STARTED.addTalkI d(7012)) J7 r! y3 u2 X- ^- O" S. s
- STARTED.addTalkId(7009)! S$ O }$ @1 s$ v* ?
- STARTED.addTalkId(7011)
Скопировать код
( T- g. v; Y [* A' P5 T* p P X
|