Зарегистрируйтесь сейчас чтобы найти еще больше друзей, и получить полноценный доступ ко всем функциям сайта!
Для просмотра Вам необходимо авторизоваться Если Вы еще не зарегистрированы, перейдите по ссылке:Зарегистрироваться
x
Хроники Interlude8 b/ Z7 _3 V0 t
Сборка L2j4 H6 c2 b& X1 {& p$ N7 \
Обратите внимание: в файле htm стартового NCP обязательно должна быть ссылка на квест:* w9 a o# A3 ^ E6 f) d3 l N
- STARTED.addQuestDrop(KELTIR_NPC_ID,FANGS_ITEM_ID,DROP_RATE)
Скопировать код Для этого квеста больше ничего не надо. Все необходимое для корректной работы квеста уже добавили. Вот полный текст квеста:# P0 Y0 n" _0 Q2 Z4 E9 }$ G
1 l) B* D8 B$ L3 V- if getCount(st) >= 4 :
f8 j0 f$ ^, K$ p2 a" i& w - completed(st)
; ^. B$ l# @! @0 K0 J1 b - return; e. s/ n4 F, N4 P5 x- @8 x1 z
- 6 ^3 s: W: Z* w: M$ S- Q4 r
- class Quest (JQuest):
o V3 z; f& r$ m/ L9 _ - def __init__(self,id,name,descr): JQuest.__init__(self,id,name,descr)
- x: N5 J0 ?, W - def onEvent (self,event,st):
2 f, I8 w% f9 x- y) u7 O5 C3 y - id = st.getState()
4 |+ |# \) s9 q, X$ h - if id == CREATED : st.setState(STARTED)
" d+ i3 @# _# X - elif id == COMPLETED: pass
4 m. D( U" i: @8 v: ~8 C6 w U/ D/ E - elif id == STARTED : check(st)
7 f! t% z8 a; ]9 c - return
- j: [ W; k4 n" C& x. e
+ _0 |& D" C/ w! ^6 s# _" S- QUEST = Quest(201,"Tutorial", "Tutorial quest"). f4 G1 J& w" V
- CREATED = State('Start', QUEST)
8 n& V9 i& ]& m1 k - STARTED = State('Started', QUEST)
' g$ M, W3 i! h8 k( Q - COMPLETED = State('Completed', QUEST)
) H9 @" D, r/ w$ K
: b8 b% K5 Q9 x {# T- QUEST.setInitialState(CREATED)$ s; [1 ]' @0 H) M) T. {) ~. \
- QUEST.addStartNpc(7056)
1 g* o" N" Z) | }' w) |* a - STARTED.addQuestDrop(KELTIR_NPC_ID,FANGS_ITEM_ID,DROP_RATE)
Скопировать код Теперь рассмотрим, как это работает.
6 K, k2 ? E$ D; rИгрок подходит к начальному NCP (в данном случае 7056), нажимает на «Quest». Квест будет создан и состояние квеста перейдет к CREATED и игроку будет показана страничка Start.htm с описанием квеста. Тогда метод onEvent, поле открытия странички Start.htm переведет состояние квеста в STARTED и игроку будет показана страничка Started.htm, где будет опсание того, как найти keltirs и .т.д.
! S8 Q4 [0 I( q, p
* @$ E3 a$ t7 L: q5 Y1 ]2 F( d \# K. n1 W
При состоянии STARTED будет зарегистрирован дроп «fangs» при убийстве keltirs. Игрок может вернуться к стартовому NCP и спросить о квесте – метод onEvent будет вызван снова. Если у игрока не хватает необходимого количества предметов, то метод check() не переведет квест в следующее состояние и Started.htm будет показана снова. Но если игрок собрал необходимее количество предметов (в данном случае 4 клыка), то метод check() вызовет метод completed() который переведет квест в новое состояние COMPLETED, заберет все клыки, даст карту мира, т.к. это награда за квест, покажет Completed.htm и завершит квест.% w/ h7 C$ ~1 N0 p
/ h Y9 D! _ W4 V/ G
3 _! w# u, T6 R$ X( ]4 _9 x6 h8 r0 oТеперь давайте сделаем наш квест более похожим на то, что он должен из себя представлять.4 j* R" L! H+ j1 ~0 ~% c* k
Прежде всего у нас есть 3 метода для объявления их в Яве – onTalk, onKill и onEvent. Если методы onTalk и onKill не объявлены, то за них все будет делать метод onEvent, т.е. определять квестовых монстров и вызывать диалоги NCP. Есть примечание, методы onTalk и onKill будут вызывать только диалоги с NCP в зависимости от текущего состояния квеста. Метод onKill будет вызываться только тогда, когда мы убиваем квестового монстра.- F. M) U# A$ l% Z7 p
$ E4 Q/ R5 n& }* P" E5 I
9 y5 g9 V. m/ mДавайте рассмотрим как вызывается метод onKill при убийстве keltir в состоянии квеста STARTED:
! R F; b, ~, {4 \- STARTED.addKillId(KELTIR_NPC_ID)
Скопировать код и метод onKill в классе Quest:, ^. |+ ?9 j8 G1 g+ Q7 y! U9 c# T
$ c* A8 \$ B) Z
- class Quest (JQuest):
; f; g$ {/ I3 w6 ^# ` - ...
" W0 o( M: W$ ]2 e m - def onKill (self,npcId,st):1 Q( \& \1 B' V0 `4 ~
- if npcId == KELTIR_NPC_ID:
) T+ ^8 \0 e( j& |. N - n = getCount(st)) W9 j; `/ S7 m
- if n == 0:1 }- P1 a% l9 x9 Z) v5 R9 T
- return "Chat0.htm"
9 A: p# z5 S% E' i6 f& `9 Y4 {, x - elif n == 1:
/ `# ]9 P% T4 `( a! E5 B - return "Chat1.htm"
w$ }1 N0 h% ]' H - elif n >= 4:
. O0 o$ |; J( }) i5 |/ h4 J - return "Chat4.htm"
/ `0 y3 s' j! i6 S5 N1 T - return "Collected "+str(n)+" of 4 fangs"1 g1 ~: ~4 B+ ^, ]4 z% T- Z
- return
Скопировать код Метод onKill (а так же метод onTalk) имеет следующие параметры:% u) v. a7 J# V
# f9 \) R8 t% a5 Y0 ?5 ~+ E' C
4 v+ @) ?9 z* ]" d% f' x/ B• self – квест
7 K2 F' w# N% K' U4 I i• npcId – ID NCP, которого мы должны убивать (если это метод onTalk, то ID того NCP, с которым мы должны поговорить).
9 Q7 H- x' X5 f6 @) ~• st – текущее состояние игрока.8 Z( R! p$ I( m [% _- B* y, A
9 n+ Y5 D& r# c1 B* E9 B8 _6 _! }1 J+ h/ V
В этом методе мы проверяем и отмечаем, является ли убитый NCP keltir’ом. В основном эта проверка не нужна, т.к. у нас только KELTIR_NPC_ID.& S+ }, {* P, K \2 m1 X
, k( o* o$ M* D
$ ]/ ]# \) w+ G% s
Затем проверяем количество предметов (в данном случае количество клыков), и если их вообще нет, то возвращаем строку "Chat0.htm", если только один предмет, то возвращаем строку "Chat1.htm", если же предметов 4 или больше, то "Chat4.htm". Если строка возвращена из методов onEvent, onKill или onTalk, то сервер покажет соответствующие htm. В Chat0.htm может иметь следующий текст: «Вы не имеете ни одного клыка, возвращайтесь позже, когда соберете 4 штуки и бла, бла, бла…», в Chat1.htm может быть следующий текст: «У Вас всего 1 клык, по этому соберите еще…». В Chat4.htm – «Вы собрали необходимое количество предметов, возвращайтесь к вашему тренеру, что бы завершить квест…»
% p3 u3 f! v$ e. G) Q$ n F; D3 B9 e5 ?! `1 U4 y8 _9 t! ]
- J6 {0 Z! g) U
Примечание: если в строка return начинается с "<html>", то будет показана страничка html с текстом, который стоит далее. Так вместо:
# A: w$ z6 o* ~! Z% h: Preturn "Chat4.htm"
3 E& Q/ h! R& p2 w3 Z9 u6 M g- u. q+ q7 }: O$ M9 K9 O# M, c
3 ~8 _9 t5 k$ d- ^можно поставить:9 J, P4 r* y: ^' s4 L/ Q! A& b
- return "<html><body>Return to your trainer to complete the quest</body></html>"
Скопировать код Так же если строка заканчивается без .htm или в начале нет <html>, то текст будет выведен, как системное сообщение в окне чата. В нашем случае мы сделаем так, что бы при каждом убийстве keltik выводилось системное сообщение: «Собрано N из 4-х клыков».
+ ]' V. G0 F1 w5 F) O: `, E z8 A# t. r2 A! `7 b8 z( }
% B6 a% L6 O/ L; e6 @/ ?: ?2 k
Наш код для onKill имеет один недостаток. Он будет постоянно показывать Chat0.htm, Chat1.htm и Chat4.htm, нам же необходимо, что бы Chat0.htm и Chat1.htm показывались только один раз. Как нам это сделать? С помощью переменных.; J' w, }# z9 D1 r( P" A3 _+ S
- U. G2 E" N5 H. f1 Z; G( o. [, ^5 t3 m( l3 @
В каждом квесте строки могут храниться с помощью переменных. Эти переменные сохраняются в Вашей БД. В каждом методе мы можем назначить, прочитать и удалить переменные. Давайте изменим метод onKill, так что бы каждый диалог вызывался только один раз.9 f; j: @ W9 f# @3 x- C) {! n2 z
- def onKill (self,npcId,st):
* ?: x$ _7 `" q4 Y* p4 l9 `8 Y0 c - if npcId == KELTIR_NPC_ID:0 B8 w: l! Y1 I: u
- n = getCount(st)
* F2 Z: G1 W: D% J6 p - if n == 0:
. f) Q' L4 i% g6 ~, r - if st.get('chat0') == None :
6 F' D/ s/ a8 i4 K9 J1 |! N - st.set("chat0", "true")) T$ r/ h. u- y( j. q
- return "Chat0.htm"
% {9 R1 F* O: ?; s - elif n == 1:
' y$ C. U1 W X# v. J - if st.get('chat1') == None :, `5 y/ D2 P3 F, Q' Z
- st.set("chat1", "true")
3 J' Z2 h. W# ?: A6 J6 g - return "Chat1.htm"
- l. ]2 M3 W) U5 b; D - elif n >= 4:# S$ H2 D" n0 `) C: S$ a' ~ ~' \
- return "Chat4.htm"
, J6 I9 ^! L0 {% l4 T: `, z - return "Collected "+str(n)+" of 4 fangs"
/ `; u4 l! w0 R% F - return
Скопировать код Если у игрока нет клыков (n=0), то мы получаем занчение переменной 'chat0'. Когда метод onKill вызван в первый раз, то пока ни каких переменных не имеется и python возвращает значение None. В этом случае объявляется переменная и показывается диалог Chat0.htm. Когда мы убиваем keltir, но не получаем с него клык, функция st.get('chat0') возвращает строку true, а не None. И во второй раз окно с Chat0.htm не появится, но в окне чата появится строчка «Collected 0 of 4 fangs». По тому же принципу сделано и с Chat1.htm.
. i6 V( z; L; [8 H5 v% L" h; b0 f% y: i- M% m
/ f. C D: i) dВот конечный рабочий вариант квеста:& J. C- K% x' u6 A5 o4 p5 C
- import sys
5 e6 F4 }; ?! P4 m6 w; V% A - from net.sf.l2j.gameserver.model.quest import State, P, b9 I+ K* o& l. t# k
- from net.sf.l2j.gameserver.model.quest import QuestState
/ ]; j I; X N4 Y' ]# s1 B: t - from net.sf.l2j.gameserver.model.quest.jython import QuestJython as JQuest9 V+ z/ v2 z% t* {
6 E) m3 k5 {, t9 b% T# Z9 T: L- KELTIR_NPC_ID = 12082
~' a! u8 G, I" K8 r# M7 O - FANGS_ITEM_ID = 1859
3 A, [& \' P) c/ T: D5 S - DROP_RATE = 500000
& d* a2 y! X2 y1 x; v8 y
: @( r' z, k, R- WORLD_MAP_ITEM_ID = 1665
& Z m* ~2 P- r- X4 S$ T; X - ( z9 G. B; j) T/ ]
- def getCount(st) :2 A0 O/ V( w; i. E. c
- return st.getQuestItemsCount(FANGS_ITEM_ID)- \* L: n5 L; T2 K& U
: B n0 R& I" r5 ]% s, b- def completed(st) :' o( T T! p$ Z* X, w
- st.setState(COMPLETED)( C7 K( s0 H8 |) c' v
- st.clearQuestDrops()7 |' a: A0 {+ s+ X
- st.takeItems(FANGS_ITEM_ID,-1)
" H2 O. N. K! S' E. w- A - st.giveItems(WORLD_MAP_ITEM_ID,1) T2 q, ^3 Z' V* X( c
- st.exitQuest(False)
. t' `2 {7 W" L+ H; o' U - return L7 V8 A" |, M- g
- # r' I$ E6 o$ z! x0 P8 Y
- def check(st) :
5 n4 f+ a6 I3 D - if getCount(st) >= 4 :" X1 n; `( d3 [2 N
- completed(st): o9 k3 w( h) P$ V/ c8 W1 W
- return" |, q7 E* ^ r0 X7 P e2 \3 g
) U8 M; R, u6 S- class Quest (JQuest):6 Y" b9 ^" m4 G" \5 e6 ` g5 {, K
- 2 Y3 t7 B$ l2 ~
- def __init__(self,id,name,descr): JQuest.__init__(self,id,name,descr) Z L9 B) I# w$ M& l& ]# _
- 2 D6 K6 f y$ W) N* k5 b* d
- def onEvent (self,event,st):
7 i! g3 T$ d& e# K - id = st.getState(). R& \4 h3 f7 D$ c: E0 z! ?; E
- if id == CREATED : st.setState(STARTED)
' O# F. v2 |* `! p; h" \! Q% P, u; W - elif id == COMPLETED: pass
+ P# J7 S8 L( @ - elif id == STARTED : check(st). t2 |! G6 G$ h8 g
- return
8 t$ @- ]$ s& Z8 V
Z3 X( [+ S) K6 i- J- def onKill (self,npcId,st):
9 V: T" Y1 m2 t - if npcId == KELTIR_NPC_ID:, ?) Z8 M" O8 g. Q( {" W# c9 S
- n = getCount(st)- f$ T% v& V( D# `5 T" M' s# K
- if n == 0:
) l# o+ r& Z3 [$ _( s+ D9 G - if st.get('chat0') == None :; v5 g1 j$ e& j4 n
- st.set("chat0", "true")
@$ M1 V% x( `+ ]1 J - return "Chat0.htm"
% U' O3 h1 }; i; p6 r - elif n == 1: |+ Y: p2 E* Y$ y
- if st.get('chat1') == None :; y) B9 E7 {5 a9 [. @5 B2 S
- st.set("chat1", "true")! m6 _; t q4 B) e$ i" U
- return "Chat1.htm"
. ?( m8 ~ M( @4 L+ D8 ]4 A2 g - elif n >= 4:0 ]5 |8 n4 p& I& j" b
- return "Chat4.htm"
9 _. g; v: h% m1 Y5 h5 B - return "Collect "+str(n)+" of 4 fangs") ]: k* K1 q9 q/ k
- return
z5 t# |1 d2 L3 y - 2 I. U4 s$ t' r# j$ H
- QUEST = Quest(201, "Tutorial", "Tutorial quest")
3 U+ Z& d" M2 n" q! m1 s - CREATED = State('Start', QUEST)" G1 G. g3 E! r6 T$ E! Z
- STARTED = State('Started', QUEST)2 A0 z9 V( c" x7 `' [4 H# C- S
- COMPLETED = State('Completed', QUEST)
6 P) U Z: j7 t" X2 t$ D8 \ - - ~; k$ q& U3 ?0 ?) r) Z7 t
- QUEST.setInitialState(CREATED)! {" I0 c: ?/ k0 d
- QUEST.addStartNpc(7056)/ H, }# A4 L4 M: Z6 _9 D) L- x
- QUEST.addStartNpc(7012)' o, h* {1 q0 G. d
- QUEST.addStartNpc(7009)( U; ~2 r; D W {5 z9 g
- QUEST.addStartNpc(7011)/ u& T9 B' F$ }* R" s# C% H" m
9 L& B$ @% z; a9 |' S. O- STARTED.addQuestDrop(KELTIR_NPC_ID,FANGS_ITEM_ID,DROP_RATE)3 j+ c" p' Z1 V; e$ F$ o' a
- STARTED.addKillId(KELTIR_NPC_ID)) C- R5 x! U# D( m1 s
- STARTED.addTalkId(7056)0 }2 e# E; P0 ?( e H6 s
- STARTED.addTalkI d(7012)6 ^0 A# b" G$ `
- STARTED.addTalkId(7009); ~" \! ~2 D3 J! i+ o& }1 a
- STARTED.addTalkId(7011)
Скопировать код : ]: r# T3 K3 }2 V. s& T3 O3 K
4 e; ~" c- X& p; g* B- |+ z |