Зарегистрируйтесь сейчас чтобы найти еще больше друзей, и получить полноценный доступ ко всем функциям сайта!
Для просмотра Вам необходимо авторизоваться Если Вы еще не зарегистрированы, перейдите по ссылке:Зарегистрироваться
x
Хроники Interlude
! ~) v, \ ?: ?0 y8 f* J. cСборка L2j% n" G; l0 ~7 a6 K% C, \3 ~
Обратите внимание: в файле htm стартового NCP обязательно должна быть ссылка на квест:
% ]" j5 c0 A1 E- STARTED.addQuestDrop(KELTIR_NPC_ID,FANGS_ITEM_ID,DROP_RATE)
Скопировать код Для этого квеста больше ничего не надо. Все необходимое для корректной работы квеста уже добавили. Вот полный текст квеста:1 ^3 k& e$ @4 g* S! e! _# ~ J
9 d) p6 G% F& x" Q+ p- if getCount(st) >= 4 :
7 r- z3 U4 B! j1 }- ~: v' ? - completed(st)
+ q" c+ ~. M' @ - return2 [8 O8 s1 }* O% j4 G, L2 j
. G( J( {+ h3 b0 e6 [6 [) ^- class Quest (JQuest):! D) h9 w8 l- q. V$ W
- def __init__(self,id,name,descr): JQuest.__init__(self,id,name,descr)6 Z4 @$ `, Q x7 F, O1 M0 S
- def onEvent (self,event,st):9 M4 T, W3 m* f
- id = st.getState()) b: P z/ e! N9 L \2 g( Z- I: y
- if id == CREATED : st.setState(STARTED)
# {8 b8 j2 K* d& _ - elif id == COMPLETED: pass0 f' n* ?: c$ U. D$ b- t2 s
- elif id == STARTED : check(st)% ~3 t8 M1 |5 |
- return/ w$ ]7 @6 V* l4 `5 g, e( d# ~
* I1 [4 A' d3 m+ N- QUEST = Quest(201,"Tutorial", "Tutorial quest"). F, F5 U% {' _/ i8 v
- CREATED = State('Start', QUEST)
$ g, r. [" C* c% y" t' M; R - STARTED = State('Started', QUEST)
/ O. p0 D5 m/ U) t - COMPLETED = State('Completed', QUEST)- @3 G0 ?) O z5 [; x0 L& B$ f
- 9 d/ J& L$ U N( D1 o1 z- z7 }
- QUEST.setInitialState(CREATED)
; r ]- p5 H3 p! u# w - QUEST.addStartNpc(7056); H" y2 [. x8 u) K3 k* I5 v3 ~1 L
- STARTED.addQuestDrop(KELTIR_NPC_ID,FANGS_ITEM_ID,DROP_RATE)
Скопировать код Теперь рассмотрим, как это работает.
J4 }; k8 h, @, j( P9 w3 |) [Игрок подходит к начальному NCP (в данном случае 7056), нажимает на «Quest». Квест будет создан и состояние квеста перейдет к CREATED и игроку будет показана страничка Start.htm с описанием квеста. Тогда метод onEvent, поле открытия странички Start.htm переведет состояние квеста в STARTED и игроку будет показана страничка Started.htm, где будет опсание того, как найти keltirs и .т.д.
: k' e* `' K. Y, T
% n1 c& D8 Q# Y B7 X# v
. u8 G+ O) K- C ]9 m. nПри состоянии STARTED будет зарегистрирован дроп «fangs» при убийстве keltirs. Игрок может вернуться к стартовому NCP и спросить о квесте – метод onEvent будет вызван снова. Если у игрока не хватает необходимого количества предметов, то метод check() не переведет квест в следующее состояние и Started.htm будет показана снова. Но если игрок собрал необходимее количество предметов (в данном случае 4 клыка), то метод check() вызовет метод completed() который переведет квест в новое состояние COMPLETED, заберет все клыки, даст карту мира, т.к. это награда за квест, покажет Completed.htm и завершит квест.: V- t, i) l* o' D
8 t1 ^( M, N+ B0 b. Q' k
* ^ b. p2 H! k# X$ N% j" ~2 }) @
Теперь давайте сделаем наш квест более похожим на то, что он должен из себя представлять.
6 `( K2 l1 ~8 K, c5 KПрежде всего у нас есть 3 метода для объявления их в Яве – onTalk, onKill и onEvent. Если методы onTalk и onKill не объявлены, то за них все будет делать метод onEvent, т.е. определять квестовых монстров и вызывать диалоги NCP. Есть примечание, методы onTalk и onKill будут вызывать только диалоги с NCP в зависимости от текущего состояния квеста. Метод onKill будет вызываться только тогда, когда мы убиваем квестового монстра. |2 j! Y+ H* Q- n
. R3 E3 S* G' v% i
5 m1 @3 Z0 E2 W/ ~+ r* z7 YДавайте рассмотрим как вызывается метод onKill при убийстве keltir в состоянии квеста STARTED:
6 \ Z/ M7 e/ e! s- s K- STARTED.addKillId(KELTIR_NPC_ID)
Скопировать код и метод onKill в классе Quest:+ p- S3 v! s# ~- q3 w: j: f1 V
], Y) m; L# [. F# N! J
- class Quest (JQuest):1 N' F+ z4 q x( n3 T
- ...
9 | ^! @" y# S% K+ Q' S& K( g - def onKill (self,npcId,st):' Z1 n8 L! b7 ]. X$ `' }, b
- if npcId == KELTIR_NPC_ID:
7 D: r9 G! |" ?" N - n = getCount(st)
1 Q0 N/ `. T" Z2 k - if n == 0:6 S5 X2 o+ y# e+ Z8 |
- return "Chat0.htm"( ~. S) f; C; U& f1 {
- elif n == 1:
+ h. s. H/ _4 M0 E- H( u - return "Chat1.htm"6 K3 Q% o3 j0 E* g2 K' j$ ~
- elif n >= 4:
, l# X0 ^5 J5 }2 d/ z" s' l - return "Chat4.htm"
$ H" a& I" ?0 } - return "Collected "+str(n)+" of 4 fangs"
: |+ P( h! J" V' E7 F - return
Скопировать код Метод onKill (а так же метод onTalk) имеет следующие параметры:6 r3 |: ?, e$ Z& K# P5 I/ W+ j
! p0 v4 N; L2 X: b# ~ h
* R* P& y+ i& Z- i• self – квест7 t4 Y' b: q# M
• npcId – ID NCP, которого мы должны убивать (если это метод onTalk, то ID того NCP, с которым мы должны поговорить)., N& X3 A0 t. T1 [: b A
• st – текущее состояние игрока.
5 f! P2 |3 L2 J8 ^ k+ h, K, Y5 I0 T0 M |0 e2 O4 x/ O
7 m A* y. e7 e) S# s
В этом методе мы проверяем и отмечаем, является ли убитый NCP keltir’ом. В основном эта проверка не нужна, т.к. у нас только KELTIR_NPC_ID.1 @$ N+ \: W7 @6 y5 x# b4 b! c& v3 n
; I* c: O" o$ j$ ?% T% z3 U1 u- y2 ]4 `. v% g; y- r" ]
Затем проверяем количество предметов (в данном случае количество клыков), и если их вообще нет, то возвращаем строку "Chat0.htm", если только один предмет, то возвращаем строку "Chat1.htm", если же предметов 4 или больше, то "Chat4.htm". Если строка возвращена из методов onEvent, onKill или onTalk, то сервер покажет соответствующие htm. В Chat0.htm может иметь следующий текст: «Вы не имеете ни одного клыка, возвращайтесь позже, когда соберете 4 штуки и бла, бла, бла…», в Chat1.htm может быть следующий текст: «У Вас всего 1 клык, по этому соберите еще…». В Chat4.htm – «Вы собрали необходимое количество предметов, возвращайтесь к вашему тренеру, что бы завершить квест…»- t$ g0 H7 H" p, y2 W3 \) Q( ~# b
% y6 Y( A/ v7 a4 {3 h/ R
- O, E/ ]3 F9 w. [7 uПримечание: если в строка return начинается с "<html>", то будет показана страничка html с текстом, который стоит далее. Так вместо:8 W5 g: h4 w7 z! m- r- F
return "Chat4.htm"
7 O {4 x- |( j* W, [7 b+ U) m: V# [: y
$ D# T0 W- Q& Z! Q9 ^+ Gможно поставить:1 q5 ^" E. m. ^6 r" E! J# i# }
- return "<html><body>Return to your trainer to complete the quest</body></html>"
Скопировать код Так же если строка заканчивается без .htm или в начале нет <html>, то текст будет выведен, как системное сообщение в окне чата. В нашем случае мы сделаем так, что бы при каждом убийстве keltik выводилось системное сообщение: «Собрано N из 4-х клыков».
0 n$ j, V+ E$ \% c! J1 f# S4 E
4 S1 B+ X' j( ~, o9 v
( {5 e: q, P6 }) O. Y9 v) ^Наш код для onKill имеет один недостаток. Он будет постоянно показывать Chat0.htm, Chat1.htm и Chat4.htm, нам же необходимо, что бы Chat0.htm и Chat1.htm показывались только один раз. Как нам это сделать? С помощью переменных.& L1 _9 u+ Q; _# q5 W
' i; J/ I; i9 N+ K5 G5 w D/ F q" G2 [
В каждом квесте строки могут храниться с помощью переменных. Эти переменные сохраняются в Вашей БД. В каждом методе мы можем назначить, прочитать и удалить переменные. Давайте изменим метод onKill, так что бы каждый диалог вызывался только один раз.
! }$ @! _5 c& {8 G A0 J- def onKill (self,npcId,st):* P( I) B7 Q# }! {! l2 J- e8 ^
- if npcId == KELTIR_NPC_ID:
# B/ E4 d0 Y8 ] - n = getCount(st)3 x4 B, r( A/ X' P1 U2 G& w
- if n == 0:2 {2 s) c' e; {! g% s& _
- if st.get('chat0') == None :. U% K$ P5 E" ~0 W: r
- st.set("chat0", "true")
$ `* E# [- x- B7 w0 G3 c2 Y! m - return "Chat0.htm"
( S' f$ A, x: t6 \% a6 j - elif n == 1:
0 ^/ g- J7 y/ D+ ~ - if st.get('chat1') == None :2 B/ I6 _1 b& K6 T$ L3 S7 l
- st.set("chat1", "true")6 b/ d0 _- W2 M3 p( N9 E
- return "Chat1.htm"
6 ~5 y$ M( d- n" _ - elif n >= 4:) A, k% S& z. C% O H
- return "Chat4.htm"
2 o0 ?% i: S- D# W5 [ - return "Collected "+str(n)+" of 4 fangs"
l& t6 c, T* E g6 \1 r9 { - return
Скопировать код Если у игрока нет клыков (n=0), то мы получаем занчение переменной 'chat0'. Когда метод onKill вызван в первый раз, то пока ни каких переменных не имеется и python возвращает значение None. В этом случае объявляется переменная и показывается диалог Chat0.htm. Когда мы убиваем keltir, но не получаем с него клык, функция st.get('chat0') возвращает строку true, а не None. И во второй раз окно с Chat0.htm не появится, но в окне чата появится строчка «Collected 0 of 4 fangs». По тому же принципу сделано и с Chat1.htm.
1 ~2 h; _1 ~2 G0 z6 N/ j Y+ h5 n5 h3 v9 n. }2 d; W
0 M' ^: U) N7 g9 D) K" M0 V" O
Вот конечный рабочий вариант квеста:3 V! A: @1 v/ R5 |5 N9 L; z: \( E
- import sys, h- _: s1 w' e$ V' m) |' a- Y
- from net.sf.l2j.gameserver.model.quest import State+ `0 B+ b. J5 L8 |
- from net.sf.l2j.gameserver.model.quest import QuestState# w) D' K+ _8 |* ~: j) Y/ x: R
- from net.sf.l2j.gameserver.model.quest.jython import QuestJython as JQuest. N& R3 u( X% T+ B. E: |
6 S) H5 ?% V. ^0 b- KELTIR_NPC_ID = 12082# Y$ _% i/ X. f _
- FANGS_ITEM_ID = 1859
1 p/ f0 u/ P. |, ~( A) n9 j) k. s' A - DROP_RATE = 500000 _% ~5 a4 O- b3 `
8 Y8 v; }( D' r# a# M8 n- WORLD_MAP_ITEM_ID = 1665- ]5 [2 w# B5 | A: E2 E
- 2 O% ]5 p! L% \7 l
- def getCount(st) :
/ q6 n$ u+ B* {3 j6 f - return st.getQuestItemsCount(FANGS_ITEM_ID)7 h+ K2 l4 b/ H. j, M3 l1 H
- 6 G" {' |! p) H4 x5 K& T7 g
- def completed(st) :- y; z7 g3 G) `) ]8 _! d
- st.setState(COMPLETED)
1 g+ j" i* H, ^# a( L - st.clearQuestDrops()
1 A) W: d7 Z4 L7 e( r% { - st.takeItems(FANGS_ITEM_ID,-1)9 [" [- ~( Z+ @5 l% m
- st.giveItems(WORLD_MAP_ITEM_ID,1)6 M k$ }9 U6 m
- st.exitQuest(False)9 {+ b. i4 V% |( C6 D% j% x" {
- return
5 |1 N- N T" @) W$ f - 9 Z- a: _+ S0 @9 K9 c; B
- def check(st) :/ e9 J6 t! o1 _( X
- if getCount(st) >= 4 :
+ x3 @7 |8 ?1 c @" m - completed(st)& d( M: |7 d0 e2 d
- return) l. A$ X6 {) ^( U7 ^( q
- ) ^% h% e& K4 T1 |
- class Quest (JQuest):6 B' [5 Q) q( f. j3 V* Q) v7 M& l
6 W+ v1 B# ~ c" y3 l0 ~4 O7 I- def __init__(self,id,name,descr): JQuest.__init__(self,id,name,descr)+ V# x5 y+ @8 @% ?
' A }$ ]& g" n. c) n- `- def onEvent (self,event,st):
5 r! s$ W+ o, `) \ n - id = st.getState()
, I9 ]9 U0 Q$ I. d1 X/ i# V+ R. o* n - if id == CREATED : st.setState(STARTED)$ x9 l9 v2 y" N" Q# i
- elif id == COMPLETED: pass
! ~5 B k3 C5 P+ A1 l8 I - elif id == STARTED : check(st)
0 V$ N8 B B0 K3 U - return
- S7 I ~ k- `7 m$ Y
) |: {, K* c% D9 [2 G% _- def onKill (self,npcId,st):4 n8 s5 p7 r+ E6 @2 @, C4 ^ u2 V
- if npcId == KELTIR_NPC_ID:
/ c% n0 C( N: ?5 n - n = getCount(st)1 K/ S% _6 p; `0 _
- if n == 0:3 m6 G. D6 x7 t9 m2 C: f- _
- if st.get('chat0') == None :
- ^" t* y5 {; J - st.set("chat0", "true")0 o3 X4 m6 A: y# D) ?1 K2 u
- return "Chat0.htm" @ ~5 g$ m" U. D
- elif n == 1:9 I# ]' j0 L; A5 I9 ?; ~5 D; _. `, Y
- if st.get('chat1') == None :1 q& |- N/ p8 S2 t/ I T7 ~
- st.set("chat1", "true")6 s. G/ c7 U- U' l( [/ w
- return "Chat1.htm"! a. `1 }- p6 U7 v# a c
- elif n >= 4:
! K6 o0 X) K7 c/ Z9 X( S. o; U2 n - return "Chat4.htm"
, ] u5 K5 w; r) Q6 K7 g - return "Collect "+str(n)+" of 4 fangs"
$ N5 a, W1 u, p Z3 }: [. K- ]! f) \% l8 x - return
$ Q3 d+ M1 h0 }: K - / O. I/ v( k! t5 A% @
- QUEST = Quest(201, "Tutorial", "Tutorial quest")
/ o+ X8 \) c$ { Z% p4 q - CREATED = State('Start', QUEST)
9 s, F* L" u+ ^$ `" Q - STARTED = State('Started', QUEST)
0 F9 W8 L, I) N# J5 [ - COMPLETED = State('Completed', QUEST)
7 w! d6 Z( _ G; ?" s( e$ @
1 o) u% W+ F5 F- QUEST.setInitialState(CREATED)( r7 _; f! q2 |: X; q# T/ u
- QUEST.addStartNpc(7056)
9 U8 w; y* @9 C0 V, j - QUEST.addStartNpc(7012)
% O9 @& F0 o4 e8 h, } - QUEST.addStartNpc(7009)9 U; ~) O" [+ p
- QUEST.addStartNpc(7011)
& d2 A0 {' x4 Q& |' W - 5 P$ {, ^! ~ A1 G0 f
- STARTED.addQuestDrop(KELTIR_NPC_ID,FANGS_ITEM_ID,DROP_RATE)
$ \0 L$ \4 L$ e, N - STARTED.addKillId(KELTIR_NPC_ID)
) e3 Z' u- a4 `: r n/ H% Y - STARTED.addTalkId(7056)
" G. V( ]4 G" }" T+ Q4 c' T! I - STARTED.addTalkI d(7012)& `! G' W; k: C% d$ ]5 T
- STARTED.addTalkId(7009)
; g( f' P& S+ j, E) @8 T - STARTED.addTalkId(7011)
Скопировать код
% T' C( C' R6 x! j2 `/ F9 f4 c$ \, T2 Z! x
|