Зарегистрируйтесь сейчас чтобы найти еще больше друзей, и получить полноценный доступ ко всем функциям сайта!
Для просмотра Вам необходимо авторизоваться Если Вы еще не зарегистрированы, перейдите по ссылке:Зарегистрироваться
x
Хроники Interlude# t7 _8 o1 o$ D; L+ v1 L
Сборка L2j
1 ^8 N! X) N6 ^5 o. f) x7 MОбратите внимание: в файле htm стартового NCP обязательно должна быть ссылка на квест: X( Y: d' w1 g5 d( h+ B
- STARTED.addQuestDrop(KELTIR_NPC_ID,FANGS_ITEM_ID,DROP_RATE)
Скопировать код Для этого квеста больше ничего не надо. Все необходимое для корректной работы квеста уже добавили. Вот полный текст квеста:
( Z7 F4 w. e! I4 Z* w% d( b! l+ r1 `) ]) Z0 ~8 t8 Y% i
- if getCount(st) >= 4 :
0 M3 C& r0 _5 a" ]" p - completed(st)
" B$ r, Q) j3 G' I - return
t* P$ h9 e2 L8 B1 p& Q9 R1 b - 1 z7 s Q8 A/ \6 @5 R
- class Quest (JQuest):7 {- s. ^/ c) e1 } ]" r& M
- def __init__(self,id,name,descr): JQuest.__init__(self,id,name,descr); i h+ p9 S8 A% l/ p' b& d, M
- def onEvent (self,event,st):
- E s. G" Z" `) Q+ c ]+ W: I9 U - id = st.getState()$ z: _4 e8 `2 u9 S
- if id == CREATED : st.setState(STARTED)1 x7 j4 C6 {& _2 e0 J5 F1 b$ H
- elif id == COMPLETED: pass' g" {- s* S O9 n# k6 k
- elif id == STARTED : check(st)
8 |! w5 x! W/ A9 o) `8 f+ | - return
4 x8 r! L) B- x$ \
' s: o0 N. o) J7 Y) l- V$ b- l- QUEST = Quest(201,"Tutorial", "Tutorial quest")
: u- E* ?- q# q# W. N" w B0 Y+ W! L2 ` - CREATED = State('Start', QUEST)
9 {* c% f. T. S+ ~* k8 H - STARTED = State('Started', QUEST)
. u7 E! k2 n0 ~ - COMPLETED = State('Completed', QUEST)3 q( S Z: J3 Z8 ?
' c9 A/ R: [. F' C1 D" Y6 B- QUEST.setInitialState(CREATED)
; Z; J! X- v. O+ q/ e/ i: N, d - QUEST.addStartNpc(7056)
/ H7 r0 {& v8 {4 G - STARTED.addQuestDrop(KELTIR_NPC_ID,FANGS_ITEM_ID,DROP_RATE)
Скопировать код Теперь рассмотрим, как это работает.
- }6 ^' [7 r4 y& R2 bИгрок подходит к начальному NCP (в данном случае 7056), нажимает на «Quest». Квест будет создан и состояние квеста перейдет к CREATED и игроку будет показана страничка Start.htm с описанием квеста. Тогда метод onEvent, поле открытия странички Start.htm переведет состояние квеста в STARTED и игроку будет показана страничка Started.htm, где будет опсание того, как найти keltirs и .т.д.
7 d( O0 p+ _( a5 p+ x% V5 r4 b( d, E4 F! r! C
: Y W/ U+ _5 p4 R" h3 X
При состоянии STARTED будет зарегистрирован дроп «fangs» при убийстве keltirs. Игрок может вернуться к стартовому NCP и спросить о квесте – метод onEvent будет вызван снова. Если у игрока не хватает необходимого количества предметов, то метод check() не переведет квест в следующее состояние и Started.htm будет показана снова. Но если игрок собрал необходимее количество предметов (в данном случае 4 клыка), то метод check() вызовет метод completed() который переведет квест в новое состояние COMPLETED, заберет все клыки, даст карту мира, т.к. это награда за квест, покажет Completed.htm и завершит квест.0 h- M8 g: F! Q( u9 T: f
- U, v; O& r' c2 z/ R
6 M) c" {$ @* X9 w @Теперь давайте сделаем наш квест более похожим на то, что он должен из себя представлять.# X7 g, k9 Y: |1 |
Прежде всего у нас есть 3 метода для объявления их в Яве – onTalk, onKill и onEvent. Если методы onTalk и onKill не объявлены, то за них все будет делать метод onEvent, т.е. определять квестовых монстров и вызывать диалоги NCP. Есть примечание, методы onTalk и onKill будут вызывать только диалоги с NCP в зависимости от текущего состояния квеста. Метод onKill будет вызываться только тогда, когда мы убиваем квестового монстра.. I& m' p( r) X# k1 W: p+ S
/ \8 ~7 w0 q$ }+ u
9 ^1 A- p y/ D8 P J
Давайте рассмотрим как вызывается метод onKill при убийстве keltir в состоянии квеста STARTED:' d N# D" O, k, O
- STARTED.addKillId(KELTIR_NPC_ID)
Скопировать код и метод onKill в классе Quest:
) x* M/ ~- F, U1 q. p8 }& R- \( A m( P+ M8 N
- class Quest (JQuest):0 M& f9 O( |' `3 Q6 m0 {0 l
- ...( ^( ]; w" q3 t4 j. O6 u# m
- def onKill (self,npcId,st):0 {' }% S8 @! M7 [3 H- e+ r
- if npcId == KELTIR_NPC_ID:
. V9 b5 p/ Y, { - n = getCount(st)
& t( o: c+ r# ~4 j9 U - if n == 0:
, Q" _ K9 `0 g - return "Chat0.htm"+ Q7 Y6 t' [( |$ u
- elif n == 1:% j. @! h/ d: r Y& q4 l
- return "Chat1.htm"% {4 Q9 [' L4 F
- elif n >= 4:) y5 n* w$ f+ l7 s
- return "Chat4.htm"
% n# ]; {' q2 L$ F. p - return "Collected "+str(n)+" of 4 fangs"6 r2 [2 R. t3 r
- return
Скопировать код Метод onKill (а так же метод onTalk) имеет следующие параметры:, h0 U5 z4 {3 K- D6 j) B
* T- E# i7 A7 m" E7 b6 B% D
( T2 f5 M/ S# k: J7 A2 P• self – квест8 o# s0 t3 c% B; x% M9 ^
• npcId – ID NCP, которого мы должны убивать (если это метод onTalk, то ID того NCP, с которым мы должны поговорить).
5 K( s& B/ P. P ]+ b0 F• st – текущее состояние игрока.0 W7 c& K) h. r" Q
/ f1 b' j) g1 D/ \7 q
$ E, Q9 Z, `. w4 K& MВ этом методе мы проверяем и отмечаем, является ли убитый NCP keltir’ом. В основном эта проверка не нужна, т.к. у нас только KELTIR_NPC_ID.; d3 L1 ?6 n6 y$ i6 o
9 j# Z4 ?8 P7 S% m" [
! y9 t, \! P/ BЗатем проверяем количество предметов (в данном случае количество клыков), и если их вообще нет, то возвращаем строку "Chat0.htm", если только один предмет, то возвращаем строку "Chat1.htm", если же предметов 4 или больше, то "Chat4.htm". Если строка возвращена из методов onEvent, onKill или onTalk, то сервер покажет соответствующие htm. В Chat0.htm может иметь следующий текст: «Вы не имеете ни одного клыка, возвращайтесь позже, когда соберете 4 штуки и бла, бла, бла…», в Chat1.htm может быть следующий текст: «У Вас всего 1 клык, по этому соберите еще…». В Chat4.htm – «Вы собрали необходимое количество предметов, возвращайтесь к вашему тренеру, что бы завершить квест…». g4 t) K. \5 B) O
0 i9 w' ^! I% p0 ]) I
` E; _8 ^( CПримечание: если в строка return начинается с "<html>", то будет показана страничка html с текстом, который стоит далее. Так вместо:
( K9 A; I& M8 w8 |$ B% }2 Dreturn "Chat4.htm"
* ~; \: H3 }4 b
5 Y- b c% ]; M
9 G; g+ W& e: k) m4 t9 Eможно поставить:
2 v3 n, `2 o: U9 D' W- r: `. C- return "<html><body>Return to your trainer to complete the quest</body></html>"
Скопировать код Так же если строка заканчивается без .htm или в начале нет <html>, то текст будет выведен, как системное сообщение в окне чата. В нашем случае мы сделаем так, что бы при каждом убийстве keltik выводилось системное сообщение: «Собрано N из 4-х клыков».
0 X; Y3 U! g1 p* t0 k. Y2 Y/ B( S5 m: Q$ a
1 w3 Q! v% v% } ^
Наш код для onKill имеет один недостаток. Он будет постоянно показывать Chat0.htm, Chat1.htm и Chat4.htm, нам же необходимо, что бы Chat0.htm и Chat1.htm показывались только один раз. Как нам это сделать? С помощью переменных.
7 y4 t/ N- Q& y( P8 F, j
2 u, V- f( @ h" U1 s. J) h9 p0 s
В каждом квесте строки могут храниться с помощью переменных. Эти переменные сохраняются в Вашей БД. В каждом методе мы можем назначить, прочитать и удалить переменные. Давайте изменим метод onKill, так что бы каждый диалог вызывался только один раз.
0 T) {+ U7 o( d, d5 D( z- def onKill (self,npcId,st):' L& m' E" i: p$ w) G
- if npcId == KELTIR_NPC_ID:
P' _, D3 W0 b% Z' |- z; f - n = getCount(st)1 R0 Z J4 b& g
- if n == 0:, k: j" g( L. q
- if st.get('chat0') == None :
6 y& r' f7 h3 u3 X - st.set("chat0", "true")/ `- s& M' a' I& Q
- return "Chat0.htm"
# }0 m" B' G* b/ a9 v0 { - elif n == 1:3 A( j7 R% E; [1 U
- if st.get('chat1') == None :7 J0 g+ `3 a& F' h, |5 ^' S
- st.set("chat1", "true")
+ m" n2 B; l. h9 r9 }: \% J - return "Chat1.htm"
, b, I, E6 `7 V. N4 W7 g4 Z- q! X - elif n >= 4:0 c! |! K" c% |3 |; T9 C
- return "Chat4.htm"
8 U& x5 b9 V6 g3 S1 U0 X$ w5 ` - return "Collected "+str(n)+" of 4 fangs". N' p# j+ }" Q* Q
- return
Скопировать код Если у игрока нет клыков (n=0), то мы получаем занчение переменной 'chat0'. Когда метод onKill вызван в первый раз, то пока ни каких переменных не имеется и python возвращает значение None. В этом случае объявляется переменная и показывается диалог Chat0.htm. Когда мы убиваем keltir, но не получаем с него клык, функция st.get('chat0') возвращает строку true, а не None. И во второй раз окно с Chat0.htm не появится, но в окне чата появится строчка «Collected 0 of 4 fangs». По тому же принципу сделано и с Chat1.htm.- K4 @1 ?$ ]4 G
$ Z2 o; i+ c1 Q/ z6 \5 [1 S% m8 P9 F4 E" e
Вот конечный рабочий вариант квеста:
( l! t) o9 a4 b, T- import sys0 `, G7 }" B& k' p' D/ G" G' F- ?
- from net.sf.l2j.gameserver.model.quest import State
8 H( c. E$ r p7 h! ^ - from net.sf.l2j.gameserver.model.quest import QuestState F4 o% Z+ s1 o; f# p
- from net.sf.l2j.gameserver.model.quest.jython import QuestJython as JQuest
j, K9 F$ B( K) w2 N+ t- \- p
/ l) U/ O ~& L& L% U' B) @& Y- KELTIR_NPC_ID = 12082 a I9 X9 }# X% ^% o' R
- FANGS_ITEM_ID = 1859
o) o3 h. D0 N - DROP_RATE = 500000
" `) H: @( s3 d$ G1 [; e
8 t! t* o9 E3 z* k! I- WORLD_MAP_ITEM_ID = 1665
& [' Q) v( [/ d$ z4 n) C; N* z - 3 Q; D( m' G! N1 x b' U4 Q
- def getCount(st) :2 S2 Z) T5 e4 H+ O
- return st.getQuestItemsCount(FANGS_ITEM_ID)
, K& ]9 f7 ^2 N8 G' t
6 {1 v5 j% S( d! e- def completed(st) :9 ?+ L* ~4 z0 S9 }( w1 b: ?: A
- st.setState(COMPLETED)% X( _; I& U+ d" n! ~
- st.clearQuestDrops()- v' c5 }1 g c( m5 W1 A
- st.takeItems(FANGS_ITEM_ID,-1)
+ t$ x; F8 d) h$ Q- G* `5 |3 W - st.giveItems(WORLD_MAP_ITEM_ID,1)7 n5 V0 ], P- H" k7 Q5 S( T
- st.exitQuest(False)
2 ]* Y1 `2 m; \2 j2 _* E" G, Y - return
- @8 z* U! D( I - w+ S9 D* q: @3 Z, M v: g' E
- def check(st) :0 _0 R% x' u" C8 b8 Q3 V/ n9 V
- if getCount(st) >= 4 :
- _5 S! C f* j, o" s1 Z0 E9 d" u - completed(st)2 O. C# `8 q9 _
- return
1 r9 \+ B* D7 x; C) P
5 |" v! K" P9 l }; Z, a0 ]6 w- class Quest (JQuest):
; V; ?5 |* k0 a) r
; t) Z8 l; g- \" j, x- def __init__(self,id,name,descr): JQuest.__init__(self,id,name,descr)
9 Q" f0 j! j7 u- X# L' Q9 [ - ) U( \4 ?! h3 w, R4 b* N$ [
- def onEvent (self,event,st):& @& Y4 ]3 E0 P0 K7 q0 k! A
- id = st.getState()
; t0 n6 G3 i, J( Q- z g; B% C) x - if id == CREATED : st.setState(STARTED)- }) {2 E1 k8 q1 m$ f" S& ]6 Z
- elif id == COMPLETED: pass
, z" F( ?0 @9 k: X* e - elif id == STARTED : check(st): Q' {2 T+ ?1 x/ V0 O R
- return8 H' d/ m. W6 _' M7 w+ ]
6 S( _- h; R0 @9 {, g! Q& B- def onKill (self,npcId,st):
+ o; O3 k& h b1 v. \ - if npcId == KELTIR_NPC_ID:- _: N& ~6 P; y5 N, N/ a
- n = getCount(st)* ?+ ?1 S }6 \ ]" b3 D- L
- if n == 0:
4 c/ G4 q$ @2 V1 H; S- c - if st.get('chat0') == None :
6 t7 ?0 L) f) v/ k* B) [. o0 i+ E5 j - st.set("chat0", "true")8 w- a; C0 \* ?/ a% v
- return "Chat0.htm"
' Y3 @) p: K Q - elif n == 1:
4 f7 v- `: L* h) v% J4 X - if st.get('chat1') == None :$ e5 [4 S1 }: t$ D7 u+ U7 l" c
- st.set("chat1", "true")
+ f( @1 E+ C( ?' D - return "Chat1.htm"$ D) h M! K D2 J4 S5 [9 k
- elif n >= 4:
8 [! [- l$ l# Q( x9 |# ~. ^# U - return "Chat4.htm"
5 @6 R6 K( s; H7 Q/ }% G5 @5 l - return "Collect "+str(n)+" of 4 fangs"
6 n6 \, {6 [' k& L; e+ u/ d: Y - return% M2 C) P% T4 H$ z
- u5 J4 W( e. t0 B. a! F- QUEST = Quest(201, "Tutorial", "Tutorial quest")0 t, j5 D7 t' a$ N! q \+ @
- CREATED = State('Start', QUEST)
) j0 K0 f' C4 N( o - STARTED = State('Started', QUEST)
$ ~2 _. I( i5 } - COMPLETED = State('Completed', QUEST)
/ K y& X5 K/ T: I% ?0 Q: ]
9 z- u# n5 C1 ^4 | [( L W0 I- QUEST.setInitialState(CREATED)
0 y' T D, O9 @ - QUEST.addStartNpc(7056)
5 L8 ?" p$ X( D: x - QUEST.addStartNpc(7012)
- E( ?/ W. U' w e: X% f2 u& p1 B% o - QUEST.addStartNpc(7009)
9 d" i$ [1 G _- n( F ]- y7 Q/ E& s - QUEST.addStartNpc(7011)
- N9 e. j; s2 y- r. b2 z7 ]
3 R( o8 F% P: M* Q- STARTED.addQuestDrop(KELTIR_NPC_ID,FANGS_ITEM_ID,DROP_RATE)
% J! @. x5 Y9 o; G6 p7 t - STARTED.addKillId(KELTIR_NPC_ID)
* e- y0 G4 J6 H* R - STARTED.addTalkId(7056)1 y- I/ S1 s/ |0 X
- STARTED.addTalkI d(7012)+ S, f0 t+ r: @4 H' u) u; Q
- STARTED.addTalkId(7009)! F) V/ W, P5 Q$ I* D) w
- STARTED.addTalkId(7011)
Скопировать код # _9 }: p( l- x. G" x" F
. ]; g) w- b/ f! v |