Зарегистрируйтесь сейчас чтобы найти еще больше друзей, и получить полноценный доступ ко всем функциям сайта!
Для просмотра Вам необходимо авторизоваться Если Вы еще не зарегистрированы, перейдите по ссылке:Зарегистрироваться
x
Хроники Interlude( c# r' [5 W1 `2 ~
Сборка L2j: }) Q0 {. O" |: d
Обратите внимание: в файле htm стартового NCP обязательно должна быть ссылка на квест:
* s; w! H3 j: r* ], f$ M- STARTED.addQuestDrop(KELTIR_NPC_ID,FANGS_ITEM_ID,DROP_RATE)
Скопировать код Для этого квеста больше ничего не надо. Все необходимое для корректной работы квеста уже добавили. Вот полный текст квеста:$ w4 ]. M4 E; ^( x
0 I2 m+ f8 \* {9 a
- if getCount(st) >= 4 :
5 b! n _* S2 V u4 \/ F+ D; [ - completed(st)* x/ b" V1 p3 P8 j- \- \8 Y @7 K
- return" s: g1 Z1 s' ^( W" i$ o" p& v
- 8 H, _4 B6 O4 A: S+ z
- class Quest (JQuest):
h6 h5 {/ V" ~% H+ Y `/ E7 @, f - def __init__(self,id,name,descr): JQuest.__init__(self,id,name,descr)
% N Z9 X' {+ ^6 E4 P ?2 W - def onEvent (self,event,st):0 G$ r7 q) _5 _9 B: u' U
- id = st.getState()$ F" e- K9 V t) S5 B
- if id == CREATED : st.setState(STARTED)9 S1 a% D6 i4 |
- elif id == COMPLETED: pass7 i: r. {# a6 |1 K' r3 a0 s( O' I) N
- elif id == STARTED : check(st)/ Y; p6 p' E" E, B
- return- G* x5 k+ s" q0 a) ^
- / {0 _4 \ j/ }: E
- QUEST = Quest(201,"Tutorial", "Tutorial quest")
6 ?; f2 a' A% `( J - CREATED = State('Start', QUEST)0 J" P0 Q2 c3 W) _5 \6 Y" t* }. u( U
- STARTED = State('Started', QUEST)
8 B' \ ~* T$ P" u, ~ - COMPLETED = State('Completed', QUEST)- V$ ]& N4 y) ^0 }4 u) }1 E* v- p8 N
- s, Q9 D! ]6 B
- QUEST.setInitialState(CREATED)
7 v0 x) X1 z" J* ] - QUEST.addStartNpc(7056)) H) O% @& n; V1 O* }( ]( K
- STARTED.addQuestDrop(KELTIR_NPC_ID,FANGS_ITEM_ID,DROP_RATE)
Скопировать код Теперь рассмотрим, как это работает.% h* V" O; f) b& v
Игрок подходит к начальному NCP (в данном случае 7056), нажимает на «Quest». Квест будет создан и состояние квеста перейдет к CREATED и игроку будет показана страничка Start.htm с описанием квеста. Тогда метод onEvent, поле открытия странички Start.htm переведет состояние квеста в STARTED и игроку будет показана страничка Started.htm, где будет опсание того, как найти keltirs и .т.д.
" Z. ^8 p) ?) V) R- u9 K/ P x3 g+ \6 D2 q' F
) U% N+ N. c& u5 d3 Q# C* D+ GПри состоянии STARTED будет зарегистрирован дроп «fangs» при убийстве keltirs. Игрок может вернуться к стартовому NCP и спросить о квесте – метод onEvent будет вызван снова. Если у игрока не хватает необходимого количества предметов, то метод check() не переведет квест в следующее состояние и Started.htm будет показана снова. Но если игрок собрал необходимее количество предметов (в данном случае 4 клыка), то метод check() вызовет метод completed() который переведет квест в новое состояние COMPLETED, заберет все клыки, даст карту мира, т.к. это награда за квест, покажет Completed.htm и завершит квест.
% j( S/ u" R- w* i* l5 u; \
8 j3 d% w8 ?' u, ~# G4 H. O
; a: f% V: A( A3 F* s6 b" oТеперь давайте сделаем наш квест более похожим на то, что он должен из себя представлять.3 Y2 e- l; l$ q5 `: z0 |
Прежде всего у нас есть 3 метода для объявления их в Яве – onTalk, onKill и onEvent. Если методы onTalk и onKill не объявлены, то за них все будет делать метод onEvent, т.е. определять квестовых монстров и вызывать диалоги NCP. Есть примечание, методы onTalk и onKill будут вызывать только диалоги с NCP в зависимости от текущего состояния квеста. Метод onKill будет вызываться только тогда, когда мы убиваем квестового монстра.
+ U/ g5 U, z3 R/ N( Z% _$ c
2 |/ R; { b+ }, a
) C1 Z/ }" @- F! e( u* J6 H% rДавайте рассмотрим как вызывается метод onKill при убийстве keltir в состоянии квеста STARTED:- d2 K K& i9 a$ ~7 ]9 K8 W
- STARTED.addKillId(KELTIR_NPC_ID)
Скопировать код и метод onKill в классе Quest:
! I0 U8 L9 d! E5 C
' ?- \# [/ g8 V% }' }2 Y+ f+ i- class Quest (JQuest):
% O- e& z6 J$ N! I7 F - ...) ?- V" x& \- ~ f; m
- def onKill (self,npcId,st):+ e9 Q/ n f+ b9 v/ `
- if npcId == KELTIR_NPC_ID:
! Z+ P8 o9 g2 K* k4 { - n = getCount(st)
3 m6 Z$ f% p5 i F; U - if n == 0:
; n+ ]+ F z$ s5 }/ J( X( P6 r3 L - return "Chat0.htm"
' u. _* x( u8 N, N+ e - elif n == 1:
|" K+ K7 [6 D, g# @ - return "Chat1.htm": H. p6 P9 j/ a+ @+ z; z' w. e
- elif n >= 4:+ S# l; s$ F, I1 h N
- return "Chat4.htm"
: ?: Q0 h. m( t* J" f8 u8 X2 J - return "Collected "+str(n)+" of 4 fangs"
9 @$ M( r. e+ d9 t/ ]$ B1 f& [' Q - return
Скопировать код Метод onKill (а так же метод onTalk) имеет следующие параметры:( t3 K8 m& {- c( x
6 W7 W* h' t* z4 B' \
" |8 t+ p: m0 L. q$ Y• self – квест: X/ b0 H* J. D% q
• npcId – ID NCP, которого мы должны убивать (если это метод onTalk, то ID того NCP, с которым мы должны поговорить)., W" V4 h f* [# O) k
• st – текущее состояние игрока.
3 o: O1 e5 d% A. D( w- u8 s
+ s/ M( L( Y# ]# f0 h
# j8 M: M R, t) Z5 K9 KВ этом методе мы проверяем и отмечаем, является ли убитый NCP keltir’ом. В основном эта проверка не нужна, т.к. у нас только KELTIR_NPC_ID.$ ~# c' Y" J3 x, W
3 j* Y9 A i$ l L0 m$ X/ Q
5 a q& C7 }& z, {7 G1 }" `
Затем проверяем количество предметов (в данном случае количество клыков), и если их вообще нет, то возвращаем строку "Chat0.htm", если только один предмет, то возвращаем строку "Chat1.htm", если же предметов 4 или больше, то "Chat4.htm". Если строка возвращена из методов onEvent, onKill или onTalk, то сервер покажет соответствующие htm. В Chat0.htm может иметь следующий текст: «Вы не имеете ни одного клыка, возвращайтесь позже, когда соберете 4 штуки и бла, бла, бла…», в Chat1.htm может быть следующий текст: «У Вас всего 1 клык, по этому соберите еще…». В Chat4.htm – «Вы собрали необходимое количество предметов, возвращайтесь к вашему тренеру, что бы завершить квест…»/ N/ J# M; @& x, E& C7 a/ k
$ M _, U0 h) B0 |: p1 q+ _% f! k# `: K4 s8 `6 F
Примечание: если в строка return начинается с "<html>", то будет показана страничка html с текстом, который стоит далее. Так вместо:. F$ f8 r9 ~+ U1 K( t
return "Chat4.htm". m+ Z$ |! a4 F; @' u v6 Y7 p, C5 _
/ g7 \2 ` ~3 b: }0 W! w( |! Z! U( ~8 ~6 m6 m2 ?, [
можно поставить:3 f6 S0 `. A: ?) x% v
- return "<html><body>Return to your trainer to complete the quest</body></html>"
Скопировать код Так же если строка заканчивается без .htm или в начале нет <html>, то текст будет выведен, как системное сообщение в окне чата. В нашем случае мы сделаем так, что бы при каждом убийстве keltik выводилось системное сообщение: «Собрано N из 4-х клыков».5 O. L) v4 k2 ?4 |+ }1 B/ K Q9 u
1 z9 @. T5 H; F" _# [1 f
: Y2 p% E2 w7 \+ k/ X) n5 XНаш код для onKill имеет один недостаток. Он будет постоянно показывать Chat0.htm, Chat1.htm и Chat4.htm, нам же необходимо, что бы Chat0.htm и Chat1.htm показывались только один раз. Как нам это сделать? С помощью переменных.* H& P9 z2 s7 D e" \$ [2 `
/ A+ H; X( f: k' w9 U: o T
& x: s" m* g, D5 F1 G1 j9 r) dВ каждом квесте строки могут храниться с помощью переменных. Эти переменные сохраняются в Вашей БД. В каждом методе мы можем назначить, прочитать и удалить переменные. Давайте изменим метод onKill, так что бы каждый диалог вызывался только один раз.$ j) n4 \$ F# t2 V+ p
- def onKill (self,npcId,st):0 o) g/ t3 x6 ?- x8 p! S
- if npcId == KELTIR_NPC_ID:2 \% S' T8 h$ o* b* Y4 v6 M; |8 J# j
- n = getCount(st)9 ]: O+ N2 P# ?
- if n == 0:
( X' D" M- x+ K" D+ M - if st.get('chat0') == None :7 t; l% C2 W9 }' }3 |
- st.set("chat0", "true")% k* Y1 g" R* v4 |
- return "Chat0.htm"0 A- i4 c; z( F- e- J( D
- elif n == 1:8 D- E* {4 H$ o; f7 E* p, I
- if st.get('chat1') == None :
. ~; F+ `+ G2 C$ _ - st.set("chat1", "true")
1 T9 N+ y! H0 e0 T/ v2 n4 B# e - return "Chat1.htm"
6 M0 b5 z0 u+ d/ n3 @: `5 j - elif n >= 4:
/ H8 ^+ E8 H- f" z7 d$ `- E - return "Chat4.htm"4 [8 l% b: Q) ]! j! K3 y2 ]7 q! U q
- return "Collected "+str(n)+" of 4 fangs"
/ `. |6 a% N# U/ R& O7 ~4 k! }4 l) c - return
Скопировать код Если у игрока нет клыков (n=0), то мы получаем занчение переменной 'chat0'. Когда метод onKill вызван в первый раз, то пока ни каких переменных не имеется и python возвращает значение None. В этом случае объявляется переменная и показывается диалог Chat0.htm. Когда мы убиваем keltir, но не получаем с него клык, функция st.get('chat0') возвращает строку true, а не None. И во второй раз окно с Chat0.htm не появится, но в окне чата появится строчка «Collected 0 of 4 fangs». По тому же принципу сделано и с Chat1.htm.& d: b% v1 o2 t6 D; a- M
' w& |% X% b: ]8 f
; D. ?+ G) I# s2 VВот конечный рабочий вариант квеста:
1 M( z; \' W, _% g- \+ t; l! U- import sys
8 g' i# G. U( d( o) X+ T; ^; U - from net.sf.l2j.gameserver.model.quest import State1 Y. Z# Y& s1 m) a) B
- from net.sf.l2j.gameserver.model.quest import QuestState, Z( h; R' K8 L, F2 c
- from net.sf.l2j.gameserver.model.quest.jython import QuestJython as JQuest* ~: [! Q) _1 G
2 \ ^$ N2 T' J4 i% k! ~- KELTIR_NPC_ID = 12082* }! J( W/ k. [7 t9 ]& [. Z
- FANGS_ITEM_ID = 1859
. T# d- @) k2 n3 G% N1 Y3 X2 K7 t - DROP_RATE = 500000) Q7 ?3 m# t/ m: E% ]7 z6 r
+ m0 f a5 ?! R7 R9 ~: I- WORLD_MAP_ITEM_ID = 1665; o+ h1 N. t, C" p7 B+ C9 T
6 ]% Z* P- z F+ ]3 j- def getCount(st) :
* p) I- |6 M% I - return st.getQuestItemsCount(FANGS_ITEM_ID)
$ ~$ s! r0 o% E' J+ v - 9 \+ b1 x Q2 ?2 }% X" m
- def completed(st) :
1 D* x1 j# ]# u. M - st.setState(COMPLETED)( N1 `/ |7 ^/ Z
- st.clearQuestDrops()
2 O7 A" ~5 F" D2 J - st.takeItems(FANGS_ITEM_ID,-1)' S' u6 J7 P( G
- st.giveItems(WORLD_MAP_ITEM_ID,1)% s8 E4 x1 |1 _( y' R
- st.exitQuest(False)8 p2 N# @1 G! ] r
- return6 _( y8 l y+ B3 @/ N, I1 S1 ?
- % N6 J2 Y' x: g7 j* P6 R
- def check(st) :9 c0 S. Q: ~9 m! | ^! w1 a
- if getCount(st) >= 4 :
6 Z& e% W+ o3 `( k - completed(st)+ q0 }! ~3 f$ V6 n
- return- M0 X9 n* T/ `* r
, r$ T: \8 [" n* H- class Quest (JQuest):4 A4 \2 t) d+ I
- 2 p/ M0 Y9 n4 [3 _9 l
- def __init__(self,id,name,descr): JQuest.__init__(self,id,name,descr)
# _( z4 ^/ a: j
- N, x$ D `6 R) Q s; ~8 a" E- def onEvent (self,event,st):
. O. p" D m8 f M! Z - id = st.getState()
! @0 `0 h7 N/ e& C ^# G1 ] - if id == CREATED : st.setState(STARTED)
( o, F' j+ D- y - elif id == COMPLETED: pass
$ J3 {+ K8 S0 O& t) T% W9 W - elif id == STARTED : check(st)! S; f9 ]9 g! t2 L& T
- return
8 ^2 l6 ~2 m* ?5 H8 F - # n7 N1 R" A. D7 z# V0 x) B: }$ X
- def onKill (self,npcId,st):
& n' z* y: l# r - if npcId == KELTIR_NPC_ID:
2 c3 f% F! ^; ^+ R$ {0 f( B$ m - n = getCount(st): d! n( X( m% l3 e6 i* T
- if n == 0:
1 g2 e6 P3 p% m - if st.get('chat0') == None :4 e5 D2 N% `/ z/ }# d" \7 ?/ m
- st.set("chat0", "true"): k3 E/ m5 i3 S- [/ d
- return "Chat0.htm"
; U+ Y% \" b8 a: j - elif n == 1:
( u% C3 I/ j, N" b0 K( M - if st.get('chat1') == None :
% V+ l" R5 k9 |0 X" F - st.set("chat1", "true")* S k4 N7 K$ `! `2 n5 w* u0 G' A, K6 R
- return "Chat1.htm"
. E7 p) t* ^: V: R7 P6 R; x) v - elif n >= 4:2 P0 i4 o( m; s( K7 \
- return "Chat4.htm"
# D( i" r& A% i2 n) T3 ]$ k - return "Collect "+str(n)+" of 4 fangs"0 a& `# f+ |* G4 D& d4 f" ]
- return
" v! D8 Z8 _" _! D- x - 7 J) @! p9 q$ b. D9 u) F/ Y
- QUEST = Quest(201, "Tutorial", "Tutorial quest")$ q4 F: x0 E/ L- w8 G3 t# ^- c
- CREATED = State('Start', QUEST)
% y4 K$ j/ z9 |2 g( ]: T - STARTED = State('Started', QUEST)
4 n: V5 G4 F5 s, j3 V" x8 S) D - COMPLETED = State('Completed', QUEST)
, R8 l k, B, \! }' U V - 7 T" @; K! ~& W
- QUEST.setInitialState(CREATED)
& f+ W' ~& Q0 C - QUEST.addStartNpc(7056)# P9 \) h+ i2 e { g v3 Z% V
- QUEST.addStartNpc(7012): |/ s5 @% C! ^, T- ~
- QUEST.addStartNpc(7009)
. @; J6 r( K7 i/ C - QUEST.addStartNpc(7011)
- x( T1 e E S! A/ k% a - 0 c1 L5 N% I3 D; G# @$ `
- STARTED.addQuestDrop(KELTIR_NPC_ID,FANGS_ITEM_ID,DROP_RATE)
9 I2 D- H+ S/ | - STARTED.addKillId(KELTIR_NPC_ID)1 s7 u* p( ^3 a, h# n4 {
- STARTED.addTalkId(7056)7 Z) s5 a( W `& K2 O
- STARTED.addTalkI d(7012)4 U4 X+ N+ F* x1 ~8 U, J6 p& Z
- STARTED.addTalkId(7009)
0 q' T7 c& T Y8 g - STARTED.addTalkId(7011)
Скопировать код % d8 T$ M# \" V# l3 L6 B
' }1 i- l' W# m( t# {& V+ h |