Зарегистрируйтесь сейчас чтобы найти еще больше друзей, и получить полноценный доступ ко всем функциям сайта!
Для просмотра Вам необходимо авторизоваться Если Вы еще не зарегистрированы, перейдите по ссылке:Зарегистрироваться
x
Хроники Interlude
# ]3 U4 n9 f& ^! e& }Сборка L2j
. O! X r4 }8 o" rОбратите внимание: в файле htm стартового NCP обязательно должна быть ссылка на квест:
1 a2 Y; U! w/ V4 @. B: Q- STARTED.addQuestDrop(KELTIR_NPC_ID,FANGS_ITEM_ID,DROP_RATE)
Скопировать код Для этого квеста больше ничего не надо. Все необходимое для корректной работы квеста уже добавили. Вот полный текст квеста:# T$ J9 r( V" ^' \" l. p
& f( I! X8 u) m/ b3 H- if getCount(st) >= 4 :9 G3 \- w. N8 N; L) v9 A8 V* n: i
- completed(st)
( E$ d: @" Z; I: g, Q4 t! a7 o! ` - return
' q5 y3 t5 _% I6 n9 N: a
2 a8 l- M8 `' c) j- class Quest (JQuest):6 u/ [- U' H: i* }) J+ S V0 R
- def __init__(self,id,name,descr): JQuest.__init__(self,id,name,descr)% V5 I: D3 y( i
- def onEvent (self,event,st):
0 @& p0 h+ ~8 w1 S/ g - id = st.getState()1 A$ F9 J9 [# Q, l$ d5 O
- if id == CREATED : st.setState(STARTED)
8 f5 l' t, n ^/ R% ~" T: v. { - elif id == COMPLETED: pass1 c+ Z( t$ R' G! G
- elif id == STARTED : check(st)
4 r$ \ l" Q* @0 X% t - return m P* ~% e1 O# q
9 F7 o7 b p/ n1 _3 h; P5 P- QUEST = Quest(201,"Tutorial", "Tutorial quest")( j" g" C; I4 k' [( l
- CREATED = State('Start', QUEST)
( g) X6 A! T" H$ O8 A - STARTED = State('Started', QUEST)
+ e7 d3 w. Y" i- x1 N; E: t; L5 M$ ` - COMPLETED = State('Completed', QUEST)- L4 p/ \+ {# K. U
- 0 l( b, L% h6 i) u! C- o3 Z
- QUEST.setInitialState(CREATED): i) p( A- q" r$ W4 w/ S" d) L
- QUEST.addStartNpc(7056)* e) X* }+ h9 l Q6 \
- STARTED.addQuestDrop(KELTIR_NPC_ID,FANGS_ITEM_ID,DROP_RATE)
Скопировать код Теперь рассмотрим, как это работает.
B/ {: d& r0 f, w' F9 aИгрок подходит к начальному NCP (в данном случае 7056), нажимает на «Quest». Квест будет создан и состояние квеста перейдет к CREATED и игроку будет показана страничка Start.htm с описанием квеста. Тогда метод onEvent, поле открытия странички Start.htm переведет состояние квеста в STARTED и игроку будет показана страничка Started.htm, где будет опсание того, как найти keltirs и .т.д." F8 j# r7 A3 |$ }: ^
/ g' ]# _; P8 o! _9 L; l' ]' n/ u: K/ |) f f+ |! t
При состоянии STARTED будет зарегистрирован дроп «fangs» при убийстве keltirs. Игрок может вернуться к стартовому NCP и спросить о квесте – метод onEvent будет вызван снова. Если у игрока не хватает необходимого количества предметов, то метод check() не переведет квест в следующее состояние и Started.htm будет показана снова. Но если игрок собрал необходимее количество предметов (в данном случае 4 клыка), то метод check() вызовет метод completed() который переведет квест в новое состояние COMPLETED, заберет все клыки, даст карту мира, т.к. это награда за квест, покажет Completed.htm и завершит квест.
' C/ D/ @* ] _7 S* I* U$ e0 I9 l# K: `, J/ X
3 k- ?4 U" w q$ O
Теперь давайте сделаем наш квест более похожим на то, что он должен из себя представлять.
/ u) _ S, K' x# uПрежде всего у нас есть 3 метода для объявления их в Яве – onTalk, onKill и onEvent. Если методы onTalk и onKill не объявлены, то за них все будет делать метод onEvent, т.е. определять квестовых монстров и вызывать диалоги NCP. Есть примечание, методы onTalk и onKill будут вызывать только диалоги с NCP в зависимости от текущего состояния квеста. Метод onKill будет вызываться только тогда, когда мы убиваем квестового монстра.
2 p" I3 k: i; J5 R
3 S0 U& |. ^' L P! o$ I! z; E! Q" H
Давайте рассмотрим как вызывается метод onKill при убийстве keltir в состоянии квеста STARTED:
' b. A3 L8 X, S* l0 d- STARTED.addKillId(KELTIR_NPC_ID)
Скопировать код и метод onKill в классе Quest:- r1 l4 [" M, o3 h& r/ W" n
- R; {' N" o! T! q2 l" V/ R
- class Quest (JQuest):
& P- g+ }2 A$ I- i - ...: |9 H5 e: Y- x7 ]
- def onKill (self,npcId,st):
4 `3 q8 `, m5 Z- n; x( J - if npcId == KELTIR_NPC_ID:
3 c" T( |6 [0 W - n = getCount(st)- O+ s" W6 c" a! ^; R+ _1 z& Z
- if n == 0:
( t5 l- u) p, u2 A2 f - return "Chat0.htm"$ e4 y s. U3 N6 Y
- elif n == 1:5 C& X; y1 M0 H
- return "Chat1.htm"
" j7 I1 F, v4 z - elif n >= 4:
6 I8 j. c+ ^: U1 x6 U - return "Chat4.htm"8 o# [: l& D9 s) ]3 y! ^
- return "Collected "+str(n)+" of 4 fangs"% z0 |# _( q) j
- return
Скопировать код Метод onKill (а так же метод onTalk) имеет следующие параметры:
l/ E2 x2 v+ g7 P+ k0 k! Y, u& a- D6 ^ t |
( f! B1 U1 r9 s) P- _/ M8 c$ C• self – квест
3 t' Q7 ]0 ]8 i• npcId – ID NCP, которого мы должны убивать (если это метод onTalk, то ID того NCP, с которым мы должны поговорить).4 V4 F: k; N' Z8 E6 _5 z
• st – текущее состояние игрока., e# c1 [! Y, G; K! |$ t( D
* _, l3 h1 r5 C% Z
, j+ H" ?1 w& _4 T$ A0 qВ этом методе мы проверяем и отмечаем, является ли убитый NCP keltir’ом. В основном эта проверка не нужна, т.к. у нас только KELTIR_NPC_ID.
- Q5 e( {8 ]! r! N5 V% q2 Z; M/ c( ^& N" ?
2 S9 q0 ^# B7 Z: p6 S' R6 j/ O
Затем проверяем количество предметов (в данном случае количество клыков), и если их вообще нет, то возвращаем строку "Chat0.htm", если только один предмет, то возвращаем строку "Chat1.htm", если же предметов 4 или больше, то "Chat4.htm". Если строка возвращена из методов onEvent, onKill или onTalk, то сервер покажет соответствующие htm. В Chat0.htm может иметь следующий текст: «Вы не имеете ни одного клыка, возвращайтесь позже, когда соберете 4 штуки и бла, бла, бла…», в Chat1.htm может быть следующий текст: «У Вас всего 1 клык, по этому соберите еще…». В Chat4.htm – «Вы собрали необходимое количество предметов, возвращайтесь к вашему тренеру, что бы завершить квест…»8 h+ ?3 I0 v4 I
% b* {& o- @$ k1 a
8 d. k# q, v9 d, IПримечание: если в строка return начинается с "<html>", то будет показана страничка html с текстом, который стоит далее. Так вместо:
. s- { o- w; R9 ?* ureturn "Chat4.htm"
0 s0 i" a2 `# v9 B9 P
# A* o# |' @5 |% X! d, x6 [2 i- R3 ^" a) y; `( Z! |
можно поставить:
0 }; y; u+ D0 q( r$ q- return "<html><body>Return to your trainer to complete the quest</body></html>"
Скопировать код Так же если строка заканчивается без .htm или в начале нет <html>, то текст будет выведен, как системное сообщение в окне чата. В нашем случае мы сделаем так, что бы при каждом убийстве keltik выводилось системное сообщение: «Собрано N из 4-х клыков».- M' J b/ _5 t8 ]5 K
6 {7 ?! a1 A4 N, v; a; R
& K6 J6 t; V: b9 o5 |
Наш код для onKill имеет один недостаток. Он будет постоянно показывать Chat0.htm, Chat1.htm и Chat4.htm, нам же необходимо, что бы Chat0.htm и Chat1.htm показывались только один раз. Как нам это сделать? С помощью переменных.1 O. ~9 m$ p( F3 n& y1 L- X
# V9 c* x1 W; _
+ E. P! t0 m6 M, L# EВ каждом квесте строки могут храниться с помощью переменных. Эти переменные сохраняются в Вашей БД. В каждом методе мы можем назначить, прочитать и удалить переменные. Давайте изменим метод onKill, так что бы каждый диалог вызывался только один раз., {1 D; |; Q8 G% s u7 @$ i
- def onKill (self,npcId,st):% J* U# q+ `- s& d
- if npcId == KELTIR_NPC_ID:
7 N: ^/ \! D: V/ U0 W - n = getCount(st)
# @7 \3 ?8 @8 g' T- @4 ^; P7 W3 M - if n == 0:+ U: N- M& {! P( K" g6 L$ O
- if st.get('chat0') == None :
& p. J a2 f& u) I - st.set("chat0", "true")" J/ H2 B2 g% h; T: x7 t5 a
- return "Chat0.htm"
& v+ L0 b1 J3 v/ S' l - elif n == 1:
& i0 i) K3 u- Y2 ], {7 K' i - if st.get('chat1') == None :+ d9 c* _1 |% b4 d
- st.set("chat1", "true")
; j2 C' j* K3 {. h& s - return "Chat1.htm"
5 H& E: M! `+ d3 C. r' Y, h - elif n >= 4:% |9 `( p8 f% Q
- return "Chat4.htm"
5 [. _9 m3 x! X6 n - return "Collected "+str(n)+" of 4 fangs", p0 U' I+ h2 k7 `
- return
Скопировать код Если у игрока нет клыков (n=0), то мы получаем занчение переменной 'chat0'. Когда метод onKill вызван в первый раз, то пока ни каких переменных не имеется и python возвращает значение None. В этом случае объявляется переменная и показывается диалог Chat0.htm. Когда мы убиваем keltir, но не получаем с него клык, функция st.get('chat0') возвращает строку true, а не None. И во второй раз окно с Chat0.htm не появится, но в окне чата появится строчка «Collected 0 of 4 fangs». По тому же принципу сделано и с Chat1.htm.
- o) l% F/ s9 |5 R
+ t! c k9 G" E
* l% m; x: R9 ZВот конечный рабочий вариант квеста:+ O" b7 [ k1 N; X# o# y' y
- import sys
. U; f/ p7 I6 D9 M4 s6 \ - from net.sf.l2j.gameserver.model.quest import State
5 y0 B) p0 u6 S. B) u - from net.sf.l2j.gameserver.model.quest import QuestState0 W/ x$ V- o; V; g, x! c
- from net.sf.l2j.gameserver.model.quest.jython import QuestJython as JQuest/ C* ?+ J- f7 B8 m |" D
- ) ?9 v) ?+ L) u0 x3 Y$ T* c
- KELTIR_NPC_ID = 12082
* a$ _3 |/ @- M6 W" z( g7 Z - FANGS_ITEM_ID = 1859- i0 o% L1 {) M6 g
- DROP_RATE = 500000, r9 G0 J8 g3 \0 `9 T
- ! [+ ]: A3 j0 U1 ~% S6 K2 [
- WORLD_MAP_ITEM_ID = 1665, t$ g" G) d; i% Q0 y! C1 _; H( K
- ) I! S; j3 |' P% x; j
- def getCount(st) :
* Q) a3 T, ^- h6 R3 e$ U6 ]! o5 C - return st.getQuestItemsCount(FANGS_ITEM_ID)
9 [6 u4 o0 x& F8 c( c; H! {. E
2 v% L! K9 m: v- def completed(st) :
) R0 t) ?9 y \3 K6 ] - st.setState(COMPLETED)
- [7 B) ]6 S# A" y% x - st.clearQuestDrops()
. u5 I% s4 K8 v: x/ O+ j - st.takeItems(FANGS_ITEM_ID,-1), r: W- {( @/ E+ R+ K
- st.giveItems(WORLD_MAP_ITEM_ID,1)
6 c. Y. q' A5 A' A3 L; l3 W& ~ - st.exitQuest(False)1 Z2 j& ?; m: T; A2 A4 o/ |# ]
- return9 x6 P5 B0 O# d- l5 A) |2 {" F8 Z
- 3 @# q1 y$ @1 N$ G9 K# F
- def check(st) :
O! y! ^3 ~) G1 r i3 z - if getCount(st) >= 4 :
. p% O; B8 o( \& q2 O - completed(st)" W' E" m1 J' N- @
- return
1 D# S7 k0 q; i6 `/ c8 t( {$ O3 S5 @
9 ?. v9 p: o+ e! y& o9 e- class Quest (JQuest):' t: h2 X* Q3 ?1 Z! {
9 g4 q% D; C5 u# o$ S- def __init__(self,id,name,descr): JQuest.__init__(self,id,name,descr)6 Y! R/ O# ^! F4 r
' K; U/ d5 f- Z9 P$ D5 `- def onEvent (self,event,st):; c- F i# N8 r+ I8 c4 H8 g/ J
- id = st.getState()
( ]( n% U8 _$ W - if id == CREATED : st.setState(STARTED)
6 ?1 U6 V6 g, [ - elif id == COMPLETED: pass+ w) _ ]5 C/ G% @: x/ |
- elif id == STARTED : check(st)
) t* D/ p/ r, \0 s - return7 e$ l& U4 N8 Y! a( s i3 r
- / ~6 ` ^5 t& |: H6 [) T& C1 j: L
- def onKill (self,npcId,st):# p+ J' n7 w0 Y% V9 |6 s
- if npcId == KELTIR_NPC_ID:. f1 m# |: l+ @0 c r B% L3 k
- n = getCount(st)
% \7 x- _- p' O5 k; {8 n5 S - if n == 0:; ?: t; Q5 n( Q& s
- if st.get('chat0') == None :" T* T5 D6 p# ~8 z: I/ z9 Y
- st.set("chat0", "true")9 @1 W0 [5 b9 v3 b" l
- return "Chat0.htm"
5 T& u0 s8 U1 `( R5 T% v - elif n == 1:% {: R) ~1 M9 Q! \! e/ Z
- if st.get('chat1') == None :
" U8 J* }/ B( p( ?9 \# J - st.set("chat1", "true")
! {' E& H/ _" D5 x, L, g, ^ - return "Chat1.htm"& c3 v0 x4 k9 z. [1 V5 K6 x. N, I; [- t
- elif n >= 4:, F+ v6 L3 F: b- R7 J8 f& H' j9 [$ M# B
- return "Chat4.htm"7 ] ]7 f; S( D: `; e' `
- return "Collect "+str(n)+" of 4 fangs"
: h6 K. ]- t( Z" T7 a3 G/ _/ y, f - return
8 q: ]% l3 C) a! P/ E+ ~% {
( b; {/ M6 | N0 {, C- A- QUEST = Quest(201, "Tutorial", "Tutorial quest")
# L0 k0 g( h5 ?$ S - CREATED = State('Start', QUEST)- |0 z2 g! \- m2 N/ j7 e- W
- STARTED = State('Started', QUEST)
+ s: @, m3 e, r/ C - COMPLETED = State('Completed', QUEST)' ~; {3 ^4 B2 P
- . h3 K) W a$ u9 g' P, t
- QUEST.setInitialState(CREATED)- f& O, L6 {: k8 v
- QUEST.addStartNpc(7056)
0 w1 o& R8 w3 @# y" l! M - QUEST.addStartNpc(7012)
3 X( B3 r u* y" n - QUEST.addStartNpc(7009)
/ R( r5 V# j( @& X7 l - QUEST.addStartNpc(7011)5 b9 Y0 [; c6 i% [: H _2 G* X
. |6 s; w3 m) H: [- STARTED.addQuestDrop(KELTIR_NPC_ID,FANGS_ITEM_ID,DROP_RATE)
* B; h( F4 u3 F! l7 D' ^9 R - STARTED.addKillId(KELTIR_NPC_ID); M( H. [4 D R T6 P7 [
- STARTED.addTalkId(7056)
% X8 J- i% n7 I* B: q - STARTED.addTalkI d(7012)$ `, X& `5 O1 m; H9 a% |6 q
- STARTED.addTalkId(7009)
+ m4 g1 h" u" g3 | - STARTED.addTalkId(7011)
Скопировать код ) A3 C, a8 j1 T# v6 l0 }8 m( h
: d$ w6 D' J5 N6 x4 I |