Зарегистрируйтесь сейчас чтобы найти еще больше друзей, и получить полноценный доступ ко всем функциям сайта!
Для просмотра Вам необходимо авторизоваться Если Вы еще не зарегистрированы, перейдите по ссылке:Зарегистрироваться
x
Хроники Interlude
9 Q; p- r$ U: T7 _. uСборка L2j; d% r( w$ b- U" P
Обратите внимание: в файле htm стартового NCP обязательно должна быть ссылка на квест:" a N! d9 s @" v Y& `8 _4 g
- STARTED.addQuestDrop(KELTIR_NPC_ID,FANGS_ITEM_ID,DROP_RATE)
Скопировать код Для этого квеста больше ничего не надо. Все необходимое для корректной работы квеста уже добавили. Вот полный текст квеста:. a2 {. y2 c* q8 k2 q
# j4 x7 `% r$ I" q* x+ R- if getCount(st) >= 4 :
# S" P) x1 B4 N - completed(st)
" d: X: G- p' y) s - return% O. x) D' R5 F- ^2 a5 W
- / p0 _" ?& I6 Z- R/ t& \( W4 ^
- class Quest (JQuest):0 I N: P, `; i% m
- def __init__(self,id,name,descr): JQuest.__init__(self,id,name,descr)
: P" Y" R2 A) p. s. L- Q& S - def onEvent (self,event,st):
8 s6 D3 Z# {) `2 V- X- ?+ V+ a9 {! p - id = st.getState() {$ ~6 G1 [: E' `( v
- if id == CREATED : st.setState(STARTED)" c F7 ~0 P# t7 n8 s
- elif id == COMPLETED: pass. A" ?. F R2 z; ]! D* n
- elif id == STARTED : check(st)
M% j/ K. |) R6 q. m3 P) \ - return/ b! @5 n8 d& s X1 u; D) N# R) k
% i% S" a/ s; n) i4 n- QUEST = Quest(201,"Tutorial", "Tutorial quest")7 J5 S" Q9 f+ i; r
- CREATED = State('Start', QUEST)
' w( E* W# ~8 f5 f - STARTED = State('Started', QUEST)
3 ~: W5 p6 i R7 t7 K& u8 L - COMPLETED = State('Completed', QUEST)0 T; | M; h: f, k1 k& w, q
3 I" p/ i# ?9 @5 V* Q# |- QUEST.setInitialState(CREATED)! S" M) E' r# V( T+ w: J8 h
- QUEST.addStartNpc(7056)
2 o$ F2 [4 c" @3 w3 \ - STARTED.addQuestDrop(KELTIR_NPC_ID,FANGS_ITEM_ID,DROP_RATE)
Скопировать код Теперь рассмотрим, как это работает.2 l- ^ q ]! _7 W4 d5 s
Игрок подходит к начальному NCP (в данном случае 7056), нажимает на «Quest». Квест будет создан и состояние квеста перейдет к CREATED и игроку будет показана страничка Start.htm с описанием квеста. Тогда метод onEvent, поле открытия странички Start.htm переведет состояние квеста в STARTED и игроку будет показана страничка Started.htm, где будет опсание того, как найти keltirs и .т.д.
0 E4 J7 O$ V6 E) ~4 m P- O, m
9 {9 u5 l7 Y8 M' P! \+ X& b/ r' N1 H
При состоянии STARTED будет зарегистрирован дроп «fangs» при убийстве keltirs. Игрок может вернуться к стартовому NCP и спросить о квесте – метод onEvent будет вызван снова. Если у игрока не хватает необходимого количества предметов, то метод check() не переведет квест в следующее состояние и Started.htm будет показана снова. Но если игрок собрал необходимее количество предметов (в данном случае 4 клыка), то метод check() вызовет метод completed() который переведет квест в новое состояние COMPLETED, заберет все клыки, даст карту мира, т.к. это награда за квест, покажет Completed.htm и завершит квест.4 u+ c8 {6 H# r6 a8 {' F2 A+ y5 S
7 ^* m# X6 u1 O M6 {& d7 g% }
5 I4 t: A% K0 a* ?& sТеперь давайте сделаем наш квест более похожим на то, что он должен из себя представлять.
/ K0 v, R' c" [& y7 q- } q) kПрежде всего у нас есть 3 метода для объявления их в Яве – onTalk, onKill и onEvent. Если методы onTalk и onKill не объявлены, то за них все будет делать метод onEvent, т.е. определять квестовых монстров и вызывать диалоги NCP. Есть примечание, методы onTalk и onKill будут вызывать только диалоги с NCP в зависимости от текущего состояния квеста. Метод onKill будет вызываться только тогда, когда мы убиваем квестового монстра.' G7 \! m' R* m$ h, D/ j' q/ T! Z
( N- G) a. L6 k" z2 B9 _8 O6 j0 c( i# A, t8 o. P* D& ~
Давайте рассмотрим как вызывается метод onKill при убийстве keltir в состоянии квеста STARTED:0 I& B3 `7 `: g" Q9 v
- STARTED.addKillId(KELTIR_NPC_ID)
Скопировать код и метод onKill в классе Quest:2 F6 O4 w' Y9 J
! `6 s4 F+ y, _6 ^7 H/ J8 ~
- class Quest (JQuest):
% _$ o- V4 n3 u5 c! d - ...9 J7 C t2 b4 w
- def onKill (self,npcId,st):0 G% K9 |1 n) L$ o8 p( l
- if npcId == KELTIR_NPC_ID:1 b) k: p9 m0 J' ?+ M+ a
- n = getCount(st)
4 I( _' C- E0 c8 C - if n == 0:
- ?+ N6 Z" C; n8 j3 |3 k. m/ H - return "Chat0.htm"; e6 f) N- z7 K2 F7 n9 J! i: G& o) K
- elif n == 1:$ N2 n4 V! P% [
- return "Chat1.htm". y d1 S1 q% }1 ^: A4 U
- elif n >= 4:! s" K$ A. h+ X0 U8 ^( _
- return "Chat4.htm"
( V/ S9 ~9 p1 S - return "Collected "+str(n)+" of 4 fangs"' q2 t( r8 d9 v3 ~" d, i
- return
Скопировать код Метод onKill (а так же метод onTalk) имеет следующие параметры:
/ l6 z$ p8 r$ G+ p: P5 g
* `0 A9 A2 i3 w( a- z g! U( m; U: Q9 d; g& u: y! y
• self – квест. p' A% U% H& n4 R7 S ?
• npcId – ID NCP, которого мы должны убивать (если это метод onTalk, то ID того NCP, с которым мы должны поговорить).9 c2 X0 M2 `7 k
• st – текущее состояние игрока.
! I$ G4 U0 L4 R& x4 D; C2 o
( X. _9 k0 y' |, t9 U; F5 |* `+ C# I( }% |# I; L
В этом методе мы проверяем и отмечаем, является ли убитый NCP keltir’ом. В основном эта проверка не нужна, т.к. у нас только KELTIR_NPC_ID.
7 k, Q; M4 f' J& o u6 b) |2 G1 J: a) e" t' M2 M$ ^' D
, {) ? { _; I Q2 T& q# ~2 ^
Затем проверяем количество предметов (в данном случае количество клыков), и если их вообще нет, то возвращаем строку "Chat0.htm", если только один предмет, то возвращаем строку "Chat1.htm", если же предметов 4 или больше, то "Chat4.htm". Если строка возвращена из методов onEvent, onKill или onTalk, то сервер покажет соответствующие htm. В Chat0.htm может иметь следующий текст: «Вы не имеете ни одного клыка, возвращайтесь позже, когда соберете 4 штуки и бла, бла, бла…», в Chat1.htm может быть следующий текст: «У Вас всего 1 клык, по этому соберите еще…». В Chat4.htm – «Вы собрали необходимое количество предметов, возвращайтесь к вашему тренеру, что бы завершить квест…»+ Y! h# m" F: @6 `! P" U: w3 x
; f2 W& J9 C( }- W) U- i: |
( g% G @4 S+ BПримечание: если в строка return начинается с "<html>", то будет показана страничка html с текстом, который стоит далее. Так вместо:, c3 G t/ F- x& g% E& `* x. u6 ~
return "Chat4.htm"
! N* w. ~' p# C( v# o% \6 D" S u* Z+ o7 i
. O) D, j+ E7 g( q! ]- r! {- Z6 U
можно поставить:# e8 C8 A' i9 u; p
- return "<html><body>Return to your trainer to complete the quest</body></html>"
Скопировать код Так же если строка заканчивается без .htm или в начале нет <html>, то текст будет выведен, как системное сообщение в окне чата. В нашем случае мы сделаем так, что бы при каждом убийстве keltik выводилось системное сообщение: «Собрано N из 4-х клыков».
5 C( [ U1 J7 r+ L7 b+ @0 t
7 U+ S9 X: N% y/ R, s2 ?
% q: G' D0 |; M2 e8 |" _Наш код для onKill имеет один недостаток. Он будет постоянно показывать Chat0.htm, Chat1.htm и Chat4.htm, нам же необходимо, что бы Chat0.htm и Chat1.htm показывались только один раз. Как нам это сделать? С помощью переменных.
, ^' e; i$ F: W
G% t! g$ ~# E5 H" t4 l5 m9 w/ |5 K; U& q1 S7 z* V
В каждом квесте строки могут храниться с помощью переменных. Эти переменные сохраняются в Вашей БД. В каждом методе мы можем назначить, прочитать и удалить переменные. Давайте изменим метод onKill, так что бы каждый диалог вызывался только один раз.
" T i e2 M' z4 I' f& ?) N# U/ u- def onKill (self,npcId,st):
6 `* p5 A* o! J$ L- M0 M - if npcId == KELTIR_NPC_ID:" z" e9 J+ J0 A
- n = getCount(st), o, G, E8 F% k6 ?( T5 u0 X
- if n == 0:
: W j1 Z7 U: {" y! F - if st.get('chat0') == None :& O) u1 a1 I/ N2 |4 M% E
- st.set("chat0", "true")
4 j4 e0 |2 \) @; U0 ^2 F - return "Chat0.htm"
& h3 f0 S% o8 c. \- Q - elif n == 1:* W1 J; ?7 J& d" W1 k
- if st.get('chat1') == None :& U4 X" q( y" I2 u. N/ z5 v2 J; C
- st.set("chat1", "true")$ a- v6 ]; s& i5 D- N1 e# F; v
- return "Chat1.htm"
3 K2 G- z T" i' n5 _0 w - elif n >= 4:; p G$ I* M/ Q5 f, n+ v
- return "Chat4.htm"+ ]0 s6 r* Q9 V/ ^. d
- return "Collected "+str(n)+" of 4 fangs"8 F: w0 G$ r6 n( \* Z* D
- return
Скопировать код Если у игрока нет клыков (n=0), то мы получаем занчение переменной 'chat0'. Когда метод onKill вызван в первый раз, то пока ни каких переменных не имеется и python возвращает значение None. В этом случае объявляется переменная и показывается диалог Chat0.htm. Когда мы убиваем keltir, но не получаем с него клык, функция st.get('chat0') возвращает строку true, а не None. И во второй раз окно с Chat0.htm не появится, но в окне чата появится строчка «Collected 0 of 4 fangs». По тому же принципу сделано и с Chat1.htm.
" S l, t, C1 G8 x3 R- J3 F& R! {+ m& ^& ^3 [4 a
1 X: z* K: q2 w# {4 C+ z8 oВот конечный рабочий вариант квеста:
* W' b/ ?: D5 }# {) c- import sys# r0 V# n! K% N' `
- from net.sf.l2j.gameserver.model.quest import State
) h' |/ \+ Z6 S b1 n - from net.sf.l2j.gameserver.model.quest import QuestState/ M( `7 K9 I8 Q Y
- from net.sf.l2j.gameserver.model.quest.jython import QuestJython as JQuest' R) @$ y( T% Z P0 g7 a, M
2 z# c- n: r, t1 D$ I; M- KELTIR_NPC_ID = 120824 f/ y' w3 b4 V
- FANGS_ITEM_ID = 1859# b3 C3 v6 z8 Q
- DROP_RATE = 500000. E6 W5 L& |2 R; b! u! W, x
$ L. {" _$ t `; |. Z: K4 |- WORLD_MAP_ITEM_ID = 16651 a7 e. {6 b% B& ~* c
8 i( ^! E& @4 Y- k: \4 u+ z- def getCount(st) :
0 g1 d- M t8 |0 e3 U+ ^9 e- P+ \ - return st.getQuestItemsCount(FANGS_ITEM_ID)
. ]# z7 s' p6 O2 L1 G7 x7 `
. d) l" l# ?! Y( J+ n% H% K- def completed(st) :
+ w2 {( @/ a/ u - st.setState(COMPLETED)+ ? d! _! X- W$ u) R# M: m$ s+ V
- st.clearQuestDrops()" o, O( G) d6 u4 s/ }: O& h
- st.takeItems(FANGS_ITEM_ID,-1)- d" k* c5 n: i9 L* N' }: k
- st.giveItems(WORLD_MAP_ITEM_ID,1)( e4 o; T' g! q' V/ u3 f) Z" u. L
- st.exitQuest(False)2 J: b! [. S. n9 O/ b- W
- return
* s" I( A+ a! u2 ^/ }" o4 Z' s
, b- D6 Z4 E" l2 F6 P# g: a- def check(st) :4 F. }6 I' m9 e" ?4 o& c9 p
- if getCount(st) >= 4 :
: Z( N% d- `5 j* i* A - completed(st)
* V2 O0 Q, g6 \! ^( f - return
3 q: k1 Z. K# z9 q& w: c W: K/ v! ~" T: p
. @% j+ Q& o- v c2 e3 H- class Quest (JQuest):& P' d1 f; H* @4 D! S! { M
2 y5 C5 W# h( L% I# {$ o- def __init__(self,id,name,descr): JQuest.__init__(self,id,name,descr)$ v3 i4 x8 [7 q Y. z
, ]* O: P2 {2 R) Q5 z) w- def onEvent (self,event,st):
) S) r- Z3 E+ R x3 ]& s - id = st.getState()
6 a5 }% g/ k2 N/ f$ l5 x8 V, G - if id == CREATED : st.setState(STARTED)
% r; a0 `# H1 n8 R* o; `. c - elif id == COMPLETED: pass+ H0 c# G H+ u; x5 c6 C# v
- elif id == STARTED : check(st)
. k( l% ^1 w: p5 v, X - return0 P5 Y i' J% n
- 8 U- f( F+ d1 w- `4 @) B
- def onKill (self,npcId,st):) v' E$ m; M( `1 }8 {
- if npcId == KELTIR_NPC_ID:) L7 i7 S1 n7 L' ~6 A( x: k
- n = getCount(st)
* Y0 q" K. ?7 D7 ^0 e1 d7 u - if n == 0:9 t+ J T# [5 |& E( k" j7 e) w
- if st.get('chat0') == None :
4 ]8 t8 G+ Q/ G - st.set("chat0", "true")
0 n5 i0 ^/ o7 F9 ]$ C - return "Chat0.htm"
- O/ t2 P* T' k - elif n == 1:3 A, k6 X3 }2 X5 Z {
- if st.get('chat1') == None :
- e/ q0 s4 l- `* f: \4 U/ { - st.set("chat1", "true")
7 C2 N5 n# C: ?8 l& B2 ` - return "Chat1.htm"3 Y( Z5 ?2 q1 P
- elif n >= 4:
0 l# _! j8 X- m' A% j - return "Chat4.htm"
Z, z1 e0 r" C9 N# J! J9 r, W1 S - return "Collect "+str(n)+" of 4 fangs"* _ y5 s) }! D2 e
- return& z }1 j4 W! f
- % U$ R6 p- H3 I2 H; z6 a' h! [# K
- QUEST = Quest(201, "Tutorial", "Tutorial quest")
8 b M% @$ F4 }& N" Q - CREATED = State('Start', QUEST)) u7 o! r f7 X( o. A
- STARTED = State('Started', QUEST)% c" d' Y7 A# B* ]; F8 D- H
- COMPLETED = State('Completed', QUEST)1 z# r( N% e! o4 p# j" r7 F s2 L$ c
- 4 _: k' k8 {) {' z& R
- QUEST.setInitialState(CREATED)
* P" x1 |+ v% j+ Q2 l - QUEST.addStartNpc(7056)* L X& `9 K& I/ _) d
- QUEST.addStartNpc(7012)
& D! }/ F- ~/ g8 i8 t- X - QUEST.addStartNpc(7009)
, S7 U M5 P7 N) L. b# @; _1 G0 F7 n - QUEST.addStartNpc(7011)! u0 {" ]8 `! {+ f
8 M4 L- p$ g5 s) k* ~- STARTED.addQuestDrop(KELTIR_NPC_ID,FANGS_ITEM_ID,DROP_RATE)3 A9 R* }, }9 N3 N2 x
- STARTED.addKillId(KELTIR_NPC_ID)" o' a0 O% [9 t# W# ~
- STARTED.addTalkId(7056); q4 i/ v( A$ A2 t6 E1 ?2 ]
- STARTED.addTalkI d(7012)
: d% p# ?) g4 n/ y3 ] - STARTED.addTalkId(7009)8 M2 d5 M5 B1 @3 j! q
- STARTED.addTalkId(7011)
Скопировать код
6 n: A4 U9 X. x( a# n8 H1 s
' B3 h8 D3 F% e* N( }2 F# d |