Зарегистрируйтесь сейчас чтобы найти еще больше друзей, и получить полноценный доступ ко всем функциям сайта!
Для просмотра Вам необходимо авторизоваться Если Вы еще не зарегистрированы, перейдите по ссылке:Зарегистрироваться
x
Хроники Interlude
) R) @: I, {; c) @4 k$ I# cСборка L2j9 ^5 j/ h$ S* C
Обратите внимание: в файле htm стартового NCP обязательно должна быть ссылка на квест:. A2 b6 ~& l' b% Y
- STARTED.addQuestDrop(KELTIR_NPC_ID,FANGS_ITEM_ID,DROP_RATE)
Скопировать код Для этого квеста больше ничего не надо. Все необходимое для корректной работы квеста уже добавили. Вот полный текст квеста:
; O7 l. l3 |% e, B: w
/ w/ N5 o1 ?# v) b' [/ D1 ?! o7 ]% Q- if getCount(st) >= 4 :) R' V/ A2 l5 Q, c5 ^: L& l
- completed(st)
5 b9 h! F( \, s) C$ G2 t, z6 K - return
) E p9 H7 U5 F O8 }, v- j
$ d* h. X9 f7 C& d* G6 ?- class Quest (JQuest):& g7 @, p/ }+ O& C1 o' S
- def __init__(self,id,name,descr): JQuest.__init__(self,id,name,descr)) u* M( g2 p; g* j( }: s
- def onEvent (self,event,st):
3 s$ }2 s. w z+ O" ^( P - id = st.getState()
. @' C' X. d9 M: J0 ^; m - if id == CREATED : st.setState(STARTED): |9 |+ ?+ h& j2 w+ u
- elif id == COMPLETED: pass
i; }" x! [; ]1 I - elif id == STARTED : check(st)$ S% s1 s% s# X: C6 J7 H/ V
- return0 E3 _; O x, E$ W- Z
- + H# s6 K `' B( ]- A& j7 A
- QUEST = Quest(201,"Tutorial", "Tutorial quest")! S: N2 o; v0 [2 U0 o
- CREATED = State('Start', QUEST)7 @+ ] y H1 u$ R: \" v5 X$ Z! \
- STARTED = State('Started', QUEST)
* g9 E: G+ ~) t6 P - COMPLETED = State('Completed', QUEST)3 s4 ]5 H) }& S' j( }8 i
% s* h7 S7 [7 o- }8 ]# ^* P7 H! J- QUEST.setInitialState(CREATED)' n8 ^$ V1 k- s7 P# M3 Q, u3 |; A
- QUEST.addStartNpc(7056)
& p& A* R+ F2 U' a- Y! H - STARTED.addQuestDrop(KELTIR_NPC_ID,FANGS_ITEM_ID,DROP_RATE)
Скопировать код Теперь рассмотрим, как это работает.
7 T5 ?( l/ U7 L2 a2 hИгрок подходит к начальному NCP (в данном случае 7056), нажимает на «Quest». Квест будет создан и состояние квеста перейдет к CREATED и игроку будет показана страничка Start.htm с описанием квеста. Тогда метод onEvent, поле открытия странички Start.htm переведет состояние квеста в STARTED и игроку будет показана страничка Started.htm, где будет опсание того, как найти keltirs и .т.д.
/ s& S" Z7 @% O/ ?
9 i: T3 F8 `5 x5 d3 Q0 D! w' W" L3 C A
При состоянии STARTED будет зарегистрирован дроп «fangs» при убийстве keltirs. Игрок может вернуться к стартовому NCP и спросить о квесте – метод onEvent будет вызван снова. Если у игрока не хватает необходимого количества предметов, то метод check() не переведет квест в следующее состояние и Started.htm будет показана снова. Но если игрок собрал необходимее количество предметов (в данном случае 4 клыка), то метод check() вызовет метод completed() который переведет квест в новое состояние COMPLETED, заберет все клыки, даст карту мира, т.к. это награда за квест, покажет Completed.htm и завершит квест.
" O6 z8 D7 I! b& M1 H' m1 e7 a0 T6 b+ B4 M M4 n6 }0 b
4 C' [; r; N7 [Теперь давайте сделаем наш квест более похожим на то, что он должен из себя представлять.. {# M p1 o; Z7 h
Прежде всего у нас есть 3 метода для объявления их в Яве – onTalk, onKill и onEvent. Если методы onTalk и onKill не объявлены, то за них все будет делать метод onEvent, т.е. определять квестовых монстров и вызывать диалоги NCP. Есть примечание, методы onTalk и onKill будут вызывать только диалоги с NCP в зависимости от текущего состояния квеста. Метод onKill будет вызываться только тогда, когда мы убиваем квестового монстра.6 \+ V1 N! T9 v& z! m7 N7 x9 j% b) k0 G8 f
( r' W# q, W% E( ?0 ]/ w2 d: s. m$ A
Давайте рассмотрим как вызывается метод onKill при убийстве keltir в состоянии квеста STARTED:
' k/ i6 F, Y' Z1 d- STARTED.addKillId(KELTIR_NPC_ID)
Скопировать код и метод onKill в классе Quest:
# `# ~! e' \: i' Q. `. M; V+ {) @- a" D0 p
- class Quest (JQuest):" U5 @: ? B) k8 l, @) I
- ...
+ D, {: d. Z! d3 D& w$ B1 ` - def onKill (self,npcId,st): m8 p6 ^$ x8 [5 `2 y4 I
- if npcId == KELTIR_NPC_ID:( t, Z/ w4 m* e2 i; g) h: P' W, V d
- n = getCount(st)
! I% E: l. a/ }2 ?! i( H6 @ - if n == 0:6 t" v# f' r' O D$ H/ K
- return "Chat0.htm"9 G4 n3 O2 H7 j! v2 C
- elif n == 1:
* G, \8 M. u/ u8 q1 q$ g% l - return "Chat1.htm"
+ g/ r# k, Q1 J8 u - elif n >= 4:% `1 {( R Z# O; A, U& k* L
- return "Chat4.htm"# U8 d5 m5 g* `. }; ]$ g
- return "Collected "+str(n)+" of 4 fangs"+ F- v4 l. C8 n6 U" c4 d
- return
Скопировать код Метод onKill (а так же метод onTalk) имеет следующие параметры:0 b/ j3 R: Z! F9 e0 }! X
4 l2 K% y" z* @8 n" D% [
* K) U) |( f/ p- ~ Y5 y$ I) v• self – квест: _2 X9 ^0 b: F( c* V) B' N0 v5 L
• npcId – ID NCP, которого мы должны убивать (если это метод onTalk, то ID того NCP, с которым мы должны поговорить).8 O- Y8 l( a$ X$ }
• st – текущее состояние игрока.( q* ]% R% C/ D, t& l
) L- n5 s: R: G9 l4 Q2 {; C4 ]5 }2 D2 D3 a
В этом методе мы проверяем и отмечаем, является ли убитый NCP keltir’ом. В основном эта проверка не нужна, т.к. у нас только KELTIR_NPC_ID.
5 X, _/ | T% e U3 _' H5 q1 c* K, |( i z$ f3 b( U9 }% L# M
) \( [ d, |" p9 g F0 TЗатем проверяем количество предметов (в данном случае количество клыков), и если их вообще нет, то возвращаем строку "Chat0.htm", если только один предмет, то возвращаем строку "Chat1.htm", если же предметов 4 или больше, то "Chat4.htm". Если строка возвращена из методов onEvent, onKill или onTalk, то сервер покажет соответствующие htm. В Chat0.htm может иметь следующий текст: «Вы не имеете ни одного клыка, возвращайтесь позже, когда соберете 4 штуки и бла, бла, бла…», в Chat1.htm может быть следующий текст: «У Вас всего 1 клык, по этому соберите еще…». В Chat4.htm – «Вы собрали необходимое количество предметов, возвращайтесь к вашему тренеру, что бы завершить квест…»
! C5 d" l! k* e& K) g+ r# Z" R5 I: G1 w6 z* @: `
( H$ e8 `$ W+ j$ `0 Y) s7 k* o
Примечание: если в строка return начинается с "<html>", то будет показана страничка html с текстом, который стоит далее. Так вместо:
1 `8 i( O3 ?6 nreturn "Chat4.htm"
$ E9 ~+ ]0 m& y4 m3 [
) i8 l% C. R; g" c
3 ~! a5 ^, S/ O7 hможно поставить:( \1 W9 t) f0 }1 V9 ~% X: t
- return "<html><body>Return to your trainer to complete the quest</body></html>"
Скопировать код Так же если строка заканчивается без .htm или в начале нет <html>, то текст будет выведен, как системное сообщение в окне чата. В нашем случае мы сделаем так, что бы при каждом убийстве keltik выводилось системное сообщение: «Собрано N из 4-х клыков».
2 Q$ ?. x. {' Q8 n+ W8 x% t% e2 \: T5 Q/ S! I
P, a/ D* v# SНаш код для onKill имеет один недостаток. Он будет постоянно показывать Chat0.htm, Chat1.htm и Chat4.htm, нам же необходимо, что бы Chat0.htm и Chat1.htm показывались только один раз. Как нам это сделать? С помощью переменных.
6 N. L4 Y' Y+ s3 m% O
6 b: W; {" m- y, ^7 I4 z3 u" `- s7 x6 J
В каждом квесте строки могут храниться с помощью переменных. Эти переменные сохраняются в Вашей БД. В каждом методе мы можем назначить, прочитать и удалить переменные. Давайте изменим метод onKill, так что бы каждый диалог вызывался только один раз.1 t6 ?, ~7 d! |, G
- def onKill (self,npcId,st):
- r: O2 p3 A! |7 r! w3 b0 C( p - if npcId == KELTIR_NPC_ID:
2 E$ e2 [4 q% D* t - n = getCount(st)
`! V) O' I5 N& `" p! {4 c- z - if n == 0:
; h& `* E) w. t# }& w& f% l - if st.get('chat0') == None :
/ I! Z, Y: K* R; | - st.set("chat0", "true")! w; @7 a% V( f* V. Q. F6 _
- return "Chat0.htm"
3 n6 y+ u# e+ B. u$ s - elif n == 1:( V$ K( i* W) d" `
- if st.get('chat1') == None :
% _/ S2 A" A9 w( ^+ v - st.set("chat1", "true")# W. R' S+ \: I5 g* r. ~
- return "Chat1.htm"; o7 B1 a2 }2 ]- F! }' ]
- elif n >= 4:4 Q- L3 f0 u/ x, l0 @# V9 ~
- return "Chat4.htm"/ c1 } ]% M* \& }
- return "Collected "+str(n)+" of 4 fangs"% q& \3 }7 W; N, W! a' ~
- return
Скопировать код Если у игрока нет клыков (n=0), то мы получаем занчение переменной 'chat0'. Когда метод onKill вызван в первый раз, то пока ни каких переменных не имеется и python возвращает значение None. В этом случае объявляется переменная и показывается диалог Chat0.htm. Когда мы убиваем keltir, но не получаем с него клык, функция st.get('chat0') возвращает строку true, а не None. И во второй раз окно с Chat0.htm не появится, но в окне чата появится строчка «Collected 0 of 4 fangs». По тому же принципу сделано и с Chat1.htm.
( G: N5 S; n: }) H
# p1 j, Z- ?) p3 x2 u; b' {$ m+ S+ E5 H) |2 j1 |: g' ]: P# C b
Вот конечный рабочий вариант квеста:
: J' ?7 C% V" e* n- import sys
5 @+ C9 c* F4 ~5 f, Z/ i+ e$ x - from net.sf.l2j.gameserver.model.quest import State4 ]0 z! P8 r: J2 o
- from net.sf.l2j.gameserver.model.quest import QuestState
; U/ k8 U: ^3 l* w! L - from net.sf.l2j.gameserver.model.quest.jython import QuestJython as JQuest- {" B+ ~( e- [ u4 a
- - g% v# x0 ]( @3 A% J* d
- KELTIR_NPC_ID = 12082
8 b) E8 R# z4 q! ~/ J - FANGS_ITEM_ID = 1859
! _' K% e+ M4 `3 U' @1 S1 \8 { - DROP_RATE = 500000* h0 Y+ @( o4 q* j" E
, x- [3 [. S9 R5 H- a+ [1 L# R* ~- WORLD_MAP_ITEM_ID = 1665
6 ^) D. |0 }9 d3 p
9 c1 \; ]3 T+ }8 I2 A$ {2 r" X- def getCount(st) :
k* C0 v, o# E1 r$ j - return st.getQuestItemsCount(FANGS_ITEM_ID); C7 Y9 e2 t. ^' t0 v
- 4 t+ l8 g( \- t* R# l. D" I# o
- def completed(st) :# Y+ V) c% c3 ^8 U& p9 {! U
- st.setState(COMPLETED)
1 y4 V/ M5 k; m+ _ - st.clearQuestDrops()
3 Z+ y+ u; \' z* n - st.takeItems(FANGS_ITEM_ID,-1)2 X. g2 c2 }9 E" I/ _
- st.giveItems(WORLD_MAP_ITEM_ID,1)
8 Y) W6 j' U7 z9 I+ Q) u. r! o* [ - st.exitQuest(False)2 ?8 s, E2 T4 w' i0 d+ v
- return
) j( B0 g8 @- l" ~8 x - + d# @3 t* U4 R7 |+ x9 F, \, J
- def check(st) :9 }6 f x W; { f
- if getCount(st) >= 4 :. q! `% [" C& y5 P6 z% E
- completed(st)
4 ~0 w2 l9 L+ E- Y7 |0 Z( Y0 r - return
. t8 j3 E( |. O! {9 S0 W. H
, O6 g+ i4 s3 R& S: U. n: Y- class Quest (JQuest):3 Q: T" k" h g% P
& }8 L0 y+ X: J! [, ]' g* L- def __init__(self,id,name,descr): JQuest.__init__(self,id,name,descr)
& Q* M- M' U+ r& A/ W; x4 j/ W
+ Q& A- a z6 |/ ^0 Y, _2 o' {- def onEvent (self,event,st):- i4 A( b. s" ]7 D9 @9 L( U O, _
- id = st.getState()
: s) b+ D+ u% f. | - if id == CREATED : st.setState(STARTED). R" w- R1 B$ Y% K9 P
- elif id == COMPLETED: pass
/ Q- l; m( _/ J' f3 y' d; _ - elif id == STARTED : check(st)/ G7 e- o# b# ^1 f
- return
7 j! \( S* P$ x+ l' u/ l - 2 e8 S w4 _8 M! |! ^8 G9 g1 K
- def onKill (self,npcId,st):
8 R7 ?( f: |: g: Q4 @, ^/ \8 P( P- H - if npcId == KELTIR_NPC_ID:
0 t- m. `7 {( V4 \2 v( E8 c* i - n = getCount(st)
: Y2 z% p& `$ s, a* N1 W. w8 r - if n == 0:! f% h! s8 a* F. u3 R
- if st.get('chat0') == None :
( h! N4 L/ d. m0 j8 \6 ?: h3 G4 D- M - st.set("chat0", "true")' U, B2 z% f. _4 v3 {
- return "Chat0.htm"
: R. K% S: i0 G$ J - elif n == 1:
: S/ w' X/ [- a/ m/ ?' ~ - if st.get('chat1') == None :
! _/ }; ]0 p! f3 \* M8 j - st.set("chat1", "true")( E9 d2 ?# J( O" J; M' u
- return "Chat1.htm"
& l; m& T* a, W! T$ f - elif n >= 4:
- H' X' b5 @! `; _ o. m - return "Chat4.htm"6 @' I$ T! G6 g$ E# ?3 E7 e
- return "Collect "+str(n)+" of 4 fangs"
) Z" D* X: b- Q1 Z. _% Z) s H! ? - return
9 e6 t2 d1 J. h( F5 b! C
4 \. J! C D6 r: A6 p- QUEST = Quest(201, "Tutorial", "Tutorial quest") ]6 Z1 F, q0 x% p6 s) N f
- CREATED = State('Start', QUEST); t0 E2 F1 H% r7 W+ o L/ i
- STARTED = State('Started', QUEST), q& Z. g! `/ m& l
- COMPLETED = State('Completed', QUEST)
2 a' D: W# \, K0 r1 @& y
5 h0 a' p5 ~3 x6 S3 A2 n1 \- QUEST.setInitialState(CREATED)' w& ~% ]& k" }
- QUEST.addStartNpc(7056)3 A3 T8 o" W- U# a# F
- QUEST.addStartNpc(7012)
: B! }& @( B3 O3 \# e - QUEST.addStartNpc(7009)
6 `9 s( S) n O - QUEST.addStartNpc(7011)' p0 K: O c$ l# ^" H
( I& v3 A+ Y2 g- STARTED.addQuestDrop(KELTIR_NPC_ID,FANGS_ITEM_ID,DROP_RATE)
% m- i: m: r* r - STARTED.addKillId(KELTIR_NPC_ID)
9 j2 ]5 P! _9 R- p/ ] - STARTED.addTalkId(7056)
: c) v0 M0 j' [ s& c; H - STARTED.addTalkI d(7012)
+ U3 ^' c/ L2 D" N+ J - STARTED.addTalkId(7009)
6 @6 _4 |$ o0 b1 f* b) w/ W - STARTED.addTalkId(7011)
Скопировать код
& X9 b N: ?4 `7 s! ?7 M+ {5 \; V5 K+ Y
|