Зарегистрируйтесь сейчас чтобы найти еще больше друзей, и получить полноценный доступ ко всем функциям сайта!
Для просмотра Вам необходимо авторизоваться Если Вы еще не зарегистрированы, перейдите по ссылке:Зарегистрироваться
x
Хроники Interlude
' I3 L8 u) X# u8 D% t. hСборка L2j
; Z# p8 q! P. t0 E; [, Q+ dОбратите внимание: в файле htm стартового NCP обязательно должна быть ссылка на квест:
. ~/ |- a7 [+ }& y# J- STARTED.addQuestDrop(KELTIR_NPC_ID,FANGS_ITEM_ID,DROP_RATE)
Скопировать код Для этого квеста больше ничего не надо. Все необходимое для корректной работы квеста уже добавили. Вот полный текст квеста:0 O& b1 r0 Z) ^% M# j
3 p: p5 ?7 b8 C
- if getCount(st) >= 4 :
$ U5 }# |. v2 m1 p! L; O - completed(st); |+ g3 s* A; _5 d
- return
6 I& ?7 r# X. H% k0 w, U0 g7 G - 5 ]9 J% V* @# q
- class Quest (JQuest):; l3 U% e1 ~' \! D. E. u3 z' o
- def __init__(self,id,name,descr): JQuest.__init__(self,id,name,descr)
( g" d1 _9 ~8 @6 B0 U; X - def onEvent (self,event,st):
$ l6 Q7 @1 [' D - id = st.getState()
/ i+ J) C0 ^' w( e - if id == CREATED : st.setState(STARTED)
" _) ]9 N5 k5 o5 g$ ?% {; U. ?0 @ - elif id == COMPLETED: pass" d8 [# [% w4 _5 u
- elif id == STARTED : check(st) D1 \+ g- `. u
- return
9 B0 k6 z" G% M - & p& [/ t1 _0 V: u( ~% N& {; r) T
- QUEST = Quest(201,"Tutorial", "Tutorial quest")
- i* E! P4 @/ @5 ?( `3 G: [ - CREATED = State('Start', QUEST)2 [4 l- s% j; ]+ Q$ `5 [6 o% q1 T
- STARTED = State('Started', QUEST)
5 B9 d8 e$ l% F - COMPLETED = State('Completed', QUEST)
# s) e7 s$ y5 D/ t
8 w0 D* \4 s& k M# B5 [" D5 i+ B# }- QUEST.setInitialState(CREATED)7 V& M( @, Z" E, g5 z* w
- QUEST.addStartNpc(7056)
: h; Y8 D1 d! q# T/ V8 d3 X - STARTED.addQuestDrop(KELTIR_NPC_ID,FANGS_ITEM_ID,DROP_RATE)
Скопировать код Теперь рассмотрим, как это работает.& o: a0 Q1 x) K
Игрок подходит к начальному NCP (в данном случае 7056), нажимает на «Quest». Квест будет создан и состояние квеста перейдет к CREATED и игроку будет показана страничка Start.htm с описанием квеста. Тогда метод onEvent, поле открытия странички Start.htm переведет состояние квеста в STARTED и игроку будет показана страничка Started.htm, где будет опсание того, как найти keltirs и .т.д.4 L2 H# m- Q) f: m# s
" }3 A& W8 I5 m' |8 J7 O D& }
4 o. J! |4 ]# lПри состоянии STARTED будет зарегистрирован дроп «fangs» при убийстве keltirs. Игрок может вернуться к стартовому NCP и спросить о квесте – метод onEvent будет вызван снова. Если у игрока не хватает необходимого количества предметов, то метод check() не переведет квест в следующее состояние и Started.htm будет показана снова. Но если игрок собрал необходимее количество предметов (в данном случае 4 клыка), то метод check() вызовет метод completed() который переведет квест в новое состояние COMPLETED, заберет все клыки, даст карту мира, т.к. это награда за квест, покажет Completed.htm и завершит квест.8 G+ t- h c+ S" n% c# ^
) [8 X; e2 Z8 ] v6 [' |7 D: O5 ?# j7 U; C4 y
Теперь давайте сделаем наш квест более похожим на то, что он должен из себя представлять.- a7 x5 T w3 b1 O+ C& P
Прежде всего у нас есть 3 метода для объявления их в Яве – onTalk, onKill и onEvent. Если методы onTalk и onKill не объявлены, то за них все будет делать метод onEvent, т.е. определять квестовых монстров и вызывать диалоги NCP. Есть примечание, методы onTalk и onKill будут вызывать только диалоги с NCP в зависимости от текущего состояния квеста. Метод onKill будет вызываться только тогда, когда мы убиваем квестового монстра.
9 F& w% G1 [" A& U% n0 C0 p; {/ ~2 H/ B; y* @# s
+ Z0 r I, v8 `* f
Давайте рассмотрим как вызывается метод onKill при убийстве keltir в состоянии квеста STARTED:
+ o) s! _- F' m- STARTED.addKillId(KELTIR_NPC_ID)
Скопировать код и метод onKill в классе Quest:
* v; X% e8 q& ~/ m9 d' ^) s, V$ U# v( e! M# ?* r- O
- class Quest (JQuest):
+ \& Y2 F- f# {2 v# {& k$ m- F - ...
: W7 A7 C7 U3 E9 q - def onKill (self,npcId,st):8 W5 z1 q4 Z p
- if npcId == KELTIR_NPC_ID:
( e1 y. L0 t1 H - n = getCount(st)* z0 `' ^9 f; ]2 Q \" p
- if n == 0:
* L1 }# Y) |9 a; f3 O, F4 a: G9 a - return "Chat0.htm": B" b3 T/ l F% F k8 b& |
- elif n == 1:
( j2 |/ X3 j0 s - return "Chat1.htm"5 @+ e8 z" s8 x7 N
- elif n >= 4:1 ]. |: u# Q, j3 a/ ~* I. |- E1 q. g
- return "Chat4.htm"7 f$ M) ^2 B8 v# N% Y7 X' t3 Y9 ~
- return "Collected "+str(n)+" of 4 fangs"& J2 \& W7 Y) D3 S" O9 q' t
- return
Скопировать код Метод onKill (а так же метод onTalk) имеет следующие параметры:, F# V; W8 M" h% G: x
* q# _( }' B. U
0 q1 G1 O/ R% q$ d/ c
• self – квест
2 _: D: A) V* a2 M) y1 T• npcId – ID NCP, которого мы должны убивать (если это метод onTalk, то ID того NCP, с которым мы должны поговорить).+ f; N8 F1 k0 D/ a: i/ U( w
• st – текущее состояние игрока.
- ~0 W: i1 g4 S9 V& N8 A. ]+ C% T, R3 K6 ~
7 J2 C8 p% R- N# y3 n2 E+ rВ этом методе мы проверяем и отмечаем, является ли убитый NCP keltir’ом. В основном эта проверка не нужна, т.к. у нас только KELTIR_NPC_ID.2 r! K% l C% h! z% S* c; w6 z
" ~1 Z- o8 }- \- G6 G1 d; f( c2 b0 K% Z) t1 \7 Q
Затем проверяем количество предметов (в данном случае количество клыков), и если их вообще нет, то возвращаем строку "Chat0.htm", если только один предмет, то возвращаем строку "Chat1.htm", если же предметов 4 или больше, то "Chat4.htm". Если строка возвращена из методов onEvent, onKill или onTalk, то сервер покажет соответствующие htm. В Chat0.htm может иметь следующий текст: «Вы не имеете ни одного клыка, возвращайтесь позже, когда соберете 4 штуки и бла, бла, бла…», в Chat1.htm может быть следующий текст: «У Вас всего 1 клык, по этому соберите еще…». В Chat4.htm – «Вы собрали необходимое количество предметов, возвращайтесь к вашему тренеру, что бы завершить квест…»
5 _5 O* M: ~& d+ A. s* Y( B( U5 K/ `- d+ v/ v5 @
1 h( q& \8 d% Q+ s+ _Примечание: если в строка return начинается с "<html>", то будет показана страничка html с текстом, который стоит далее. Так вместо:( d+ H8 l; k! z1 h" k7 J% q: B
return "Chat4.htm"$ Y- W# N; n- {, v
6 a& ]3 ?2 a$ E. H5 f3 i- {9 j+ P5 V- ^5 U Q t
можно поставить:
6 j0 \* D7 \4 J- return "<html><body>Return to your trainer to complete the quest</body></html>"
Скопировать код Так же если строка заканчивается без .htm или в начале нет <html>, то текст будет выведен, как системное сообщение в окне чата. В нашем случае мы сделаем так, что бы при каждом убийстве keltik выводилось системное сообщение: «Собрано N из 4-х клыков».( N$ X# E# w; c
/ Y6 m: Z& N: X' y1 r# V
( b& }$ R1 F- A I* [& M7 uНаш код для onKill имеет один недостаток. Он будет постоянно показывать Chat0.htm, Chat1.htm и Chat4.htm, нам же необходимо, что бы Chat0.htm и Chat1.htm показывались только один раз. Как нам это сделать? С помощью переменных.
. O0 e3 f; F# |6 j8 {% d# j
8 m9 Q8 u4 B* e6 E7 t9 ?
" ^; L; C; v e* w4 O( Z$ fВ каждом квесте строки могут храниться с помощью переменных. Эти переменные сохраняются в Вашей БД. В каждом методе мы можем назначить, прочитать и удалить переменные. Давайте изменим метод onKill, так что бы каждый диалог вызывался только один раз./ ? q0 n/ R! a: q: }! L0 {
- def onKill (self,npcId,st): r5 o9 G0 H- I: o0 R
- if npcId == KELTIR_NPC_ID:0 @& ^! s: B4 \" l
- n = getCount(st)& r3 ?+ m8 i i! w" N; U
- if n == 0:: R! e. }) R% \3 q( ^( L
- if st.get('chat0') == None :7 H; f% P9 M4 t, ~& F0 I( E
- st.set("chat0", "true")
" Q% S* a: p' p- s0 O7 S; r7 b - return "Chat0.htm"
1 [8 ~, j S+ D; i: g1 }' f- g - elif n == 1:. _* W9 x" D0 _# G# k4 \' t. [6 _
- if st.get('chat1') == None :
1 R, w% d4 h% X' t* b' [8 N - st.set("chat1", "true")% X( L4 v8 x/ ~! D, x$ L
- return "Chat1.htm"& d: w6 U- z, A& e& p8 P
- elif n >= 4:4 G' K7 i: w/ {0 O. d6 N9 `
- return "Chat4.htm"
7 X3 |! [1 H- K/ d# ]1 b6 P - return "Collected "+str(n)+" of 4 fangs"
) s* U+ G/ b$ U2 A' K5 S - return
Скопировать код Если у игрока нет клыков (n=0), то мы получаем занчение переменной 'chat0'. Когда метод onKill вызван в первый раз, то пока ни каких переменных не имеется и python возвращает значение None. В этом случае объявляется переменная и показывается диалог Chat0.htm. Когда мы убиваем keltir, но не получаем с него клык, функция st.get('chat0') возвращает строку true, а не None. И во второй раз окно с Chat0.htm не появится, но в окне чата появится строчка «Collected 0 of 4 fangs». По тому же принципу сделано и с Chat1.htm.& F4 T+ N3 C/ S% E
* b# j% F2 i- R" y! S- T( H
( f& j% u6 }& ^" P/ A
Вот конечный рабочий вариант квеста:7 r7 {+ H9 I5 }5 f6 \( d& E: _
- import sys
( S' c% m1 x" w0 [* e- T6 J - from net.sf.l2j.gameserver.model.quest import State
; M' G) n$ ]' j/ n: Z Y - from net.sf.l2j.gameserver.model.quest import QuestState
6 _. }/ \! O: z, W - from net.sf.l2j.gameserver.model.quest.jython import QuestJython as JQuest- b. ?+ Z% V6 n& |
}: ]& @8 T2 L$ g! a; ~! X* z- KELTIR_NPC_ID = 12082
. Y" J J% S# a: W7 K; {: l! K) ] - FANGS_ITEM_ID = 1859 ~8 l# @' x, S" w# e- d4 ]
- DROP_RATE = 5000001 P- I, L! ~' ^
- 9 j/ a" A' i5 f
- WORLD_MAP_ITEM_ID = 1665/ P+ ^, v: V8 o% j
! s+ U \! a+ J' U* _- def getCount(st) :6 d$ S2 m- o. s8 |7 A- w) Y/ R
- return st.getQuestItemsCount(FANGS_ITEM_ID)- D4 g* n% v* r6 e+ @9 @
$ [& t# R4 H8 D5 i- def completed(st) :
& y. b0 Y& r5 Q; F7 } - st.setState(COMPLETED)
* O! W+ [+ i" v+ C& \( }1 s0 A - st.clearQuestDrops()" J/ t9 B4 I: N- `; g
- st.takeItems(FANGS_ITEM_ID,-1)
! m- p6 ]4 `0 C" v2 B; S - st.giveItems(WORLD_MAP_ITEM_ID,1)
" c" @( \9 w" F - st.exitQuest(False)
$ K5 T& Q8 ] h$ K8 R9 v - return
I* O2 O6 o- C - 1 u% b' F, `" k a) {1 \) |7 r
- def check(st) :! p. V5 Z- M' I# m
- if getCount(st) >= 4 :
1 w! T& ` Y5 b2 H! m - completed(st)
5 y1 ~) I2 k. s, X9 c- J- h - return
3 p- r: G+ \6 I$ C7 E( ~0 Y" z: k( y
0 R& a, K8 R) z' O* ~9 G" ]( T- class Quest (JQuest):! x- ]& J! ] Z" e- _7 z* f
! X: q5 M' a1 U# l* o/ C+ P4 `- def __init__(self,id,name,descr): JQuest.__init__(self,id,name,descr)
6 L3 ~ L: |" J9 H* U
) u3 J$ c C, t4 U/ Y0 _0 {- def onEvent (self,event,st):9 R6 n' v4 u4 P: L1 O# g7 a1 ]. L/ a( f
- id = st.getState()8 J0 ` M; F' h2 B( z% B9 h
- if id == CREATED : st.setState(STARTED)
" d0 l0 r y% y - elif id == COMPLETED: pass7 R2 Q9 g' g) A' R
- elif id == STARTED : check(st)
, V" w! e* I) ~# f) h, a - return
3 c+ w8 m' f: L7 z' f8 } - ! h* C/ h0 N) z% g$ w( h
- def onKill (self,npcId,st):! p& ]" R( \9 ]9 b
- if npcId == KELTIR_NPC_ID:3 G5 q. p) }8 E$ Z
- n = getCount(st); c9 F+ x0 K) Z8 x# ]/ m$ \
- if n == 0:7 @. _; \' v, T; Z0 ^
- if st.get('chat0') == None :' ~1 q+ t# L' ?6 K/ R$ ]: v
- st.set("chat0", "true")
( R9 o3 S8 t- @; ^! v - return "Chat0.htm"
! A' ^! J, b4 b; f - elif n == 1:5 [* P5 h. c! a! K- [( r/ M& G
- if st.get('chat1') == None :, R$ p0 t3 h3 M5 V
- st.set("chat1", "true")
: k$ V/ y/ F9 Q0 D9 l, E& o! f - return "Chat1.htm" x3 j; x' d8 }% {$ J' C( K8 D
- elif n >= 4:
# c, o J2 D: H - return "Chat4.htm"7 J# ^: `; H, l
- return "Collect "+str(n)+" of 4 fangs"& n" N+ X) {4 f5 B, u. o% B
- return
, t- Q/ B$ J4 B6 A+ k) ] - + Z$ h+ m8 I' c0 B
- QUEST = Quest(201, "Tutorial", "Tutorial quest"): ~7 }! ] U# U* D& k% g9 G
- CREATED = State('Start', QUEST)
9 p7 S* V! A* w5 ^ - STARTED = State('Started', QUEST)
7 J8 m& t$ U/ k5 h6 u0 }5 T - COMPLETED = State('Completed', QUEST)7 A* z D- D2 N1 ]+ f- J, \8 M
- " I$ u. m# y O, I4 [
- QUEST.setInitialState(CREATED)
a7 y0 b- \2 I - QUEST.addStartNpc(7056). U+ _" p6 q: P7 ^) r- O4 a, A
- QUEST.addStartNpc(7012)/ r5 @ U* a& _8 t" n! A
- QUEST.addStartNpc(7009) H5 v$ h9 P" j- @2 Y- G! q
- QUEST.addStartNpc(7011)9 S3 u- O" g, K7 [
' L6 _- f2 |& O: B* k- t6 p2 }) `- STARTED.addQuestDrop(KELTIR_NPC_ID,FANGS_ITEM_ID,DROP_RATE)
8 s7 i* t! O/ l5 z) m$ ]6 B- g( o - STARTED.addKillId(KELTIR_NPC_ID)/ G/ F: o) T' Q" i% d* ]2 L) f
- STARTED.addTalkId(7056)* x" V% o& x. C t
- STARTED.addTalkI d(7012)( F" g; H* O4 e( B: K% b9 ~
- STARTED.addTalkId(7009)& k: T) w2 `6 T% q& a- T
- STARTED.addTalkId(7011)
Скопировать код . R7 Z, {+ z9 ?& u" T8 J
/ H; p/ N/ F* Q2 X1 u# X! M2 ^" E4 f
|