Зарегистрируйтесь сейчас чтобы найти еще больше друзей, и получить полноценный доступ ко всем функциям сайта!
Для просмотра Вам необходимо авторизоваться Если Вы еще не зарегистрированы, перейдите по ссылке:Зарегистрироваться
x
Хроники Interlude
) Z6 a' _7 u- k) |# B( GСборка L2j1 z3 i) A) ]0 t. c0 d+ _
Обратите внимание: в файле htm стартового NCP обязательно должна быть ссылка на квест: _& j' d5 g O8 M
- STARTED.addQuestDrop(KELTIR_NPC_ID,FANGS_ITEM_ID,DROP_RATE)
Скопировать код Для этого квеста больше ничего не надо. Все необходимое для корректной работы квеста уже добавили. Вот полный текст квеста:* B! u. k$ |/ }" u9 l4 ^
6 K, S1 F- }; y2 c9 s. a- if getCount(st) >= 4 :9 F9 ~1 E M# p
- completed(st)
, R+ V( O) C7 G7 V - return
5 E. e& B& t& x3 k. I - $ c1 V1 O/ ~9 u# J
- class Quest (JQuest):
3 |8 E+ F3 @: z/ p% `; X5 _ - def __init__(self,id,name,descr): JQuest.__init__(self,id,name,descr)
0 @( n7 |* a( M* D - def onEvent (self,event,st):
# v! k# s2 @$ g) i - id = st.getState()) Z; W% W. F( U2 [! O
- if id == CREATED : st.setState(STARTED)
9 \2 Z" [/ K# m. O! v& n) f# W' T - elif id == COMPLETED: pass! R& t) A5 H+ [3 ]
- elif id == STARTED : check(st)* |5 H0 \8 {' X& F* }& w
- return" y4 K z( i. }
- T% i/ R( e7 r- QUEST = Quest(201,"Tutorial", "Tutorial quest")0 s- A8 X1 t- A8 Z
- CREATED = State('Start', QUEST)
3 @" `9 B6 s2 h* Z; ]$ B/ n0 O - STARTED = State('Started', QUEST)
$ S+ L7 w) f: s - COMPLETED = State('Completed', QUEST)
2 ~. c; u/ V! }5 m - ' g. B5 e X9 X! _2 e6 @
- QUEST.setInitialState(CREATED)! |" o; y9 O( ~7 @( }7 \& m
- QUEST.addStartNpc(7056)6 f* ?" G7 M: Q& |8 W7 q
- STARTED.addQuestDrop(KELTIR_NPC_ID,FANGS_ITEM_ID,DROP_RATE)
Скопировать код Теперь рассмотрим, как это работает./ M; I/ x) `2 [
Игрок подходит к начальному NCP (в данном случае 7056), нажимает на «Quest». Квест будет создан и состояние квеста перейдет к CREATED и игроку будет показана страничка Start.htm с описанием квеста. Тогда метод onEvent, поле открытия странички Start.htm переведет состояние квеста в STARTED и игроку будет показана страничка Started.htm, где будет опсание того, как найти keltirs и .т.д.' j8 A. j+ `3 Z2 h9 \: d) p
0 @* D* i9 r' t. ~. r
' q# J3 H% P/ H# H8 A/ Z
При состоянии STARTED будет зарегистрирован дроп «fangs» при убийстве keltirs. Игрок может вернуться к стартовому NCP и спросить о квесте – метод onEvent будет вызван снова. Если у игрока не хватает необходимого количества предметов, то метод check() не переведет квест в следующее состояние и Started.htm будет показана снова. Но если игрок собрал необходимее количество предметов (в данном случае 4 клыка), то метод check() вызовет метод completed() который переведет квест в новое состояние COMPLETED, заберет все клыки, даст карту мира, т.к. это награда за квест, покажет Completed.htm и завершит квест." a P5 n/ p+ y
/ [6 G- |( p) O, q2 y$ d+ g
! w1 n" i {! u0 m
Теперь давайте сделаем наш квест более похожим на то, что он должен из себя представлять.
/ j9 S& @1 N; _5 s, N# b) P e8 c$ s, lПрежде всего у нас есть 3 метода для объявления их в Яве – onTalk, onKill и onEvent. Если методы onTalk и onKill не объявлены, то за них все будет делать метод onEvent, т.е. определять квестовых монстров и вызывать диалоги NCP. Есть примечание, методы onTalk и onKill будут вызывать только диалоги с NCP в зависимости от текущего состояния квеста. Метод onKill будет вызываться только тогда, когда мы убиваем квестового монстра.
# _: ]1 g0 ? C |: T: Q: O6 \" K4 [0 d1 X- ~/ w& ]
, s3 [/ W9 O3 _3 ^; L) e. f! {Давайте рассмотрим как вызывается метод onKill при убийстве keltir в состоянии квеста STARTED: I* Q5 j. C4 w5 H/ n2 }; V
- STARTED.addKillId(KELTIR_NPC_ID)
Скопировать код и метод onKill в классе Quest:' A# X+ L8 J0 x8 U- h
+ T8 n: e/ F' Y
- class Quest (JQuest):0 N" d3 \5 m {7 o. `& `% q
- ...) Z/ m' v9 l2 g
- def onKill (self,npcId,st):
/ l1 }8 q" h/ c: o- g2 F0 w3 g0 e8 | - if npcId == KELTIR_NPC_ID:6 i, g; n1 n' j2 ~( Z. M" D- T
- n = getCount(st)) e0 s8 R( l: _' U9 Q0 Z* A) R' l3 ^
- if n == 0: r2 K( I( C6 f4 e; G. B
- return "Chat0.htm", J% ]! Q. C+ z! j5 A
- elif n == 1:
4 q _9 l0 C% `+ T% U - return "Chat1.htm", E2 d8 U' g2 f6 e3 s# c& Z
- elif n >= 4:, G5 r7 {2 Z1 c. d
- return "Chat4.htm"* s& v' F6 W P. p4 ]
- return "Collected "+str(n)+" of 4 fangs"* ^% B( m1 U- K5 |
- return
Скопировать код Метод onKill (а так же метод onTalk) имеет следующие параметры:
* ^9 B% w* f* W6 w
( O1 }: e! {( Y L
# }# L/ _6 u% d• self – квест
/ t# E5 S B! V, Q7 K7 f• npcId – ID NCP, которого мы должны убивать (если это метод onTalk, то ID того NCP, с которым мы должны поговорить).
: X& f0 ?4 W: c. i% k3 j• st – текущее состояние игрока.2 ^2 \6 ]% j4 l, q( g# H# h
; H( r! x# C' I5 w+ ?2 @) J
& ]/ a+ ?* D0 n: K4 w0 T4 t [9 X
В этом методе мы проверяем и отмечаем, является ли убитый NCP keltir’ом. В основном эта проверка не нужна, т.к. у нас только KELTIR_NPC_ID.# q& ]4 f' F! S
0 |# `4 V- ?3 Y4 z' w, P% L
+ @& h" V* Z# g9 g/ x7 cЗатем проверяем количество предметов (в данном случае количество клыков), и если их вообще нет, то возвращаем строку "Chat0.htm", если только один предмет, то возвращаем строку "Chat1.htm", если же предметов 4 или больше, то "Chat4.htm". Если строка возвращена из методов onEvent, onKill или onTalk, то сервер покажет соответствующие htm. В Chat0.htm может иметь следующий текст: «Вы не имеете ни одного клыка, возвращайтесь позже, когда соберете 4 штуки и бла, бла, бла…», в Chat1.htm может быть следующий текст: «У Вас всего 1 клык, по этому соберите еще…». В Chat4.htm – «Вы собрали необходимое количество предметов, возвращайтесь к вашему тренеру, что бы завершить квест…» v$ M1 d( W, P& A9 s
/ Y+ D7 U9 p5 x w5 J. n, I
7 o$ }1 i5 L! e* IПримечание: если в строка return начинается с "<html>", то будет показана страничка html с текстом, который стоит далее. Так вместо:9 i$ r0 } X7 O0 H) C
return "Chat4.htm") J1 W2 a8 T6 `, ]5 U
b8 ?% w$ W1 l7 U
( u4 z3 ]* ?8 |, w8 u4 N0 W- u7 L) ^
можно поставить:
! ]5 p4 u) ^) i) A) e- return "<html><body>Return to your trainer to complete the quest</body></html>"
Скопировать код Так же если строка заканчивается без .htm или в начале нет <html>, то текст будет выведен, как системное сообщение в окне чата. В нашем случае мы сделаем так, что бы при каждом убийстве keltik выводилось системное сообщение: «Собрано N из 4-х клыков».5 T& Z. L+ u; C/ K7 S
% N" j0 }% E4 h. j- p! i8 [, ]
4 y; N6 V. f3 l" [% K7 fНаш код для onKill имеет один недостаток. Он будет постоянно показывать Chat0.htm, Chat1.htm и Chat4.htm, нам же необходимо, что бы Chat0.htm и Chat1.htm показывались только один раз. Как нам это сделать? С помощью переменных.0 i. a' S8 x; p5 N' O
% Q3 Z8 H3 X( K+ Y7 n% }9 o9 i. a, T$ H' M& h
В каждом квесте строки могут храниться с помощью переменных. Эти переменные сохраняются в Вашей БД. В каждом методе мы можем назначить, прочитать и удалить переменные. Давайте изменим метод onKill, так что бы каждый диалог вызывался только один раз.
% R) U/ T6 n! U; ~- def onKill (self,npcId,st):
3 m& A' Y9 N" F& i, h0 X - if npcId == KELTIR_NPC_ID:
! s. ^" A- w$ a. e/ d - n = getCount(st)( T z8 g. @% l& W
- if n == 0:6 c0 {$ i1 \) v2 Q
- if st.get('chat0') == None :% J% F& S1 f1 J4 |/ A' m4 R) K
- st.set("chat0", "true")& j) ]( l$ [1 u5 k. r/ D3 A
- return "Chat0.htm"1 O a5 u8 ]5 H8 o
- elif n == 1:, s8 ~3 [# f4 j+ L7 H' F4 B1 G+ o
- if st.get('chat1') == None :4 p) ^+ }, o. E. D
- st.set("chat1", "true")
0 V! v, `6 I# g3 U% u' q3 T5 ] - return "Chat1.htm"
% t, \- K- f$ }! R$ J0 E# v - elif n >= 4:. x4 j6 R7 X% G2 }3 T/ H/ [: r: l
- return "Chat4.htm"* I8 X+ h! W3 t6 k
- return "Collected "+str(n)+" of 4 fangs"
, \1 ?8 N) j+ G6 B" R; A - return
Скопировать код Если у игрока нет клыков (n=0), то мы получаем занчение переменной 'chat0'. Когда метод onKill вызван в первый раз, то пока ни каких переменных не имеется и python возвращает значение None. В этом случае объявляется переменная и показывается диалог Chat0.htm. Когда мы убиваем keltir, но не получаем с него клык, функция st.get('chat0') возвращает строку true, а не None. И во второй раз окно с Chat0.htm не появится, но в окне чата появится строчка «Collected 0 of 4 fangs». По тому же принципу сделано и с Chat1.htm.
/ L8 v; h2 C' L) b+ v, Y! e g! ^' }; m2 B E; ]5 [( Y4 k
' l3 p; B. ]- w$ J# ]4 r- l, W2 C
Вот конечный рабочий вариант квеста:
# z8 u1 a) i2 r( ^& D6 H- import sys
# ?1 b. p8 i# Z* |3 M" I" Y - from net.sf.l2j.gameserver.model.quest import State: J) ?& S( j2 h( g9 |
- from net.sf.l2j.gameserver.model.quest import QuestState' Z6 [4 s) ~4 d% ` j
- from net.sf.l2j.gameserver.model.quest.jython import QuestJython as JQuest
P( Q5 J# _7 \, I% V/ ]
; \* D( o! |1 t- l) F7 g$ H/ B- KELTIR_NPC_ID = 12082
; S+ y4 U( b/ O( C# B - FANGS_ITEM_ID = 18591 c5 F4 y1 O" d: F1 ]
- DROP_RATE = 500000
[! t( g' ^0 F: O - 4 h2 w5 k$ B+ T( v! h: R9 A0 _
- WORLD_MAP_ITEM_ID = 1665
$ h' a1 y% z- p5 H0 j# c
2 Y; L9 L8 }$ `% ~ _- def getCount(st) :
3 p: z& N/ l, F" O - return st.getQuestItemsCount(FANGS_ITEM_ID)
# U" }6 J* \: t% ] - % R6 c' H) t' c- t" l- u
- def completed(st) :, c! |; K7 X4 \: G8 C
- st.setState(COMPLETED)0 l0 E" q- K. f, N8 V1 d" C
- st.clearQuestDrops()
2 K+ C* [8 X( V X/ x( J - st.takeItems(FANGS_ITEM_ID,-1)$ H- M# w0 ^8 D/ y
- st.giveItems(WORLD_MAP_ITEM_ID,1)
& |2 p/ g! K) M9 C - st.exitQuest(False)5 d d8 w; l \4 A
- return! P" r) V- X; \. c
% L# T, y3 Y& e7 \- def check(st) :* t4 W$ f7 x1 L( V7 _. I
- if getCount(st) >= 4 :6 q% {' v f: P- }0 n. ~
- completed(st)
' s# s- L% h" Y) J- |" f, ^8 C - return' U; [4 f$ G1 O# z* L3 c
) B5 g, b( {- T. ]) ?) o4 v% v- class Quest (JQuest):
* y) `& O3 q$ k% C) ? - 1 B: q) L) J9 J8 N& ?
- def __init__(self,id,name,descr): JQuest.__init__(self,id,name,descr): o' f& J" L# ?
- 4 A' [' C) I8 ?* c- Y2 A
- def onEvent (self,event,st):
: f0 V" S& \! ] z* p. n; w8 \( g - id = st.getState()
# i: S8 b, h2 l6 s R - if id == CREATED : st.setState(STARTED)3 {" H) ^+ g$ ^
- elif id == COMPLETED: pass
: _9 l, a" H j6 t - elif id == STARTED : check(st)+ e5 B0 z1 R* U4 ~& E8 n
- return$ W" [1 M |( _
- " Q q) g5 a% A
- def onKill (self,npcId,st):
7 C8 a0 s; M2 i' C% ` - if npcId == KELTIR_NPC_ID:& N3 ?. u! Q9 `0 C4 s6 z
- n = getCount(st)
" j, N/ A: Q j/ F8 H - if n == 0:7 u' ?" A# t7 X! T
- if st.get('chat0') == None :
3 A% p) {' |$ S% b2 D - st.set("chat0", "true")
9 d5 T4 b# c! H; y" P& G- G - return "Chat0.htm"/ B6 g! W8 x* {% x
- elif n == 1:4 c" P, r! A6 |0 Z2 c2 A
- if st.get('chat1') == None :
# o$ B: h+ j2 M, t - st.set("chat1", "true")
- D. Z, D9 m) \2 v- m# @( q& D - return "Chat1.htm"0 w% G2 _% R7 _- ?2 v* r5 }. A+ e% b7 k
- elif n >= 4:* P5 w# h" {! j
- return "Chat4.htm"7 z7 u. b* K7 z" B! d8 N
- return "Collect "+str(n)+" of 4 fangs"
% G G3 q! d: H" }% B% d, v8 s0 l - return
; |3 {: _8 E* J, M- \* d4 u - " K+ T$ a, R% n4 } ]3 ^+ K, ~% A) [
- QUEST = Quest(201, "Tutorial", "Tutorial quest")
1 G+ {: N7 ?1 M$ t - CREATED = State('Start', QUEST)
2 P# P/ h9 z! D0 h9 C8 f/ r - STARTED = State('Started', QUEST)
* ^+ y. X; q4 z" [; g1 x5 u - COMPLETED = State('Completed', QUEST)
, F! I2 J% L5 ~9 k3 I8 W" [
% U: r; d* B' q8 F; \+ b- QUEST.setInitialState(CREATED)/ _" m9 B: p) s: p
- QUEST.addStartNpc(7056)$ R: {- r" R; |# b: P6 t K
- QUEST.addStartNpc(7012)
, F; a! M) k" y7 r - QUEST.addStartNpc(7009)
: i6 o" L8 z5 a3 t" [1 R- t - QUEST.addStartNpc(7011)4 q1 e f7 [8 f+ t/ D( T4 _1 h, D8 K
, D2 X3 d+ r+ |- O8 K- STARTED.addQuestDrop(KELTIR_NPC_ID,FANGS_ITEM_ID,DROP_RATE)* G0 O S2 k0 k6 w: s5 J M. Z+ i+ p
- STARTED.addKillId(KELTIR_NPC_ID)
# M7 z5 F4 b( L, x- A+ S ? - STARTED.addTalkId(7056)
: I2 c. Z _: F% w! k* B- o - STARTED.addTalkI d(7012)
/ ^; B' ~0 {7 q - STARTED.addTalkId(7009)
7 P+ {+ ?) Y: D* e7 X - STARTED.addTalkId(7011)
Скопировать код 7 X) x' H* n6 r5 g
- u) ^2 o7 l; h( O7 b |