Зарегистрируйтесь сейчас чтобы найти еще больше друзей, и получить полноценный доступ ко всем функциям сайта!
Для просмотра Вам необходимо авторизоваться Если Вы еще не зарегистрированы, перейдите по ссылке:Зарегистрироваться
x
Хроники Interlude" e: C* i6 j1 X, A; f, I: E3 f( s
Сборка L2j
3 s, h1 ^& K9 E4 C/ J/ ^7 K+ aОбратите внимание: в файле htm стартового NCP обязательно должна быть ссылка на квест:5 `2 {. O" e" z- V5 X+ l
- STARTED.addQuestDrop(KELTIR_NPC_ID,FANGS_ITEM_ID,DROP_RATE)
Скопировать код Для этого квеста больше ничего не надо. Все необходимое для корректной работы квеста уже добавили. Вот полный текст квеста:
3 n! W2 Z; b- X: a; {9 \" X* S7 @$ F& w3 `, u2 \# [- E+ [
- if getCount(st) >= 4 :+ a2 \. G; v- _8 R- s3 i4 ]
- completed(st): f2 g; j4 a; ]3 z6 r* @
- return
3 _6 }: Q$ l4 p! f6 \+ b - + L9 T) s" k5 j9 ]/ ]: N
- class Quest (JQuest):% o1 @# J0 l: q* r: q' J! v
- def __init__(self,id,name,descr): JQuest.__init__(self,id,name,descr)
) m+ ^: C1 v7 W$ t; W9 a; D) w* |* T, y - def onEvent (self,event,st):& `8 X0 y( i+ a% f
- id = st.getState()& h1 n2 P2 {& E: ^& N+ z/ l5 ~( k
- if id == CREATED : st.setState(STARTED)
, U& o) G+ d- j - elif id == COMPLETED: pass
( {' |' I+ z) ]% h - elif id == STARTED : check(st)
; E' Z1 {7 X0 H; |+ d - return
4 D9 Y$ x* o8 [% n: k: l4 w9 ~ - . W9 S% @4 }# z5 o2 O3 b
- QUEST = Quest(201,"Tutorial", "Tutorial quest")3 M! D! D0 h. P: ^
- CREATED = State('Start', QUEST)
' X2 @5 f$ M( U3 W0 L/ U" N* i - STARTED = State('Started', QUEST)0 {6 T$ ^! R T8 A9 m; \
- COMPLETED = State('Completed', QUEST)
1 Q3 U# c0 Q4 K$ [- v) A - q9 u C6 M% |0 d! z
- QUEST.setInitialState(CREATED)
3 l% |! s' ~7 F* U/ Q5 Q& J( {+ k3 B* u - QUEST.addStartNpc(7056)# O) I& X& W/ n8 n
- STARTED.addQuestDrop(KELTIR_NPC_ID,FANGS_ITEM_ID,DROP_RATE)
Скопировать код Теперь рассмотрим, как это работает.0 f. y4 a$ n. w; A! A
Игрок подходит к начальному NCP (в данном случае 7056), нажимает на «Quest». Квест будет создан и состояние квеста перейдет к CREATED и игроку будет показана страничка Start.htm с описанием квеста. Тогда метод onEvent, поле открытия странички Start.htm переведет состояние квеста в STARTED и игроку будет показана страничка Started.htm, где будет опсание того, как найти keltirs и .т.д.
9 U0 y( b$ S; l' t+ F, M; h; z9 K$ A. v; G- L- U2 l
( |8 V5 Z' o o, L: w# s9 z, BПри состоянии STARTED будет зарегистрирован дроп «fangs» при убийстве keltirs. Игрок может вернуться к стартовому NCP и спросить о квесте – метод onEvent будет вызван снова. Если у игрока не хватает необходимого количества предметов, то метод check() не переведет квест в следующее состояние и Started.htm будет показана снова. Но если игрок собрал необходимее количество предметов (в данном случае 4 клыка), то метод check() вызовет метод completed() который переведет квест в новое состояние COMPLETED, заберет все клыки, даст карту мира, т.к. это награда за квест, покажет Completed.htm и завершит квест.
! E9 S. C8 c3 m; q. }' s5 Z
0 r m; \# o4 k) a( n: @1 ~; [. o3 b; b1 y* B6 i( p
Теперь давайте сделаем наш квест более похожим на то, что он должен из себя представлять.
- s; u3 p- ?: h1 v$ [* V+ _Прежде всего у нас есть 3 метода для объявления их в Яве – onTalk, onKill и onEvent. Если методы onTalk и onKill не объявлены, то за них все будет делать метод onEvent, т.е. определять квестовых монстров и вызывать диалоги NCP. Есть примечание, методы onTalk и onKill будут вызывать только диалоги с NCP в зависимости от текущего состояния квеста. Метод onKill будет вызываться только тогда, когда мы убиваем квестового монстра.
9 Z- ]" r; l% ]5 |/ U+ X! Z7 o) p
& {; M$ h/ H5 T) X W7 e% E1 s' v1 s7 @
Давайте рассмотрим как вызывается метод onKill при убийстве keltir в состоянии квеста STARTED:0 s E1 D( r) z* |9 {
- STARTED.addKillId(KELTIR_NPC_ID)
Скопировать код и метод onKill в классе Quest:
% \- @7 q) C: L& ?& Q! |5 P0 f* G$ F# ~$ v; w
- class Quest (JQuest):+ G3 c' e( F; y; y: U* T( O/ Y K
- .../ z; {% S3 E3 k( z! E0 M
- def onKill (self,npcId,st):& b* ~! G- L0 g: g0 G j/ `
- if npcId == KELTIR_NPC_ID:: V/ r; M. p+ F/ [# Q& g# I
- n = getCount(st)
/ v) I$ V; \# A. l8 F+ r - if n == 0:) n8 }; @1 `% j; B/ F) b
- return "Chat0.htm"
2 N! R y `; I8 h/ e% M+ J - elif n == 1:9 |3 W* E! k, H0 ~# u0 I i' S
- return "Chat1.htm"
' P6 G% Y0 c5 Q$ _ - elif n >= 4:
5 c' R" G5 r4 ~# M- ] - return "Chat4.htm"
|* A$ J: ?. K) S* b - return "Collected "+str(n)+" of 4 fangs"
" G% S: ~7 v {/ ?: b7 t1 z& D - return
Скопировать код Метод onKill (а так же метод onTalk) имеет следующие параметры:
q {. h( A& f8 O, i' F+ O' U9 p8 S" z9 d; o, r! W
5 ^; b! @) W) ]7 ]/ g• self – квест# U$ L' S) _1 j+ T$ u' m8 E7 E
• npcId – ID NCP, которого мы должны убивать (если это метод onTalk, то ID того NCP, с которым мы должны поговорить).
. _% q5 Z5 [4 X1 |' `/ m& b• st – текущее состояние игрока.' {& |" W' V; C9 ]! W% p
1 F0 ~; H4 W d; n
) ?4 @& A+ j, c- q: W9 C% N
В этом методе мы проверяем и отмечаем, является ли убитый NCP keltir’ом. В основном эта проверка не нужна, т.к. у нас только KELTIR_NPC_ID.) N6 l, _! F) ^7 ~
; y- Y2 t6 e* @% N3 t; z& d
# I* O n0 h: J" B. F
Затем проверяем количество предметов (в данном случае количество клыков), и если их вообще нет, то возвращаем строку "Chat0.htm", если только один предмет, то возвращаем строку "Chat1.htm", если же предметов 4 или больше, то "Chat4.htm". Если строка возвращена из методов onEvent, onKill или onTalk, то сервер покажет соответствующие htm. В Chat0.htm может иметь следующий текст: «Вы не имеете ни одного клыка, возвращайтесь позже, когда соберете 4 штуки и бла, бла, бла…», в Chat1.htm может быть следующий текст: «У Вас всего 1 клык, по этому соберите еще…». В Chat4.htm – «Вы собрали необходимое количество предметов, возвращайтесь к вашему тренеру, что бы завершить квест…», X# P E) n: R4 q6 F
& ?. |! C7 @6 y8 B
( u e: g/ B' w& p8 Q( vПримечание: если в строка return начинается с "<html>", то будет показана страничка html с текстом, который стоит далее. Так вместо:) u9 D* q+ K; }) [" ^' z) ^
return "Chat4.htm"
- o) r8 G3 _7 P! x5 E G; Y4 y! K& a* H
+ k. [6 K$ p$ v8 i% W& Yможно поставить:
" v" c$ i; X* @: m; J, b- return "<html><body>Return to your trainer to complete the quest</body></html>"
Скопировать код Так же если строка заканчивается без .htm или в начале нет <html>, то текст будет выведен, как системное сообщение в окне чата. В нашем случае мы сделаем так, что бы при каждом убийстве keltik выводилось системное сообщение: «Собрано N из 4-х клыков».
5 s q0 e' W9 {1 F4 T$ ~( s) Q# k8 Z) ?4 B1 W# j; `
7 _% D- ^( O+ q$ \Наш код для onKill имеет один недостаток. Он будет постоянно показывать Chat0.htm, Chat1.htm и Chat4.htm, нам же необходимо, что бы Chat0.htm и Chat1.htm показывались только один раз. Как нам это сделать? С помощью переменных., y1 x1 ^7 q5 b' B Q
5 s$ f3 b7 c( }: }3 `# v
/ C* {& W& C m% i* v- @( t }
В каждом квесте строки могут храниться с помощью переменных. Эти переменные сохраняются в Вашей БД. В каждом методе мы можем назначить, прочитать и удалить переменные. Давайте изменим метод onKill, так что бы каждый диалог вызывался только один раз.
& C/ d8 R) u3 b' X$ U2 w2 {- def onKill (self,npcId,st):
/ l. a! u* I! S% }! Y - if npcId == KELTIR_NPC_ID:8 [, `. u! C8 h+ y! j' ?
- n = getCount(st)
' q! f3 N: b& S! H! S - if n == 0:4 b. j$ `$ E: _' J) A/ [
- if st.get('chat0') == None :; P0 a: Y; j8 p: O; e* c
- st.set("chat0", "true")
" B1 x5 v5 Q8 a4 x& B1 i - return "Chat0.htm"% G4 [6 O/ }/ v; @
- elif n == 1:/ q+ y! c7 B3 U L1 T
- if st.get('chat1') == None :4 _5 j4 P" e( O- C" k
- st.set("chat1", "true")
+ |5 b7 B1 c0 x& ]6 I - return "Chat1.htm"; \! n- J! c t
- elif n >= 4:
- e, Z2 w, ]9 ]; J3 n6 o* q - return "Chat4.htm"
% I3 r# J5 k$ G - return "Collected "+str(n)+" of 4 fangs"; ?0 ~: _ X3 F/ b2 g
- return
Скопировать код Если у игрока нет клыков (n=0), то мы получаем занчение переменной 'chat0'. Когда метод onKill вызван в первый раз, то пока ни каких переменных не имеется и python возвращает значение None. В этом случае объявляется переменная и показывается диалог Chat0.htm. Когда мы убиваем keltir, но не получаем с него клык, функция st.get('chat0') возвращает строку true, а не None. И во второй раз окно с Chat0.htm не появится, но в окне чата появится строчка «Collected 0 of 4 fangs». По тому же принципу сделано и с Chat1.htm.
! f0 m+ e8 S8 @1 Q
& D7 X, p5 x k4 T% p
; f$ m( {! [/ z/ u. RВот конечный рабочий вариант квеста:# Z) ^% z% e1 {) B# N2 p {+ k2 {
- import sys
h+ G7 q# }& ?) @& R! m - from net.sf.l2j.gameserver.model.quest import State
. k$ d6 w& S" {( h7 N! u; Y' B- y - from net.sf.l2j.gameserver.model.quest import QuestState
; k6 _" w* Z% d. Z7 j. P7 P2 Z$ ` - from net.sf.l2j.gameserver.model.quest.jython import QuestJython as JQuest
! O. ]+ P1 h6 M( V2 z5 N2 C1 d h( Q - + z @7 Z& `/ k, F! Q, @
- KELTIR_NPC_ID = 12082% O1 {" r) K& K, w8 V* {9 W; r
- FANGS_ITEM_ID = 18596 I) f2 Z" K7 ?0 w3 x
- DROP_RATE = 500000
7 v4 ^ p/ C( y0 G0 x# f - / s9 q3 a3 n3 X/ |/ d9 x
- WORLD_MAP_ITEM_ID = 1665
% a$ M; S8 O' `1 s; ?$ m7 [/ j/ x1 W
( I. J7 A; }% \* r- def getCount(st) :0 E& ]2 v5 Q x8 i) z6 n' d, l
- return st.getQuestItemsCount(FANGS_ITEM_ID)
4 [7 |; m+ Q6 D0 U( X( N& z$ I - 9 `6 w5 k8 N/ o( C
- def completed(st) :( E3 K3 e/ p8 X
- st.setState(COMPLETED)
7 n$ i. J, b4 A. `+ y8 O- O* W - st.clearQuestDrops()! m4 R$ Z9 @/ ?8 Z$ q( G3 F
- st.takeItems(FANGS_ITEM_ID,-1)" v% s0 _9 ^6 G8 ]9 @/ F
- st.giveItems(WORLD_MAP_ITEM_ID,1)
6 `0 R/ N* t/ i( X7 u+ ] - st.exitQuest(False)
# Y0 w2 R9 i/ c! N. \1 M* T - return; @7 ] v0 |3 O& o/ p
# h4 L& Y* y) P6 v" S7 u- def check(st) :
: v* s6 {1 D$ U; A/ s - if getCount(st) >= 4 :
( e$ A3 [# H9 O+ c2 ` - completed(st)' T* O! n$ U6 |* G* \
- return6 Z" G" M5 ]& n% ]6 c$ d
3 Z9 x4 a) X: g5 e- N7 u- class Quest (JQuest):7 v' O, b* ]2 N: e" u
- 3 P. v4 a, \$ E. `2 O& Y/ ]
- def __init__(self,id,name,descr): JQuest.__init__(self,id,name,descr)
* l/ ?, A' n. _1 h
, a" @" P5 F1 E& n' i7 `- def onEvent (self,event,st):
' f; A- |& [/ R7 g( D/ S4 b - id = st.getState()" P' H0 N) L `- V
- if id == CREATED : st.setState(STARTED)" R# I7 x/ ~/ Z: P: J
- elif id == COMPLETED: pass
8 [3 j' @+ r0 i2 Q3 r7 U - elif id == STARTED : check(st)/ y9 K: N& \7 L! r1 u9 T
- return: `8 R5 e) Z/ U
- 6 M/ r4 e% F+ x2 I
- def onKill (self,npcId,st):
3 w: O4 {, I: u9 a: `# W - if npcId == KELTIR_NPC_ID:+ {3 C! D5 Y4 @& \1 l6 Q: K
- n = getCount(st)9 D1 C0 r; L) l; ] K; k; j
- if n == 0:
! C# P& S# Y* K: k - if st.get('chat0') == None :2 S/ w6 G% K' E/ p6 a/ O x
- st.set("chat0", "true")4 X: Z0 H# S# U- |% h
- return "Chat0.htm"! C! v7 X$ \' Y1 S& s7 y9 n
- elif n == 1:
" u( d9 z2 p0 M# E; C- f b - if st.get('chat1') == None :
' I9 u! Z0 f7 Z$ O U! H - st.set("chat1", "true")
# n- D D. p _" _5 p9 G8 w% Q - return "Chat1.htm"& v# y( \3 K; f# y
- elif n >= 4:
! Q. u& F( N$ W) R5 E6 T - return "Chat4.htm"
& |7 r% {9 J" R - return "Collect "+str(n)+" of 4 fangs"
5 U: [+ ^+ F& b8 e7 e - return5 _, W7 o$ J0 e$ q6 S1 d# W
" h- h- Y9 \% u- QUEST = Quest(201, "Tutorial", "Tutorial quest")
/ ~% T4 n& w% K2 ]: k - CREATED = State('Start', QUEST)- \! h! i, l% b ?) ~
- STARTED = State('Started', QUEST)3 z9 I8 P- I/ `6 c8 P' V/ i
- COMPLETED = State('Completed', QUEST)/ ~8 X' C2 f3 H4 {: U0 |4 F! v F1 I
- 7 S: r% c4 a2 I7 u
- QUEST.setInitialState(CREATED)
" M; N4 k5 e9 Z' r* }" p - QUEST.addStartNpc(7056)
* o6 V# ]; s6 {. @& G( G - QUEST.addStartNpc(7012)
5 L( ?# e* C3 I0 i Q* `( ~ E: @ - QUEST.addStartNpc(7009)
9 p, ^# _* f8 ~& v - QUEST.addStartNpc(7011)2 V# e d" h, F7 u4 T" J
3 k; u8 p5 P$ B; K6 k6 u- STARTED.addQuestDrop(KELTIR_NPC_ID,FANGS_ITEM_ID,DROP_RATE)6 e' k6 y' z8 h+ _) Q( l* d% ?
- STARTED.addKillId(KELTIR_NPC_ID)
& b# k* ]9 D m/ ^; h! V - STARTED.addTalkId(7056)8 `% K, A0 ]- _* }) ?( R" F4 W
- STARTED.addTalkI d(7012)0 ]! w- Y/ @: U& i6 b
- STARTED.addTalkId(7009)4 j$ k5 j6 V1 U$ r+ c3 H7 v I
- STARTED.addTalkId(7011)
Скопировать код
$ u% b3 y+ T& d5 ^
) q$ k* V6 O- G. [; K+ v8 R0 u |