Зарегистрируйтесь сейчас чтобы найти еще больше друзей, и получить полноценный доступ ко всем функциям сайта!
Для просмотра Вам необходимо авторизоваться Если Вы еще не зарегистрированы, перейдите по ссылке:Зарегистрироваться
x
Хроники Interlude( r! C9 f( u8 Y: D( C
Сборка L2j
0 w, [9 ^; q0 w: i( yОбратите внимание: в файле htm стартового NCP обязательно должна быть ссылка на квест:
0 D! H4 a& G( P& T4 j( S- STARTED.addQuestDrop(KELTIR_NPC_ID,FANGS_ITEM_ID,DROP_RATE)
Скопировать код Для этого квеста больше ничего не надо. Все необходимое для корректной работы квеста уже добавили. Вот полный текст квеста:
( m/ e4 ?. v7 J! B# ~1 B2 F# S8 _7 d. l8 B& v- |
- if getCount(st) >= 4 :. C h r9 F- P f
- completed(st); [) z3 K2 t( i8 A! a' j
- return0 x$ ?, g5 `- y8 g4 M
! y9 s& c6 P/ @" D) r- class Quest (JQuest):- c# N/ `3 s. ~( ?& j
- def __init__(self,id,name,descr): JQuest.__init__(self,id,name,descr)
+ X/ |) @* q @; M - def onEvent (self,event,st):
& V4 i7 L1 n, f6 d8 W$ f- q - id = st.getState()
' ? Z a9 X& k9 Y& @ - if id == CREATED : st.setState(STARTED)
6 G, X- t" X( P5 O. H - elif id == COMPLETED: pass+ _2 F3 a4 Y1 w5 I. e# L
- elif id == STARTED : check(st)
6 u4 e, _$ ^& H4 O2 J; }+ F. Z: O - return
8 S4 i" @7 w" [! C: T - . C5 P) d7 F$ P5 j" L
- QUEST = Quest(201,"Tutorial", "Tutorial quest")
, ~" v/ V% V/ K - CREATED = State('Start', QUEST)& C8 W( T# F% K. C3 |" }
- STARTED = State('Started', QUEST)
Y! g( d1 O, [- F; Z3 M( j: U7 x - COMPLETED = State('Completed', QUEST)
0 @ e9 e; t5 y$ A+ v$ I( `$ K - 4 [* R# r; ]1 ~0 t' `9 ^' d/ R
- QUEST.setInitialState(CREATED)' ~, u% f/ _+ B
- QUEST.addStartNpc(7056)5 g: K4 k# c2 a+ f- e
- STARTED.addQuestDrop(KELTIR_NPC_ID,FANGS_ITEM_ID,DROP_RATE)
Скопировать код Теперь рассмотрим, как это работает.
3 J$ T& W0 j) U1 {( VИгрок подходит к начальному NCP (в данном случае 7056), нажимает на «Quest». Квест будет создан и состояние квеста перейдет к CREATED и игроку будет показана страничка Start.htm с описанием квеста. Тогда метод onEvent, поле открытия странички Start.htm переведет состояние квеста в STARTED и игроку будет показана страничка Started.htm, где будет опсание того, как найти keltirs и .т.д.' [, L; S' {$ k) P! v _1 @
3 k" V5 t( o# ^0 y G7 Y, g/ V! B8 L
6 S% [- R' V1 O0 D3 l% AПри состоянии STARTED будет зарегистрирован дроп «fangs» при убийстве keltirs. Игрок может вернуться к стартовому NCP и спросить о квесте – метод onEvent будет вызван снова. Если у игрока не хватает необходимого количества предметов, то метод check() не переведет квест в следующее состояние и Started.htm будет показана снова. Но если игрок собрал необходимее количество предметов (в данном случае 4 клыка), то метод check() вызовет метод completed() который переведет квест в новое состояние COMPLETED, заберет все клыки, даст карту мира, т.к. это награда за квест, покажет Completed.htm и завершит квест.3 m4 Q- s4 J, @9 f" e+ R4 e- m
5 r9 g' ~+ l; ^9 p
; _! p' h- R6 k. P- R; VТеперь давайте сделаем наш квест более похожим на то, что он должен из себя представлять.; f# X: p" J) A+ n5 S$ N; I
Прежде всего у нас есть 3 метода для объявления их в Яве – onTalk, onKill и onEvent. Если методы onTalk и onKill не объявлены, то за них все будет делать метод onEvent, т.е. определять квестовых монстров и вызывать диалоги NCP. Есть примечание, методы onTalk и onKill будут вызывать только диалоги с NCP в зависимости от текущего состояния квеста. Метод onKill будет вызываться только тогда, когда мы убиваем квестового монстра.. S( _7 n! G t2 f
: c. M+ w/ } ^0 d3 v- ^- |1 E! B. K3 t8 i* G
Давайте рассмотрим как вызывается метод onKill при убийстве keltir в состоянии квеста STARTED:
1 ^5 M C# Z6 s3 R; f- STARTED.addKillId(KELTIR_NPC_ID)
Скопировать код и метод onKill в классе Quest:; y/ _' w( n$ X) W& l
1 I- y8 n! p: x5 Z- class Quest (JQuest):6 z( [# K- u7 | ]- R4 W+ o
- ...( D8 ?2 {' ^& |0 l
- def onKill (self,npcId,st):& `9 e7 s: L* U3 o; B
- if npcId == KELTIR_NPC_ID:
9 b7 J+ @" I. T - n = getCount(st)- f3 v) c" ]2 y
- if n == 0:+ [/ ^5 N9 L5 N+ D+ `- X& Z
- return "Chat0.htm"
2 A" V) J2 D. z+ D8 h) S6 g - elif n == 1:6 J4 p4 ~ i. d( x. A
- return "Chat1.htm"3 }. d3 W) ^0 c6 {
- elif n >= 4:( H/ j! s- y5 q6 T/ e$ l# O; A
- return "Chat4.htm"
, q" G5 p! j6 I" A: P' o, F - return "Collected "+str(n)+" of 4 fangs"
/ n1 v6 O4 l0 D& C$ x* r4 E - return
Скопировать код Метод onKill (а так же метод onTalk) имеет следующие параметры:3 m Z* t% l! t/ @4 x* K
5 ^& ^* S/ E6 Y( S5 Q- E
; a. y% I; ~! R6 b- ?, q• self – квест4 b4 w$ E( s! T
• npcId – ID NCP, которого мы должны убивать (если это метод onTalk, то ID того NCP, с которым мы должны поговорить).8 U' r/ r4 ? H& w |; d' J0 E% \
• st – текущее состояние игрока.+ v6 w) S/ s i$ [& v7 x
, `( V" g' J# M# m$ `- x
/ N/ z, O5 ^) L4 F- g3 ?1 j" aВ этом методе мы проверяем и отмечаем, является ли убитый NCP keltir’ом. В основном эта проверка не нужна, т.к. у нас только KELTIR_NPC_ID.0 q% r/ y8 e5 q& M
+ G' F! Z$ C! t: E8 t, N. ]0 ?
! M5 D8 W) l' B# \3 F/ n3 E8 j' dЗатем проверяем количество предметов (в данном случае количество клыков), и если их вообще нет, то возвращаем строку "Chat0.htm", если только один предмет, то возвращаем строку "Chat1.htm", если же предметов 4 или больше, то "Chat4.htm". Если строка возвращена из методов onEvent, onKill или onTalk, то сервер покажет соответствующие htm. В Chat0.htm может иметь следующий текст: «Вы не имеете ни одного клыка, возвращайтесь позже, когда соберете 4 штуки и бла, бла, бла…», в Chat1.htm может быть следующий текст: «У Вас всего 1 клык, по этому соберите еще…». В Chat4.htm – «Вы собрали необходимое количество предметов, возвращайтесь к вашему тренеру, что бы завершить квест…»! C- T: z' C) c% t# ? p
f. m; W) t! J$ z
C2 b1 F* p4 S! lПримечание: если в строка return начинается с "<html>", то будет показана страничка html с текстом, который стоит далее. Так вместо:( R2 g# E. A: u9 @" {4 V
return "Chat4.htm"9 a* U% R5 u9 f/ |9 S4 e9 C
, M5 M \( ^/ S; d( @5 `4 S% C) N+ _5 X4 Q& f3 ?
можно поставить:
" O7 k5 K# H8 ]+ e, O- return "<html><body>Return to your trainer to complete the quest</body></html>"
Скопировать код Так же если строка заканчивается без .htm или в начале нет <html>, то текст будет выведен, как системное сообщение в окне чата. В нашем случае мы сделаем так, что бы при каждом убийстве keltik выводилось системное сообщение: «Собрано N из 4-х клыков».
7 {3 B% u8 \0 W$ r/ t' x0 Q4 ~
) c( _3 K$ O2 v J- N1 r
- |0 K( {( K& R. \( V3 Y( iНаш код для onKill имеет один недостаток. Он будет постоянно показывать Chat0.htm, Chat1.htm и Chat4.htm, нам же необходимо, что бы Chat0.htm и Chat1.htm показывались только один раз. Как нам это сделать? С помощью переменных.- d( H8 {; u; @7 y8 X' h3 E* e
+ j) j6 s3 x; T
' ^- R8 X- T, P# Q3 q B1 A
В каждом квесте строки могут храниться с помощью переменных. Эти переменные сохраняются в Вашей БД. В каждом методе мы можем назначить, прочитать и удалить переменные. Давайте изменим метод onKill, так что бы каждый диалог вызывался только один раз.
% K# k: N& d8 _" z v- def onKill (self,npcId,st):% Y1 |1 T5 s ^& w
- if npcId == KELTIR_NPC_ID:- l0 ~7 C4 @ s+ S1 A
- n = getCount(st)& J8 V7 L7 c7 u; I! k! K3 I" J+ J
- if n == 0:
; y- O8 S4 e( s5 L9 M: p - if st.get('chat0') == None :* k: W7 v, C) W) i$ Q* |
- st.set("chat0", "true")& f2 h8 T% ]& y- s# x2 s' p q& c
- return "Chat0.htm"7 ~: P g; n' U( s! \$ I! d/ H
- elif n == 1:9 O; K9 B: T1 B
- if st.get('chat1') == None :9 L4 L4 t6 b3 a( H) k) M! J
- st.set("chat1", "true")
^6 u% v0 w/ S! j) _ - return "Chat1.htm"# U; j6 q# C z' X
- elif n >= 4:
& F$ n6 }$ p3 m( N - return "Chat4.htm") R9 w! I k/ R" ]1 e. e- ?8 F
- return "Collected "+str(n)+" of 4 fangs"
- E/ D! r# T7 X3 Z8 ?! e8 p8 u4 k - return
Скопировать код Если у игрока нет клыков (n=0), то мы получаем занчение переменной 'chat0'. Когда метод onKill вызван в первый раз, то пока ни каких переменных не имеется и python возвращает значение None. В этом случае объявляется переменная и показывается диалог Chat0.htm. Когда мы убиваем keltir, но не получаем с него клык, функция st.get('chat0') возвращает строку true, а не None. И во второй раз окно с Chat0.htm не появится, но в окне чата появится строчка «Collected 0 of 4 fangs». По тому же принципу сделано и с Chat1.htm.
% d1 M; y% J( r
+ k6 u1 C7 Q! f( ~# R" G
$ w/ Z/ T1 v8 M3 @7 g) Z0 F# rВот конечный рабочий вариант квеста:) S9 ~8 @+ `& x
- import sys
" A: ^: m# F4 j( T - from net.sf.l2j.gameserver.model.quest import State: O/ o( G& W" L6 W* s5 y
- from net.sf.l2j.gameserver.model.quest import QuestState- `! q' D; V: F
- from net.sf.l2j.gameserver.model.quest.jython import QuestJython as JQuest2 Q! x! j4 I4 e" r7 F9 Q4 G0 a
' T: P0 |$ K0 \8 ^+ s% q0 m- KELTIR_NPC_ID = 12082. [) T& f" V) O7 G
- FANGS_ITEM_ID = 1859
$ p. c% l0 I; G% b - DROP_RATE = 500000
, I- ?/ c; A3 h5 z! x, k7 T* z - 2 E3 |0 I4 i- m( i' W
- WORLD_MAP_ITEM_ID = 1665
7 Z( m Z& o0 w& x5 `* v$ i/ e6 Z
* Q4 ~! m4 {- R/ @- def getCount(st) :
, G# i3 J7 v- s. X1 R - return st.getQuestItemsCount(FANGS_ITEM_ID)$ S0 j$ N& k7 J& P5 ~1 w
- y' C% h5 i+ t4 c. Z% P- def completed(st) :6 h. i, i# F: j
- st.setState(COMPLETED)
: a. B5 J# @: | ^- o0 I" b/ e - st.clearQuestDrops()
6 ]; _7 ]3 }( a8 n& O; V# }- v - st.takeItems(FANGS_ITEM_ID,-1)' I* x: ]* b) n6 a4 G8 y9 f! X
- st.giveItems(WORLD_MAP_ITEM_ID,1)8 W( g& \9 F% ]4 O1 Y0 `1 }4 R: L
- st.exitQuest(False)8 \, s9 u$ t* P, T. i4 a- a
- return
7 t) j9 {/ ]# V) b% L - 6 g3 K) g( T+ f
- def check(st) :% ? d1 w$ d2 h: s8 k! y# |( B
- if getCount(st) >= 4 :
) {* ?8 @6 @" f! O* Y& { - completed(st)" ~$ f) S9 Z: o* u8 e
- return5 P9 [2 n( u' K' j) o$ W
- & ]3 F$ u4 j8 v- J3 w
- class Quest (JQuest):( { A* k6 e7 t! k. N
& ]) h# O" b* A# l- def __init__(self,id,name,descr): JQuest.__init__(self,id,name,descr)
" A3 J% m# T6 c; N
6 [; R$ a) t# U6 Q% N- def onEvent (self,event,st):5 h \. G6 u$ F. ~, V
- id = st.getState()
) W* J. P/ @! J' Q/ ^$ X$ L - if id == CREATED : st.setState(STARTED)
n9 ?8 X! b& b2 a/ E, N4 X/ @ - elif id == COMPLETED: pass
8 x0 s& L$ v. ?7 V - elif id == STARTED : check(st)
- c+ I, y6 w0 E; L1 e - return( l. X0 v7 G% k3 t) t+ s6 v# M
3 E8 `* W- H( ^7 p- s- def onKill (self,npcId,st):0 [" C$ o! ?4 g7 f4 O8 e
- if npcId == KELTIR_NPC_ID:* [6 R" R; P& Z
- n = getCount(st)
+ `6 |& @% _# \6 V! r& T9 i0 G - if n == 0:
( u! m. y; c* B; E% z$ l - if st.get('chat0') == None :* @2 @8 e+ A, ~# v
- st.set("chat0", "true")
9 l% A( R# L( d/ R8 T - return "Chat0.htm"/ F( V6 O2 {0 C& h8 ]
- elif n == 1:5 R' s6 V7 t2 I
- if st.get('chat1') == None :
) |& f7 ?& U7 B4 }$ o I6 M! T3 a - st.set("chat1", "true")) V# K1 [ D2 y1 P/ M0 @
- return "Chat1.htm": l# ~1 f3 A1 B1 A8 O$ [4 w
- elif n >= 4:3 B! S. ~4 E3 | |2 `# ]& {
- return "Chat4.htm"1 f: Q: B( L5 i; c
- return "Collect "+str(n)+" of 4 fangs"+ g$ r; T- m: J
- return, a5 r0 A4 w, j( }- U' u# h6 D
. c" L( j: G/ Z' _, Q4 P( Q- QUEST = Quest(201, "Tutorial", "Tutorial quest")
' O. s( A; {" ^; @6 W w' ^+ | - CREATED = State('Start', QUEST)! J5 s! }( w* H- b- ^
- STARTED = State('Started', QUEST)6 `" Z+ Z" U1 [; r% C4 S" Y% a
- COMPLETED = State('Completed', QUEST)$ [7 Q$ A. B% b
- " A* L, ~7 w- p" G9 [1 w6 j
- QUEST.setInitialState(CREATED)3 X; F4 L# n; O
- QUEST.addStartNpc(7056)
- M( r& ^3 W, k* z4 O" w! m& a - QUEST.addStartNpc(7012)8 d5 A$ S3 R2 Q& ^6 ]. ]9 i. L
- QUEST.addStartNpc(7009)
' U" C* \ M# \ - QUEST.addStartNpc(7011)% o7 A0 J0 `- o8 ?2 o
& W1 N: d9 Z0 R" q- B; j- STARTED.addQuestDrop(KELTIR_NPC_ID,FANGS_ITEM_ID,DROP_RATE)( S& a$ S8 {5 L$ _: p7 f, S
- STARTED.addKillId(KELTIR_NPC_ID)+ P3 `) ^% y( `: `0 L2 b# m
- STARTED.addTalkId(7056)+ {( ^$ b5 P/ g( s. v! Z* G
- STARTED.addTalkI d(7012)
, O" w, e( @ R6 y0 p: G0 D - STARTED.addTalkId(7009)
/ @2 v+ r- [* X# } - STARTED.addTalkId(7011)
Скопировать код 8 b$ R' ~# ~) S+ ]
0 K! A- ]: o' h8 t/ E6 G! m |