Зарегистрируйтесь сейчас чтобы найти еще больше друзей, и получить полноценный доступ ко всем функциям сайта!
Для просмотра Вам необходимо авторизоваться Если Вы еще не зарегистрированы, перейдите по ссылке:Зарегистрироваться
x
Хроники Interlude
7 s7 j1 C6 ]+ v6 A$ tСборка L2j a0 A) n" t' f
Обратите внимание: в файле htm стартового NCP обязательно должна быть ссылка на квест:
8 B1 F$ ?7 I) t, Y" A5 F- STARTED.addQuestDrop(KELTIR_NPC_ID,FANGS_ITEM_ID,DROP_RATE)
Скопировать код Для этого квеста больше ничего не надо. Все необходимое для корректной работы квеста уже добавили. Вот полный текст квеста:
\6 Q3 a( k7 M# h+ D+ B
+ {4 Z. \6 v! f: [, k) x- if getCount(st) >= 4 :
$ B' `+ \& K& |5 M - completed(st)
7 `! R' M* T0 C! B$ n - return. C- M, v9 ^4 i
3 B, l9 E u% T* f5 g/ [6 n7 Z- class Quest (JQuest):
% L+ i8 a$ ?# { - def __init__(self,id,name,descr): JQuest.__init__(self,id,name,descr)
# |8 [" Z( a8 L - def onEvent (self,event,st):
7 }# }! K* D2 S - id = st.getState()
# y- G- k: z3 w4 x) }8 c" } - if id == CREATED : st.setState(STARTED)6 }! w9 m- i7 {; M3 p
- elif id == COMPLETED: pass+ v+ @9 M1 E2 t( A# s' w7 N
- elif id == STARTED : check(st)$ V0 i5 d) J0 p4 Z
- return
- c1 [9 w4 V4 Y7 k, L6 w) } - 3 J& p6 Z+ z2 h; D5 A# p& U0 j1 t- O
- QUEST = Quest(201,"Tutorial", "Tutorial quest")4 e/ a: o; j5 l% c1 [9 S4 s# T
- CREATED = State('Start', QUEST)8 N5 M, R" ]/ r
- STARTED = State('Started', QUEST)
; G, C3 Y$ `' V8 X7 \: R3 u" M' g$ Q - COMPLETED = State('Completed', QUEST)9 r( z# n( f' E6 H8 A3 `
- ) h. v1 M7 e& Z" C, O
- QUEST.setInitialState(CREATED)
, l* {) i e0 {8 q% s - QUEST.addStartNpc(7056)4 S) ~. q5 D H: @& P* _
- STARTED.addQuestDrop(KELTIR_NPC_ID,FANGS_ITEM_ID,DROP_RATE)
Скопировать код Теперь рассмотрим, как это работает.4 h7 m9 E& m- z4 t* @5 W
Игрок подходит к начальному NCP (в данном случае 7056), нажимает на «Quest». Квест будет создан и состояние квеста перейдет к CREATED и игроку будет показана страничка Start.htm с описанием квеста. Тогда метод onEvent, поле открытия странички Start.htm переведет состояние квеста в STARTED и игроку будет показана страничка Started.htm, где будет опсание того, как найти keltirs и .т.д.
7 Z* I/ b" b0 l+ H6 n0 s" X* I( _
& J6 \2 D: o. N
' G, l, w3 ^- {7 O4 S; bПри состоянии STARTED будет зарегистрирован дроп «fangs» при убийстве keltirs. Игрок может вернуться к стартовому NCP и спросить о квесте – метод onEvent будет вызван снова. Если у игрока не хватает необходимого количества предметов, то метод check() не переведет квест в следующее состояние и Started.htm будет показана снова. Но если игрок собрал необходимее количество предметов (в данном случае 4 клыка), то метод check() вызовет метод completed() который переведет квест в новое состояние COMPLETED, заберет все клыки, даст карту мира, т.к. это награда за квест, покажет Completed.htm и завершит квест.
" q' {- F2 c! h! Y2 I
) I$ b. r4 G4 E' a5 e1 m, E; _ X, u8 Y W' `3 U
Теперь давайте сделаем наш квест более похожим на то, что он должен из себя представлять.
/ f: O# `" I7 v9 I5 cПрежде всего у нас есть 3 метода для объявления их в Яве – onTalk, onKill и onEvent. Если методы onTalk и onKill не объявлены, то за них все будет делать метод onEvent, т.е. определять квестовых монстров и вызывать диалоги NCP. Есть примечание, методы onTalk и onKill будут вызывать только диалоги с NCP в зависимости от текущего состояния квеста. Метод onKill будет вызываться только тогда, когда мы убиваем квестового монстра., y; v6 X- x/ k" P) H
( ], y! l8 L' z# h9 D7 G4 o
' x! Y, K, ]* y: T1 zДавайте рассмотрим как вызывается метод onKill при убийстве keltir в состоянии квеста STARTED:
' I6 V3 ?3 v. W% ~( |0 y- STARTED.addKillId(KELTIR_NPC_ID)
Скопировать код и метод onKill в классе Quest:
4 ]3 W- P! h) I5 {+ F. S1 x$ H
0 _2 n* u& Y7 a* t7 l% z ]- class Quest (JQuest):
Y. t) w5 @6 z - ...2 k2 M5 n6 W5 n' L2 W- B, z( t' E
- def onKill (self,npcId,st):6 K$ t1 {+ g# g
- if npcId == KELTIR_NPC_ID:3 W' }# e6 o! A4 G4 p
- n = getCount(st)& N# f+ k6 z' B
- if n == 0:
" f$ X' b5 c2 \1 Z3 J. O4 w; ?) |" Z8 b - return "Chat0.htm" M$ `9 c# O0 `1 z& |6 Y
- elif n == 1:
9 ~' {, d+ N. f! O4 H - return "Chat1.htm"- d7 t( L' J! v3 @" A( c
- elif n >= 4:( I \ X4 i' Q3 C3 M/ v* C& k
- return "Chat4.htm"# b; K, l; O( Y% q. [
- return "Collected "+str(n)+" of 4 fangs"
/ z+ ?& S8 N* \) o( `1 t0 s. E - return
Скопировать код Метод onKill (а так же метод onTalk) имеет следующие параметры:
2 c' S/ G2 C. ~' N8 x$ g. F
, ~% [ g2 a# E1 r% W5 Y' o# E+ U3 Z( N/ U1 E% k8 q! I+ S
• self – квест0 J0 ~7 d/ [. U! f: h
• npcId – ID NCP, которого мы должны убивать (если это метод onTalk, то ID того NCP, с которым мы должны поговорить).
' J1 x0 x2 }5 P+ l• st – текущее состояние игрока.
& B4 L3 G( Y) F/ a- @9 g8 ?; D7 v) Z
& v8 s& S, z5 V0 c
& `2 q) [1 z& {$ j* zВ этом методе мы проверяем и отмечаем, является ли убитый NCP keltir’ом. В основном эта проверка не нужна, т.к. у нас только KELTIR_NPC_ID.
& L6 P7 f! \ F8 b
0 e$ B( C1 p; d
; u' e: A: g1 i& @& k! C! kЗатем проверяем количество предметов (в данном случае количество клыков), и если их вообще нет, то возвращаем строку "Chat0.htm", если только один предмет, то возвращаем строку "Chat1.htm", если же предметов 4 или больше, то "Chat4.htm". Если строка возвращена из методов onEvent, onKill или onTalk, то сервер покажет соответствующие htm. В Chat0.htm может иметь следующий текст: «Вы не имеете ни одного клыка, возвращайтесь позже, когда соберете 4 штуки и бла, бла, бла…», в Chat1.htm может быть следующий текст: «У Вас всего 1 клык, по этому соберите еще…». В Chat4.htm – «Вы собрали необходимое количество предметов, возвращайтесь к вашему тренеру, что бы завершить квест…», G1 N! T( V! H, D! ^! y- d
1 F" O) i+ W! O2 h- [. @
# f2 i* o3 _4 @$ p6 u% j: c WПримечание: если в строка return начинается с "<html>", то будет показана страничка html с текстом, который стоит далее. Так вместо:4 {$ K. u8 E+ _- V0 C- v+ ]
return "Chat4.htm"0 _. m7 g6 l+ k% D0 D/ z7 h
# K; Z2 _( [1 k$ W
6 G0 l1 s0 E/ C! \5 k9 v, v
можно поставить:
! P Q$ N( c! q- return "<html><body>Return to your trainer to complete the quest</body></html>"
Скопировать код Так же если строка заканчивается без .htm или в начале нет <html>, то текст будет выведен, как системное сообщение в окне чата. В нашем случае мы сделаем так, что бы при каждом убийстве keltik выводилось системное сообщение: «Собрано N из 4-х клыков».2 A/ D7 P$ k7 M! b) M- t* v
0 s: T3 P4 S0 @: U& E# v W @
5 T Y/ `7 \+ r4 SНаш код для onKill имеет один недостаток. Он будет постоянно показывать Chat0.htm, Chat1.htm и Chat4.htm, нам же необходимо, что бы Chat0.htm и Chat1.htm показывались только один раз. Как нам это сделать? С помощью переменных.
# c+ J2 X0 _' J ?" Y4 @3 l9 R/ k
* Q# b( } ? T7 F" u6 T( x
# q7 Z) u& J# I( ^6 T) W4 H) JВ каждом квесте строки могут храниться с помощью переменных. Эти переменные сохраняются в Вашей БД. В каждом методе мы можем назначить, прочитать и удалить переменные. Давайте изменим метод onKill, так что бы каждый диалог вызывался только один раз.. ]! C' @/ k$ s; B: A+ l
- def onKill (self,npcId,st):
4 M9 A& ]& a1 z5 E% \ - if npcId == KELTIR_NPC_ID:
* }# M$ Y' e& z: M/ A: u) b* s - n = getCount(st)
. c# P4 A, Z4 T; ?6 n1 o - if n == 0:+ q$ T& M# P& E0 A
- if st.get('chat0') == None :" ^. T$ v& \( ?- {) D/ s0 m3 f7 n
- st.set("chat0", "true")
# |+ `6 f' T- x N0 Z, t2 @ - return "Chat0.htm"- Z; A" W6 G( u" {5 D
- elif n == 1:
" w0 ?$ z& X! v8 X - if st.get('chat1') == None :2 c* E @$ o# k
- st.set("chat1", "true")7 [3 a% Y5 M& N) ]4 k/ \, g
- return "Chat1.htm"1 B' v1 O2 I6 l7 {7 c( s
- elif n >= 4:) r5 A) C; P- [6 ~; M2 d$ i8 A
- return "Chat4.htm"7 z) X1 M- |/ a5 _ E6 J
- return "Collected "+str(n)+" of 4 fangs"
3 X- X+ L {2 A9 h c: J) ~% L# z - return
Скопировать код Если у игрока нет клыков (n=0), то мы получаем занчение переменной 'chat0'. Когда метод onKill вызван в первый раз, то пока ни каких переменных не имеется и python возвращает значение None. В этом случае объявляется переменная и показывается диалог Chat0.htm. Когда мы убиваем keltir, но не получаем с него клык, функция st.get('chat0') возвращает строку true, а не None. И во второй раз окно с Chat0.htm не появится, но в окне чата появится строчка «Collected 0 of 4 fangs». По тому же принципу сделано и с Chat1.htm.
& b# p) s1 z L: X$ `8 ^! H& K1 K4 n m+ [) \
- U6 E- L- X$ j( @7 e0 l0 I
Вот конечный рабочий вариант квеста:' V5 m* s* }" g+ C9 }' i) Z
- import sys m% ?$ W* D; s( b
- from net.sf.l2j.gameserver.model.quest import State
! U# N2 s C* x$ B - from net.sf.l2j.gameserver.model.quest import QuestState
8 K- M3 L* X( s5 g: I3 O - from net.sf.l2j.gameserver.model.quest.jython import QuestJython as JQuest
7 h5 R2 m7 F+ p1 v5 g
) V h; ?- P* Z; G+ `+ w* l5 _- KELTIR_NPC_ID = 12082' |- i0 ?, E9 i. E$ j- k1 [, I
- FANGS_ITEM_ID = 1859* U7 f" d+ l3 ~! Z; p# ]5 k8 L1 w* b
- DROP_RATE = 500000& f5 K' W" E8 d1 i
- 0 c& i5 l6 t. |5 c! ^5 e
- WORLD_MAP_ITEM_ID = 1665
! X# j- t. F0 k0 O+ H4 ]" ^ - 4 z. p, z3 ~) o: h, z8 q
- def getCount(st) :
4 F; M' R( r ] - return st.getQuestItemsCount(FANGS_ITEM_ID)0 ~; T8 N! F- @) V, R- o
, |2 P! u. _' I- def completed(st) :
. \7 t x+ K4 d) S6 K! y4 y0 b2 ^1 d2 ~ - st.setState(COMPLETED)
. C, B: x5 R! g( z - st.clearQuestDrops(), |' G- t1 r! \& ^* _- b
- st.takeItems(FANGS_ITEM_ID,-1)1 V) T% ?1 j' o( [# M; Q
- st.giveItems(WORLD_MAP_ITEM_ID,1)0 j/ e% F; m+ f) a9 V
- st.exitQuest(False): }, z" \" F$ Z3 X
- return
; k- s8 W$ i% X: U* _
2 J9 y# t+ ?, l- def check(st) :+ L3 R( t4 u9 f% V/ s
- if getCount(st) >= 4 :
9 O9 q/ J' h# L! W' T - completed(st)
" v9 ]; w _$ l" |% ]& q* R - return
2 w6 |. D _5 d2 u9 b0 R# x - ' B4 F8 p8 i" c! u1 r6 L" N- }$ `
- class Quest (JQuest):9 P* c% v- d. n y
- " p9 n0 P2 T4 B$ S+ L" r% g
- def __init__(self,id,name,descr): JQuest.__init__(self,id,name,descr)
P& E& Q a B7 Z
3 j: N, n+ q# H$ a) B9 G- def onEvent (self,event,st):6 U% y$ c/ P/ T8 f) ]- n8 o9 Z
- id = st.getState()
2 ]( w: }( |' y, v9 M. Z2 T - if id == CREATED : st.setState(STARTED)7 e- X' q |, X: j
- elif id == COMPLETED: pass
" D9 _' R9 L; s; K n& { - elif id == STARTED : check(st)
$ n# G8 w, H& P, R8 j8 `9 @ - return
4 ~- ]! p, h+ t
# Q* {8 a- v) L+ r- def onKill (self,npcId,st):* m1 J$ R8 w5 i5 n: S3 A2 l8 B
- if npcId == KELTIR_NPC_ID:
/ k( `9 ~9 N# |* C+ c# k - n = getCount(st)
" [( R) Z9 A! F! v8 N - if n == 0:4 T0 T8 X) a1 ^
- if st.get('chat0') == None :
, a* x7 g7 w/ b; x5 } - st.set("chat0", "true")
d" L) c ~: S' j - return "Chat0.htm"
, E# N# Y2 \: [$ H4 ? - elif n == 1:2 Z4 s: n3 v6 H: x# e5 E
- if st.get('chat1') == None :
) c* \3 W; q' _4 { - st.set("chat1", "true")
/ X+ `, ? T$ l# E2 M0 B7 b - return "Chat1.htm"
( ?6 S+ T6 p9 q( n U3 S - elif n >= 4:
2 `3 a3 `! S& |8 A& K& ]( W" g6 o - return "Chat4.htm"* Z; \: z- p# G/ t: y
- return "Collect "+str(n)+" of 4 fangs"8 o7 Q" N& L0 q3 H8 B6 g
- return
; l- R' r: H2 q( s$ r
" ~/ \$ z | {! |- QUEST = Quest(201, "Tutorial", "Tutorial quest")
, W3 }/ s! S' o# D - CREATED = State('Start', QUEST). Y7 m) N! }0 f
- STARTED = State('Started', QUEST)1 B- ?: k# t1 L! {
- COMPLETED = State('Completed', QUEST); H7 _( B, h& s& I3 @6 p0 y
- 3 v; e5 Q; k. S9 L7 E; V" D
- QUEST.setInitialState(CREATED)
( Q) m- _* f8 s5 B6 U! T6 `! z X - QUEST.addStartNpc(7056)* W+ r- H' a* a( `$ I [3 F" u
- QUEST.addStartNpc(7012)
: f' b9 c I6 F# R - QUEST.addStartNpc(7009)1 C* y# }/ `- Y# l
- QUEST.addStartNpc(7011)3 ^0 u3 J, Y# }+ ?1 R5 r/ U. j
" P. u' w5 X9 z$ Y- STARTED.addQuestDrop(KELTIR_NPC_ID,FANGS_ITEM_ID,DROP_RATE)
1 w# V$ L: V* a1 o - STARTED.addKillId(KELTIR_NPC_ID)
) I2 c$ _ i9 H7 l4 i - STARTED.addTalkId(7056)/ i* x! t+ f; b! b( l
- STARTED.addTalkI d(7012); X: v1 T. U# e: T+ b
- STARTED.addTalkId(7009)
N% z* `' R( f) Q2 P6 K2 \% i - STARTED.addTalkId(7011)
Скопировать код
3 l( F. ]& `+ i) @' D7 |& }$ r: h }+ e0 y# H; z; v5 j; l5 z. v
|