Зарегистрируйтесь сейчас чтобы найти еще больше друзей, и получить полноценный доступ ко всем функциям сайта!
Для просмотра Вам необходимо авторизоваться Если Вы еще не зарегистрированы, перейдите по ссылке:Зарегистрироваться
x
Хроники Interlude! n0 Y9 {6 }1 O9 e4 a" [ I+ p, \
Сборка L2j. V( F! u2 s$ n- O
Обратите внимание: в файле htm стартового NCP обязательно должна быть ссылка на квест:) q3 A I. B5 @; Z+ i0 p$ i
- STARTED.addQuestDrop(KELTIR_NPC_ID,FANGS_ITEM_ID,DROP_RATE)
Скопировать код Для этого квеста больше ничего не надо. Все необходимое для корректной работы квеста уже добавили. Вот полный текст квеста:8 ]; f) p8 \- \; r. Y0 N' ~! I
0 }$ q) N% H# W# Q7 l- if getCount(st) >= 4 :
5 q( ~: D B6 C" Q- {' h# w - completed(st), H) ?9 H0 h& Q t& Z! l
- return& j9 q% H$ l% p# }$ C
- 1 l' C3 n9 B' t- ]! M
- class Quest (JQuest):
, Q' |& w$ {/ B" R; a0 c - def __init__(self,id,name,descr): JQuest.__init__(self,id,name,descr)
9 c+ u+ M- n: G. |6 ^; b3 H6 c - def onEvent (self,event,st):1 U/ C0 M) N2 M7 N* _ }. E
- id = st.getState()9 P" l; Y1 ]- r/ |
- if id == CREATED : st.setState(STARTED)& L8 }7 K* M' u$ r- t2 c
- elif id == COMPLETED: pass
2 Y+ F1 S6 g: q. v) R2 v4 { - elif id == STARTED : check(st)
0 w0 _. S y3 g( z, k k1 d - return
0 [! ?( c7 s: P* R - ) m* V2 j- {% Q6 l- m! E) G
- QUEST = Quest(201,"Tutorial", "Tutorial quest"); T) \; D) X: a( m
- CREATED = State('Start', QUEST)
& {: A2 L. s, N1 d' S - STARTED = State('Started', QUEST)
) o2 s5 X% t8 R8 h9 R) Y+ b' ~ - COMPLETED = State('Completed', QUEST)) U8 ~( ^+ M' h
8 U' [# t; y. E8 o- QUEST.setInitialState(CREATED)9 t* K& h! e% m
- QUEST.addStartNpc(7056)
7 B4 }$ W2 Z1 [" r% ^; I6 m) [ - STARTED.addQuestDrop(KELTIR_NPC_ID,FANGS_ITEM_ID,DROP_RATE)
Скопировать код Теперь рассмотрим, как это работает.
- b: c$ j# z: \6 Q V3 tИгрок подходит к начальному NCP (в данном случае 7056), нажимает на «Quest». Квест будет создан и состояние квеста перейдет к CREATED и игроку будет показана страничка Start.htm с описанием квеста. Тогда метод onEvent, поле открытия странички Start.htm переведет состояние квеста в STARTED и игроку будет показана страничка Started.htm, где будет опсание того, как найти keltirs и .т.д.* k% D4 E0 Y8 ^" q
1 N( T! U$ H R9 H0 y
! e6 {* G) B5 | w) ^3 q7 z
При состоянии STARTED будет зарегистрирован дроп «fangs» при убийстве keltirs. Игрок может вернуться к стартовому NCP и спросить о квесте – метод onEvent будет вызван снова. Если у игрока не хватает необходимого количества предметов, то метод check() не переведет квест в следующее состояние и Started.htm будет показана снова. Но если игрок собрал необходимее количество предметов (в данном случае 4 клыка), то метод check() вызовет метод completed() который переведет квест в новое состояние COMPLETED, заберет все клыки, даст карту мира, т.к. это награда за квест, покажет Completed.htm и завершит квест.6 `1 o l# G9 S7 B$ Q
, h7 v: K$ u4 Z e$ y. x5 B
7 I6 K5 T+ g, n: P/ @) b. W2 SТеперь давайте сделаем наш квест более похожим на то, что он должен из себя представлять.. S7 f4 V5 @6 k* X& X
Прежде всего у нас есть 3 метода для объявления их в Яве – onTalk, onKill и onEvent. Если методы onTalk и onKill не объявлены, то за них все будет делать метод onEvent, т.е. определять квестовых монстров и вызывать диалоги NCP. Есть примечание, методы onTalk и onKill будут вызывать только диалоги с NCP в зависимости от текущего состояния квеста. Метод onKill будет вызываться только тогда, когда мы убиваем квестового монстра.
+ p( ?! ^+ ~- j/ e& R1 p$ s6 `: ^# P" j8 u" H: |! x
5 o) Y* T. f. z# w
Давайте рассмотрим как вызывается метод onKill при убийстве keltir в состоянии квеста STARTED:' [; |+ Z- R9 v
- STARTED.addKillId(KELTIR_NPC_ID)
Скопировать код и метод onKill в классе Quest:
0 m' W% v, o9 Y5 a& r0 K/ T j! A* r d
- class Quest (JQuest):. W; e; I Y- J) v" [) U, [" x) W
- ...
( I- {" v' r3 c: w+ D5 w* G - def onKill (self,npcId,st):
( y# ^7 o6 ^8 K# Z5 _3 Z - if npcId == KELTIR_NPC_ID:" T& l( p& S: J& q$ g6 P
- n = getCount(st)
; D7 L4 m+ s0 L - if n == 0:2 ~) t* G Q& d$ q7 f; |, _+ \
- return "Chat0.htm"
" c% n' M6 n+ x2 H - elif n == 1:2 n* `. h' J( u
- return "Chat1.htm"" [1 A7 D1 D5 k3 M
- elif n >= 4:
1 ?7 U* e' u& q9 S( @+ N - return "Chat4.htm"5 r2 E$ r9 P7 \; x
- return "Collected "+str(n)+" of 4 fangs"( K1 W+ `( {, e) ^3 m6 S
- return
Скопировать код Метод onKill (а так же метод onTalk) имеет следующие параметры:
: ~- t5 g& l; y- f
. X0 G) X4 u' ^9 A6 z% y) n3 B% {4 B* m0 S0 i& l( k- `% j& Y
• self – квест
6 x* E4 u7 c; I7 Q• npcId – ID NCP, которого мы должны убивать (если это метод onTalk, то ID того NCP, с которым мы должны поговорить).
" c+ X- b/ `& x• st – текущее состояние игрока.
@4 c( t$ K% o) ~( ? f2 _
) B- r8 s5 X! ]
" J$ [8 u* G4 I; D# q5 b$ GВ этом методе мы проверяем и отмечаем, является ли убитый NCP keltir’ом. В основном эта проверка не нужна, т.к. у нас только KELTIR_NPC_ID.4 Z5 @& R& k7 n
2 C) s+ _5 @% z: o6 N1 D6 ?
7 r9 K) {9 U" aЗатем проверяем количество предметов (в данном случае количество клыков), и если их вообще нет, то возвращаем строку "Chat0.htm", если только один предмет, то возвращаем строку "Chat1.htm", если же предметов 4 или больше, то "Chat4.htm". Если строка возвращена из методов onEvent, onKill или onTalk, то сервер покажет соответствующие htm. В Chat0.htm может иметь следующий текст: «Вы не имеете ни одного клыка, возвращайтесь позже, когда соберете 4 штуки и бла, бла, бла…», в Chat1.htm может быть следующий текст: «У Вас всего 1 клык, по этому соберите еще…». В Chat4.htm – «Вы собрали необходимое количество предметов, возвращайтесь к вашему тренеру, что бы завершить квест…»# O, `, f/ M& J7 W1 P0 R( h/ Y% Z
6 H; s6 ?6 r" J# r* ]- `+ \
o, a8 j' S* O8 ^; u6 L
Примечание: если в строка return начинается с "<html>", то будет показана страничка html с текстом, который стоит далее. Так вместо:8 c7 Q! J% p" w7 e8 l+ J7 A+ k
return "Chat4.htm"
. j0 X3 ]( f# @6 f3 Y: z+ t) u( v" o/ |9 {: [
: D/ E4 J) O! T' w( U* Pможно поставить:
7 o4 |+ L7 h' Q- return "<html><body>Return to your trainer to complete the quest</body></html>"
Скопировать код Так же если строка заканчивается без .htm или в начале нет <html>, то текст будет выведен, как системное сообщение в окне чата. В нашем случае мы сделаем так, что бы при каждом убийстве keltik выводилось системное сообщение: «Собрано N из 4-х клыков».
( n5 {- H1 f1 g; V5 \( G p, h t) V; R' v; d
0 w* G& }4 z1 t! R g! r% ]/ |Наш код для onKill имеет один недостаток. Он будет постоянно показывать Chat0.htm, Chat1.htm и Chat4.htm, нам же необходимо, что бы Chat0.htm и Chat1.htm показывались только один раз. Как нам это сделать? С помощью переменных.
) c1 \, [( D& d& }( h! l
! c4 {: x1 p; N5 K9 H P$ z1 e6 R$ [/ g0 d7 |8 E8 N
В каждом квесте строки могут храниться с помощью переменных. Эти переменные сохраняются в Вашей БД. В каждом методе мы можем назначить, прочитать и удалить переменные. Давайте изменим метод onKill, так что бы каждый диалог вызывался только один раз.+ @& m( G& L" _. m: ^6 M+ O
- def onKill (self,npcId,st):9 s- z% L* S! Q8 z
- if npcId == KELTIR_NPC_ID:& J* E( k9 m- N3 ?
- n = getCount(st)
5 E, E q, m7 `6 r- d - if n == 0:
/ d, n1 _# F5 f' [. x/ p: E - if st.get('chat0') == None :' n8 V9 A! g- N
- st.set("chat0", "true")
& n) R; J. q/ E* h - return "Chat0.htm"- c. @/ v& k- ^4 C. |
- elif n == 1:0 w9 i# Q6 ^% N4 S; n" x2 a* @
- if st.get('chat1') == None :# h- W, t: p% U& A: z- E2 b
- st.set("chat1", "true")4 p9 c' q8 P# o6 N
- return "Chat1.htm": t. k' ^& t. l1 B; N
- elif n >= 4:
# c0 {& ]/ y" I9 l! ^( L: y - return "Chat4.htm"
Y& I6 q7 f. e0 k8 {0 |( L - return "Collected "+str(n)+" of 4 fangs"
+ I& P" ^6 R9 l1 K. 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.
2 U% o' a; K$ J3 v; w1 ~, i- }& l' t1 e. e# n
4 }* v# p5 l5 Y$ g% K' K) [
Вот конечный рабочий вариант квеста:
2 t- I5 P1 n! [' A+ {8 g5 p5 ^- import sys
9 C* X/ A- y8 B3 ?, p - from net.sf.l2j.gameserver.model.quest import State3 J5 D0 ^) G5 ]5 s( ~. }. ^, l; G
- from net.sf.l2j.gameserver.model.quest import QuestState6 h& n7 s4 [. g' V7 H( l/ e& ^
- from net.sf.l2j.gameserver.model.quest.jython import QuestJython as JQuest
n/ v# W# X: Q* }* \2 K
* `- l0 Q d1 Q" c) e! m6 j, \- KELTIR_NPC_ID = 12082
. s0 t$ S' ]8 s, L9 r - FANGS_ITEM_ID = 18599 p7 C7 o( q6 {* S6 Y
- DROP_RATE = 5000003 ~# A% S0 d$ x0 D" x/ q7 m
- , Q/ x2 r [; G1 X3 z
- WORLD_MAP_ITEM_ID = 16655 ]7 h5 I. D4 n) h3 r; M7 G
3 [% b9 H) s( |: L1 |+ q- def getCount(st) :' S( a, ?2 a3 I/ D
- return st.getQuestItemsCount(FANGS_ITEM_ID)
3 w7 V, P* S% o - : F3 ]2 l w4 s5 Y" x
- def completed(st) :
! W/ X) a1 B4 ] - st.setState(COMPLETED)0 A9 r* [1 k1 ~6 A
- st.clearQuestDrops(). p6 g+ @, y6 C) C5 c
- st.takeItems(FANGS_ITEM_ID,-1)$ l. Z9 k$ }7 O3 l! l( R- E
- st.giveItems(WORLD_MAP_ITEM_ID,1)
) E* f0 D1 k1 ~3 ` - st.exitQuest(False)
, p7 {$ M3 T9 U2 h; V" c" M - return
3 p, R( h4 ^7 x' T
) _: d$ O! P" y) X+ k( @- def check(st) :
1 P; P' B7 {! G5 ~0 e8 l - if getCount(st) >= 4 :* f. c8 b O. \( p
- completed(st)
+ t% A# q6 M4 r9 w - return
$ N; C3 W( v0 t5 z( C6 g) t - # a p- K; e! f, T
- class Quest (JQuest):
. ] h# ~& V, N( S# z. ?+ I* R$ d - - r. l0 i- }8 |' B2 P' ^% }" c
- def __init__(self,id,name,descr): JQuest.__init__(self,id,name,descr)
; k2 P/ S, J& Q0 C! J) F0 z0 Y - + B5 Q6 h6 _' [$ G) ?& M; d
- def onEvent (self,event,st):
[' s0 v) ?5 u& ?1 G5 { - id = st.getState()
& T5 @! D5 b1 h. h5 r6 ]. m/ [ - if id == CREATED : st.setState(STARTED)
( C) U3 U+ z7 O1 T( ~ - elif id == COMPLETED: pass$ w+ {. @- ~* s$ T4 b! n
- elif id == STARTED : check(st)
4 ~) N& \( b- K' g - return8 t1 H* U1 ?6 W9 I* P/ A2 S
- 7 U; a# G2 D6 B: M
- def onKill (self,npcId,st):! |" x9 q6 j! @1 q
- if npcId == KELTIR_NPC_ID:; ]9 I z* g9 @/ l6 J9 b
- n = getCount(st)
* g9 {- s7 t4 L, t1 v - if n == 0:
3 E- V/ X9 Z$ I3 c! J- V$ ~1 W' I - if st.get('chat0') == None :2 }4 ?% }- N1 B; E# M- d
- st.set("chat0", "true")
7 s1 C4 f. K+ B) J( B' w - return "Chat0.htm" V! z7 i/ N9 q. i5 V# V' c8 ~
- elif n == 1:' H, O4 s& H% |$ ^1 \5 F% q
- if st.get('chat1') == None :
2 c: Q8 E+ g% E4 @) {9 J$ M - st.set("chat1", "true")9 P' q s o) B: H8 m
- return "Chat1.htm"
' ^8 g' a, f2 D2 l9 X - elif n >= 4:, G* H e/ y, Z3 n7 ?
- return "Chat4.htm"
$ Z4 Y- M2 a: B - return "Collect "+str(n)+" of 4 fangs"- w5 s9 A) \% @0 a# J' ~
- return
) f5 n, O5 ^4 M& L! W2 `5 g5 o - 9 g* `; I( T$ k% N
- QUEST = Quest(201, "Tutorial", "Tutorial quest")7 ^& A4 V2 P" L; F
- CREATED = State('Start', QUEST)% t+ m; K/ [, c& _; z
- STARTED = State('Started', QUEST)& x; g9 W5 ~9 I5 [( r( z; t" G9 N
- COMPLETED = State('Completed', QUEST)
" T8 \0 u( o6 ]2 Q2 C - 3 e: X- q6 H9 i; i6 e
- QUEST.setInitialState(CREATED)# U& N, O7 q9 X4 u7 O* z
- QUEST.addStartNpc(7056)( h6 G9 u2 G3 F5 k
- QUEST.addStartNpc(7012)
, I) s! {3 `" x! e: N" w - QUEST.addStartNpc(7009)+ b* S4 b- T8 D% c% m9 h
- QUEST.addStartNpc(7011)6 }/ S8 T0 q$ G, r5 N5 @: v
- " y! V! E3 c) p9 X$ _
- STARTED.addQuestDrop(KELTIR_NPC_ID,FANGS_ITEM_ID,DROP_RATE)0 L; M# B. h' d, W7 I9 T, t7 v
- STARTED.addKillId(KELTIR_NPC_ID)
, w# b5 g3 x8 b5 U: {# \* X - STARTED.addTalkId(7056); e9 h; f" y) o1 @* y. d1 \
- STARTED.addTalkI d(7012)
- O5 g7 l' b }' B& W% U* _ - STARTED.addTalkId(7009)6 n+ @6 o" b6 f- x
- STARTED.addTalkId(7011)
Скопировать код
) I% T% C$ i" B( v2 ~9 I {. H; p$ Y* x% R/ S4 f" c( p4 S' f
|