Зарегистрируйтесь сейчас чтобы найти еще больше друзей, и получить полноценный доступ ко всем функциям сайта!
Для просмотра Вам необходимо авторизоваться Если Вы еще не зарегистрированы, перейдите по ссылке:Зарегистрироваться
x
Хроники Interlude. Y( N& K6 J* `8 \
Сборка L2j- \- L$ a: ~: n7 w0 @& [
Обратите внимание: в файле htm стартового NCP обязательно должна быть ссылка на квест:+ S5 Z& |' \$ v! k% E
- STARTED.addQuestDrop(KELTIR_NPC_ID,FANGS_ITEM_ID,DROP_RATE)
Скопировать код Для этого квеста больше ничего не надо. Все необходимое для корректной работы квеста уже добавили. Вот полный текст квеста:
% J% Q. u$ ]8 K5 k: w; ^/ n) b; Y" O, W$ I! {
- if getCount(st) >= 4 :$ |1 I$ \& \" c- _; H" z1 O5 y F, r
- completed(st)
' I9 W7 }5 }% _' q+ L: K+ _ - return
; X, L. y& U: D" ?) R; v+ y8 |; o
6 h; d# [8 G5 q- W- class Quest (JQuest):
% v- ]+ C& k$ X - def __init__(self,id,name,descr): JQuest.__init__(self,id,name,descr). x8 P) |9 i7 S4 V& V
- def onEvent (self,event,st):
" D* w' A4 k" y/ @ - id = st.getState()
& j% P5 g* y' f/ v* ]6 c - if id == CREATED : st.setState(STARTED)3 |3 G4 z3 o, T
- elif id == COMPLETED: pass
8 z! @2 u- O) m, e- ]$ b. U - elif id == STARTED : check(st) A0 S5 T0 I! ?% t! q
- return
5 c$ L. ?2 M5 Q) k7 S, S! u
7 P2 i2 t& U8 [! J2 f' @- QUEST = Quest(201,"Tutorial", "Tutorial quest")2 r/ V! ?/ X5 |& q' G9 C
- CREATED = State('Start', QUEST)
+ h7 R: ~ q2 }' T/ m( z3 ^5 G' L - STARTED = State('Started', QUEST)6 L; M' T2 p$ W% ?# O; ?
- COMPLETED = State('Completed', QUEST)( _+ u: K' k2 h
% A: _; d; O' _/ u- QUEST.setInitialState(CREATED)
' [. r& }/ _+ ^5 d - QUEST.addStartNpc(7056)
5 ]. Y! r3 }, L2 H - STARTED.addQuestDrop(KELTIR_NPC_ID,FANGS_ITEM_ID,DROP_RATE)
Скопировать код Теперь рассмотрим, как это работает.) X, p! o) `+ r
Игрок подходит к начальному NCP (в данном случае 7056), нажимает на «Quest». Квест будет создан и состояние квеста перейдет к CREATED и игроку будет показана страничка Start.htm с описанием квеста. Тогда метод onEvent, поле открытия странички Start.htm переведет состояние квеста в STARTED и игроку будет показана страничка Started.htm, где будет опсание того, как найти keltirs и .т.д.
+ p. M; N2 E% a, b3 c/ c) @* f" [* M' @2 }
9 V4 u, v& S( P: q; P: OПри состоянии STARTED будет зарегистрирован дроп «fangs» при убийстве keltirs. Игрок может вернуться к стартовому NCP и спросить о квесте – метод onEvent будет вызван снова. Если у игрока не хватает необходимого количества предметов, то метод check() не переведет квест в следующее состояние и Started.htm будет показана снова. Но если игрок собрал необходимее количество предметов (в данном случае 4 клыка), то метод check() вызовет метод completed() который переведет квест в новое состояние COMPLETED, заберет все клыки, даст карту мира, т.к. это награда за квест, покажет Completed.htm и завершит квест.
/ W9 \, V9 T7 N4 G' ~1 k6 E0 l: |. V# A$ R( l/ g+ M X- d0 C4 m7 |$ g
6 y# d" z2 ^- i6 y( O
Теперь давайте сделаем наш квест более похожим на то, что он должен из себя представлять.. \6 N: |0 i' M9 W% R4 W0 [
Прежде всего у нас есть 3 метода для объявления их в Яве – onTalk, onKill и onEvent. Если методы onTalk и onKill не объявлены, то за них все будет делать метод onEvent, т.е. определять квестовых монстров и вызывать диалоги NCP. Есть примечание, методы onTalk и onKill будут вызывать только диалоги с NCP в зависимости от текущего состояния квеста. Метод onKill будет вызываться только тогда, когда мы убиваем квестового монстра.9 Y( X) i9 S3 V7 p1 f
/ I- `& F1 X2 G9 I: z7 X V, B. ?7 e( S3 o
Давайте рассмотрим как вызывается метод onKill при убийстве keltir в состоянии квеста STARTED:
0 a1 T$ {0 u2 D) t7 u- STARTED.addKillId(KELTIR_NPC_ID)
Скопировать код и метод onKill в классе Quest:$ ]& k0 T) t4 W% t/ t8 d
& v4 E4 `( R1 r& B+ P- class Quest (JQuest):
* H$ B; K: _3 t3 l3 L1 Y- G* g - ...8 M- _8 j7 L) o2 i
- def onKill (self,npcId,st):
! t1 }: g% t& K - if npcId == KELTIR_NPC_ID:
0 W/ P* M' O- K4 r6 D0 G' n - n = getCount(st)+ Z: o$ E, R" ^' H, v
- if n == 0:6 a l1 W7 [1 x9 G/ v/ ~. c; r
- return "Chat0.htm"
) E. }% L6 n, z/ h4 q: T - elif n == 1:
# s. [' J e2 k2 x2 a - return "Chat1.htm"
/ Y4 \2 o$ A1 g& K. A7 r* W) {1 c - elif n >= 4:1 r7 f `, c/ X& U6 Y
- return "Chat4.htm"
. a( k: v& W. ]7 g6 M6 _ - return "Collected "+str(n)+" of 4 fangs"+ l' ^; I+ I$ T4 ]" S
- return
Скопировать код Метод onKill (а так же метод onTalk) имеет следующие параметры:6 C- q& e$ s( e5 P0 d
4 g) A: L/ I) X3 v
7 D$ q2 X5 X) V2 j• self – квест
- D0 |8 w* G( ]• npcId – ID NCP, которого мы должны убивать (если это метод onTalk, то ID того NCP, с которым мы должны поговорить).5 e2 l2 i8 V4 K7 S; U! \( o) l
• st – текущее состояние игрока.3 O7 L+ M' Y/ L; k
: h' y* @3 t4 f/ A/ ]. P) ]# h5 j
. d8 D5 |2 F3 H: \/ w- jВ этом методе мы проверяем и отмечаем, является ли убитый NCP keltir’ом. В основном эта проверка не нужна, т.к. у нас только KELTIR_NPC_ID.3 Q8 _+ W+ Q6 B7 ?0 Z
3 E) m [6 y- h# o1 `0 E
5 G. E3 ]6 l* A3 Y ~- g, RЗатем проверяем количество предметов (в данном случае количество клыков), и если их вообще нет, то возвращаем строку "Chat0.htm", если только один предмет, то возвращаем строку "Chat1.htm", если же предметов 4 или больше, то "Chat4.htm". Если строка возвращена из методов onEvent, onKill или onTalk, то сервер покажет соответствующие htm. В Chat0.htm может иметь следующий текст: «Вы не имеете ни одного клыка, возвращайтесь позже, когда соберете 4 штуки и бла, бла, бла…», в Chat1.htm может быть следующий текст: «У Вас всего 1 клык, по этому соберите еще…». В Chat4.htm – «Вы собрали необходимое количество предметов, возвращайтесь к вашему тренеру, что бы завершить квест…»+ x9 n3 C) t# a9 Y! O
% k9 f; w% a/ T: @% a
; w5 I+ `$ j8 J! vПримечание: если в строка return начинается с "<html>", то будет показана страничка html с текстом, который стоит далее. Так вместо:; e3 x! u3 y* S5 [4 c B
return "Chat4.htm"0 n$ y% N j/ a5 B7 E% |
# F% V; `( E2 w. G
) M- k/ j- i$ w' R6 [" S5 pможно поставить:
2 C* F- {% ^/ x W: [8 ^# ?# F- return "<html><body>Return to your trainer to complete the quest</body></html>"
Скопировать код Так же если строка заканчивается без .htm или в начале нет <html>, то текст будет выведен, как системное сообщение в окне чата. В нашем случае мы сделаем так, что бы при каждом убийстве keltik выводилось системное сообщение: «Собрано N из 4-х клыков».$ f6 a9 K. m- o l
* n$ B/ Y; y$ j
( ]' ^ |: e( {/ M, O! N! c1 q \Наш код для onKill имеет один недостаток. Он будет постоянно показывать Chat0.htm, Chat1.htm и Chat4.htm, нам же необходимо, что бы Chat0.htm и Chat1.htm показывались только один раз. Как нам это сделать? С помощью переменных.5 B2 V9 i9 X' f# Y6 |0 V
& ?5 X7 j. H2 F! ~6 z4 R9 x
+ N' @- B1 `; nВ каждом квесте строки могут храниться с помощью переменных. Эти переменные сохраняются в Вашей БД. В каждом методе мы можем назначить, прочитать и удалить переменные. Давайте изменим метод onKill, так что бы каждый диалог вызывался только один раз.$ O% k% x6 T5 f) ~% r
- def onKill (self,npcId,st):
f0 m0 U9 J5 l7 H1 ~# f$ ~ - if npcId == KELTIR_NPC_ID:7 }+ E# T9 m4 U6 [: I; B
- n = getCount(st)# v8 K! J2 j. T
- if n == 0:+ A2 j3 |3 Z5 W9 S" D
- if st.get('chat0') == None :
- H$ K. j6 T) Z( T5 b8 m/ r4 z - st.set("chat0", "true")
; b3 _+ |6 E$ I - return "Chat0.htm"
0 n" C; ^- A/ o6 Q; W - elif n == 1:# W4 v, v J" R5 ^3 @8 |9 V, m* R9 a
- if st.get('chat1') == None :
* z, W* S" ?, R. p) U5 A2 b - st.set("chat1", "true")0 v# q! `; X; |5 D9 [7 k. f
- return "Chat1.htm"
% G# m, v, R4 k+ p& z' [ - elif n >= 4:
+ b8 ]& M1 T( J% x - return "Chat4.htm"
$ h4 v q! @3 K( c, } - return "Collected "+str(n)+" of 4 fangs"/ s, H& ]9 w, T
- return
Скопировать код Если у игрока нет клыков (n=0), то мы получаем занчение переменной 'chat0'. Когда метод onKill вызван в первый раз, то пока ни каких переменных не имеется и python возвращает значение None. В этом случае объявляется переменная и показывается диалог Chat0.htm. Когда мы убиваем keltir, но не получаем с него клык, функция st.get('chat0') возвращает строку true, а не None. И во второй раз окно с Chat0.htm не появится, но в окне чата появится строчка «Collected 0 of 4 fangs». По тому же принципу сделано и с Chat1.htm.+ X4 ]4 Q9 y) S/ k+ ~6 f
' v6 x& }& f# @- v
, u; z! u& H: N. x \2 M6 mВот конечный рабочий вариант квеста:, p- L$ R4 p( N1 Q0 M' A# G3 I
- import sys
3 S( _% k1 a6 ^) t( j1 A - from net.sf.l2j.gameserver.model.quest import State
) S. R8 Z9 ~. z - from net.sf.l2j.gameserver.model.quest import QuestState
) ]8 h! \ i2 M# ? - from net.sf.l2j.gameserver.model.quest.jython import QuestJython as JQuest0 M- x9 ^* Q! ]2 j8 P& O7 f! @
- 5 g' o* M5 Q- p) X9 v o+ r
- KELTIR_NPC_ID = 12082# `" g1 w1 ^- i1 n3 }
- FANGS_ITEM_ID = 1859
9 l7 W* k- o8 m) Q3 r4 v7 E - DROP_RATE = 500000$ ?$ ~' }- F" z( U, x# V) X) T; o
6 b3 ~. l7 K# K% L& w; B" Z- WORLD_MAP_ITEM_ID = 1665
, J8 z; M$ k3 a$ G' o
, }7 b4 K: X5 k9 J& E- def getCount(st) :
! B& Z3 z! h5 v# L \1 a - return st.getQuestItemsCount(FANGS_ITEM_ID)
1 u1 x, T H% ^) h% P - 2 o( c# B" r: k, ?# H; W
- def completed(st) :7 K2 I+ R, @, E3 \6 b4 D1 X6 p
- st.setState(COMPLETED), x1 T2 u, a+ y; D
- st.clearQuestDrops()
5 A, n7 b6 ~& e. u! m - st.takeItems(FANGS_ITEM_ID,-1)
9 ~7 S: ]# r# D% ^' Q - st.giveItems(WORLD_MAP_ITEM_ID,1)
( t' q0 [- R0 r9 J; ~0 C - st.exitQuest(False)* `" s0 l/ V! S9 I
- return( I0 V$ N0 k! ~% H- ]" M- c# B
- 4 |- H4 |" l K6 z) o+ I
- def check(st) :
7 s$ y# S4 e! y5 M. s( i - if getCount(st) >= 4 :+ I0 M; J) M' l6 v
- completed(st)
/ S9 h5 ?% N% E* y - return
* @) w$ \0 n+ g) f! o
5 ^' Z: A* n) ^, E- class Quest (JQuest):7 }9 L# I5 w! v+ e
0 D' g/ y ^- ^3 G- def __init__(self,id,name,descr): JQuest.__init__(self,id,name,descr)* R6 I' x0 P( ~# q: K) l* l& z3 e
- + p8 w& {9 U' x) j! E4 Q
- def onEvent (self,event,st):. ^+ t5 U. ^9 J
- id = st.getState()5 F& w; l: m3 ]1 `
- if id == CREATED : st.setState(STARTED)5 X& k, X5 X3 D$ w$ H' @. i
- elif id == COMPLETED: pass% u# e& s# R, s% S2 U1 o
- elif id == STARTED : check(st)0 v8 f% e2 S% s0 \
- return
1 J9 D' l' G* e+ W8 ?6 ~% p5 c' F
7 q6 l- P! C# O3 B: j! N/ c- def onKill (self,npcId,st):$ o$ o' ~( p }) G2 T- T
- if npcId == KELTIR_NPC_ID:
+ o! @/ \: ?$ g& l; H - n = getCount(st)( f+ m8 K4 P3 y2 W7 i1 Q" j/ _* l
- if n == 0:; G: ^" g1 l: B8 a' a, d
- if st.get('chat0') == None :7 K! m: Y2 {5 b& Z: M, {( k* h
- st.set("chat0", "true")& u4 S7 {2 l$ b7 K7 P
- return "Chat0.htm": d) \5 w! z6 p; r5 U* ]
- elif n == 1:3 B. {" s6 N$ u' v9 |
- if st.get('chat1') == None :
) Z0 C4 s9 Q) \- w, B - st.set("chat1", "true"). ^5 R8 q, S( D _
- return "Chat1.htm"9 n3 z& _2 I/ z- o8 I
- elif n >= 4:& B% |$ \: g3 u0 L1 K3 e/ {
- return "Chat4.htm"
' J" ^( S6 ?0 n% [9 e - return "Collect "+str(n)+" of 4 fangs"- [" B# l+ h* k6 s7 e5 \8 b
- return8 L. D' y2 k$ c3 m& T
/ ~7 X7 E1 r J4 Y# R- QUEST = Quest(201, "Tutorial", "Tutorial quest")/ K! d" U ^# z3 H
- CREATED = State('Start', QUEST): j' P& V( t" X/ l
- STARTED = State('Started', QUEST)5 X9 T8 b" n3 s
- COMPLETED = State('Completed', QUEST)* J& g% B# _8 A
- 9 `' q/ _: e( ]9 ]8 j, @2 M' t6 t
- QUEST.setInitialState(CREATED)0 [. b6 ] Q; L/ ~) U& N
- QUEST.addStartNpc(7056)
( P* s( ?& Z7 B, {: L. g7 a& O& { - QUEST.addStartNpc(7012)9 ~2 X- i+ m) _$ }
- QUEST.addStartNpc(7009)
0 V) x s. t4 ^ _ - QUEST.addStartNpc(7011)
9 r f: n# N& t
5 T! s! q3 a6 t# b- STARTED.addQuestDrop(KELTIR_NPC_ID,FANGS_ITEM_ID,DROP_RATE)
( K9 c l" ?. I9 W4 r7 v! F3 N' F - STARTED.addKillId(KELTIR_NPC_ID)4 P$ ^8 O7 d! i1 |7 B; Z0 U
- STARTED.addTalkId(7056)
$ z4 O, R8 ^ N1 ~ - STARTED.addTalkI d(7012): Z* w1 t, v/ U* g
- STARTED.addTalkId(7009)1 u9 R) S2 p9 m' u2 t! _
- STARTED.addTalkId(7011)
Скопировать код 9 k2 h& Z+ O6 r8 l( b' {
% ?4 J0 M% z4 g9 J5 o
|