Зарегистрируйтесь сейчас чтобы найти еще больше друзей, и получить полноценный доступ ко всем функциям сайта!
Для просмотра Вам необходимо авторизоваться Если Вы еще не зарегистрированы, перейдите по ссылке:Зарегистрироваться
x
Хроники Interlude
8 d3 }8 ]1 `! K. [; uСборка L2j6 s n/ s9 y: r# [! |2 w) A
Обратите внимание: в файле htm стартового NCP обязательно должна быть ссылка на квест:
# h; {% }5 V5 z- STARTED.addQuestDrop(KELTIR_NPC_ID,FANGS_ITEM_ID,DROP_RATE)
Скопировать код Для этого квеста больше ничего не надо. Все необходимое для корректной работы квеста уже добавили. Вот полный текст квеста:# I& E l1 ]3 {8 b2 @( J
+ m+ n( ]; j3 x! u: S- if getCount(st) >= 4 :
. a3 U2 Z0 J) p: p9 v/ f - completed(st)3 s# N$ c1 n3 M. u
- return
& Y: r# }1 d5 L/ j - $ E& g A2 E1 Y; S
- class Quest (JQuest):
o) Z6 g. D! Q% [8 G7 R - def __init__(self,id,name,descr): JQuest.__init__(self,id,name,descr)
( K, K, f# q+ n$ Y! @ C - def onEvent (self,event,st):
! q) G5 x0 s% N. E1 ]# B - id = st.getState()
# d2 W$ T9 d8 Z2 p, G0 a+ v/ x - if id == CREATED : st.setState(STARTED)
' n" x, ?# m O& ] - elif id == COMPLETED: pass
7 A( h5 [5 p- s7 R F3 | - elif id == STARTED : check(st)% ~5 ]* h" n, B+ S% r
- return- u0 c) _- x9 M/ m
) D" |3 K" ]- j6 P! ?) o( r$ B0 O- QUEST = Quest(201,"Tutorial", "Tutorial quest")% _( U* s! q+ R: D+ z
- CREATED = State('Start', QUEST)
' i, H# `& m7 n/ u6 Q - STARTED = State('Started', QUEST)
6 i( \! K& v9 v5 h - COMPLETED = State('Completed', QUEST)
' _, w8 _! D) C' z$ A6 j - 8 ~; M, i3 t9 s* @
- QUEST.setInitialState(CREATED)
8 W% u& i+ v) z, ^7 a - QUEST.addStartNpc(7056)& o. L7 r: |% n% r
- STARTED.addQuestDrop(KELTIR_NPC_ID,FANGS_ITEM_ID,DROP_RATE)
Скопировать код Теперь рассмотрим, как это работает.
; i" x( z" r/ v5 o0 P' b( K" _Игрок подходит к начальному NCP (в данном случае 7056), нажимает на «Quest». Квест будет создан и состояние квеста перейдет к CREATED и игроку будет показана страничка Start.htm с описанием квеста. Тогда метод onEvent, поле открытия странички Start.htm переведет состояние квеста в STARTED и игроку будет показана страничка Started.htm, где будет опсание того, как найти keltirs и .т.д.
$ S* j1 F3 G9 v2 ?
2 l6 @9 k# z. D9 h/ k B& h+ V
$ |* F4 ~9 B* |% A$ o2 Q, zПри состоянии STARTED будет зарегистрирован дроп «fangs» при убийстве keltirs. Игрок может вернуться к стартовому NCP и спросить о квесте – метод onEvent будет вызван снова. Если у игрока не хватает необходимого количества предметов, то метод check() не переведет квест в следующее состояние и Started.htm будет показана снова. Но если игрок собрал необходимее количество предметов (в данном случае 4 клыка), то метод check() вызовет метод completed() который переведет квест в новое состояние COMPLETED, заберет все клыки, даст карту мира, т.к. это награда за квест, покажет Completed.htm и завершит квест.+ D6 s& d Z; G2 K( {
; e& B, K# Q( X2 L
/ C1 q/ X( y8 ?1 V9 m5 K
Теперь давайте сделаем наш квест более похожим на то, что он должен из себя представлять.
3 a, ] \. M& vПрежде всего у нас есть 3 метода для объявления их в Яве – onTalk, onKill и onEvent. Если методы onTalk и onKill не объявлены, то за них все будет делать метод onEvent, т.е. определять квестовых монстров и вызывать диалоги NCP. Есть примечание, методы onTalk и onKill будут вызывать только диалоги с NCP в зависимости от текущего состояния квеста. Метод onKill будет вызываться только тогда, когда мы убиваем квестового монстра.# R* Y: G# F7 m& D6 O
0 u% H4 {3 w1 @4 c% l) v! V. d
, c4 q& o' n4 v* }Давайте рассмотрим как вызывается метод onKill при убийстве keltir в состоянии квеста STARTED:: T% T! C; D; b/ [6 m3 ]& A }. j
- STARTED.addKillId(KELTIR_NPC_ID)
Скопировать код и метод onKill в классе Quest:, T7 M# [1 Z- k& a7 J. g
% {& o7 P9 ?1 Y1 w! v/ B# {/ a5 I- class Quest (JQuest):) N+ L6 b& `2 q- Y
- ...
( `, d# Q+ m$ x5 P- u" I0 s p0 ] - def onKill (self,npcId,st):/ {2 H' b) X# T1 X" T0 v# T1 j: X
- if npcId == KELTIR_NPC_ID:
$ m |) H# Q9 ~" f7 F - n = getCount(st)1 D/ |. u$ j) B) E
- if n == 0:
( ?8 g8 [" Z0 N( Q* p - return "Chat0.htm"/ S! p$ P+ r7 N% S8 P8 H
- elif n == 1:, \* ]" }! w: S" f( @
- return "Chat1.htm"- J; l# i% j# C
- elif n >= 4:9 k: W1 v U7 E& S
- return "Chat4.htm"/ t7 q6 ^% i# O; X% k
- return "Collected "+str(n)+" of 4 fangs"6 h, u X0 T6 \# [& V
- return
Скопировать код Метод onKill (а так же метод onTalk) имеет следующие параметры:
: a! l; B4 p7 q& @0 Y# N
. i$ ]0 K, e) ]: @* \2 M: q# D6 g4 E- ~4 Z) K) H
• self – квест
3 g. w' P) `+ b% V5 P7 y• npcId – ID NCP, которого мы должны убивать (если это метод onTalk, то ID того NCP, с которым мы должны поговорить).
% X2 {, j% Z( S0 D: ~• st – текущее состояние игрока.; N! t0 ?$ {; t; S k
/ Q+ F+ M& _1 O6 N: s1 u% |4 _
9 ^1 P; m5 }6 x xВ этом методе мы проверяем и отмечаем, является ли убитый NCP keltir’ом. В основном эта проверка не нужна, т.к. у нас только KELTIR_NPC_ID.
m% o! K7 @9 R- b+ r6 K- W. O6 _- w {1 T* U' S" g
( h) P$ x \" V, t
Затем проверяем количество предметов (в данном случае количество клыков), и если их вообще нет, то возвращаем строку "Chat0.htm", если только один предмет, то возвращаем строку "Chat1.htm", если же предметов 4 или больше, то "Chat4.htm". Если строка возвращена из методов onEvent, onKill или onTalk, то сервер покажет соответствующие htm. В Chat0.htm может иметь следующий текст: «Вы не имеете ни одного клыка, возвращайтесь позже, когда соберете 4 штуки и бла, бла, бла…», в Chat1.htm может быть следующий текст: «У Вас всего 1 клык, по этому соберите еще…». В Chat4.htm – «Вы собрали необходимое количество предметов, возвращайтесь к вашему тренеру, что бы завершить квест…»
( ?/ x- ^: e8 X7 V0 U Q2 V% @
: Y9 d7 g/ T6 k. {, z! r' u
' i" H @8 o" H+ \7 C) AПримечание: если в строка return начинается с "<html>", то будет показана страничка html с текстом, который стоит далее. Так вместо:! J& _1 T; l$ t N |
return "Chat4.htm") e2 @1 K5 P3 p7 @2 W- Z
! _% ~& H2 Z$ R+ m
% H, v) R9 g, @можно поставить:
. z" H$ ^- G* x- return "<html><body>Return to your trainer to complete the quest</body></html>"
Скопировать код Так же если строка заканчивается без .htm или в начале нет <html>, то текст будет выведен, как системное сообщение в окне чата. В нашем случае мы сделаем так, что бы при каждом убийстве keltik выводилось системное сообщение: «Собрано N из 4-х клыков».
: r8 x0 H. Q5 a \2 Q9 }
/ Z \% x2 ^7 d( h. X, f3 ]4 z2 o* f& C3 m4 x/ z
Наш код для onKill имеет один недостаток. Он будет постоянно показывать Chat0.htm, Chat1.htm и Chat4.htm, нам же необходимо, что бы Chat0.htm и Chat1.htm показывались только один раз. Как нам это сделать? С помощью переменных.' ~, D+ F* ]+ D/ M9 l/ M) z
) g( G N. \0 p5 D0 |) L$ [0 W1 Y
- G( a: F3 r0 p) g* gВ каждом квесте строки могут храниться с помощью переменных. Эти переменные сохраняются в Вашей БД. В каждом методе мы можем назначить, прочитать и удалить переменные. Давайте изменим метод onKill, так что бы каждый диалог вызывался только один раз.: i) J+ \; l4 Y+ K5 K
- def onKill (self,npcId,st):) j& n% j' c4 I- ?% w6 |. ?; x
- if npcId == KELTIR_NPC_ID:
" r- ^# A- f1 v9 E0 T0 z" B: O - n = getCount(st)
; _% j: H) h; d+ q - if n == 0:
" V$ `+ N: a* D" Q - if st.get('chat0') == None :
; Y) Q1 B2 g: w5 x: i - st.set("chat0", "true"), F& n/ ]& H& {5 ~% J# p% z8 I
- return "Chat0.htm"- [9 z- `; c0 @
- elif n == 1:
9 y6 Y. i# p) Z$ ]+ a - if st.get('chat1') == None :
3 z( l+ ~; m* S' I - st.set("chat1", "true")
2 K, ]/ [5 f5 }) q' w - return "Chat1.htm"5 y, R5 j v# Q
- elif n >= 4:1 u( ~: e2 m: ~ U1 {
- return "Chat4.htm"" Y6 }8 S+ T4 f, i4 `1 K
- return "Collected "+str(n)+" of 4 fangs"
5 u2 @4 U& Z% x# g; |/ { e2 G8 e - return
Скопировать код Если у игрока нет клыков (n=0), то мы получаем занчение переменной 'chat0'. Когда метод onKill вызван в первый раз, то пока ни каких переменных не имеется и python возвращает значение None. В этом случае объявляется переменная и показывается диалог Chat0.htm. Когда мы убиваем keltir, но не получаем с него клык, функция st.get('chat0') возвращает строку true, а не None. И во второй раз окно с Chat0.htm не появится, но в окне чата появится строчка «Collected 0 of 4 fangs». По тому же принципу сделано и с Chat1.htm.
( f% |, M8 q5 F3 K" u. [8 Y" j% r' r* U* o* S( O
/ ~& Y" M: E6 V1 D" ?0 Q0 w* q
Вот конечный рабочий вариант квеста:
2 d6 `* k; Y$ o6 p% J1 i: C- import sys- C2 `+ H* o A D- L7 E& K7 ~9 R
- from net.sf.l2j.gameserver.model.quest import State7 |1 k' I: j% O& I$ n
- from net.sf.l2j.gameserver.model.quest import QuestState
; V' t6 D& @- W& S; Q - from net.sf.l2j.gameserver.model.quest.jython import QuestJython as JQuest _7 D# I& F/ j ^2 \% R @9 F
- . k, j; ]& j# P4 W* B! M7 r
- KELTIR_NPC_ID = 12082, a# u" D: K; u$ C9 R5 a3 a& c& \
- FANGS_ITEM_ID = 1859
5 A! c }( M7 c4 _ - DROP_RATE = 500000
" g' D% R' i2 U+ V - ; Z7 _8 x! D& ~1 t% M7 x' ~+ c3 w
- WORLD_MAP_ITEM_ID = 1665
0 W% [$ N6 w: V" u+ m' W& j
0 L. V1 J+ |! C* ^, n% F& j/ w- def getCount(st) :* F! q7 J1 q* J/ b1 E
- return st.getQuestItemsCount(FANGS_ITEM_ID)
) V! P" e7 |0 p
7 Q3 H6 H3 ~8 s$ B0 |- def completed(st) :$ O& d: m$ v9 v" y* @6 Y. G" l& f! A. M
- st.setState(COMPLETED)9 s5 N: z4 K& f$ Z6 L7 J9 o
- st.clearQuestDrops()* v$ i3 f' d+ `& b. O8 V
- st.takeItems(FANGS_ITEM_ID,-1)
5 h& r# q# G% U% m1 o ~* ~ - st.giveItems(WORLD_MAP_ITEM_ID,1)& \5 _3 a& k1 b* q
- st.exitQuest(False)# q! _% g$ \4 s" v% N9 k
- return3 Z6 l, U \6 k$ M, g1 r
- " Z: {: M' u2 e8 I6 N
- def check(st) :
+ A2 c9 r" v+ Z - if getCount(st) >= 4 :
}7 K- p c2 y0 d% g - completed(st)
& d: x: S* {: D& F - return: X1 o- M7 o8 H5 y9 v0 E
' B8 l, d, M$ R# \- class Quest (JQuest):. W# R9 @. y; s% }: R4 f- F# X u [
- 5 w5 S2 m& W* L7 k) Q, Q
- def __init__(self,id,name,descr): JQuest.__init__(self,id,name,descr)! p, m0 L0 s1 O1 m' O
* e& G* }4 I1 Z9 M- def onEvent (self,event,st):
, [& A+ ]8 s3 X6 ]; X. j! Y - id = st.getState() }2 C2 N: H# R2 @
- if id == CREATED : st.setState(STARTED)
2 g3 x: S7 D$ L - elif id == COMPLETED: pass
/ p$ X. {6 ]* q - elif id == STARTED : check(st)1 s5 h9 [! a: X. P
- return
! |9 [6 ?) I1 c/ J% S - - r% a" G- l' d# J
- def onKill (self,npcId,st): z1 ]6 K3 c; |7 m9 F
- if npcId == KELTIR_NPC_ID:4 a; j& Q0 D# d @: n
- n = getCount(st), ?( t% e# C, q6 F, u
- if n == 0:5 T5 s# D& c0 G1 G' G/ {3 S! |
- if st.get('chat0') == None :8 U4 w/ h2 j5 y' y: u
- st.set("chat0", "true")
. F5 G/ U; h3 Y8 q# R0 w - return "Chat0.htm"+ u! ?. r$ R4 F1 M% S8 ~1 B
- elif n == 1:# O% I0 h0 h4 p4 S
- if st.get('chat1') == None :
, M! _" d" e0 q" K6 R# w - st.set("chat1", "true")
( R3 T# k1 o: C* Z: o1 s$ s4 w: C6 X, b - return "Chat1.htm"
6 V7 H/ Q# s8 F% A0 M/ S - elif n >= 4:- J7 U3 {" p Q! n) m2 I
- return "Chat4.htm"# {6 H2 U1 _, r% {2 s b" \
- return "Collect "+str(n)+" of 4 fangs"
+ \& S2 `6 Q% E - return
( X2 a, v3 e: S* y+ d6 O: c0 [ - # s/ n4 R8 }+ C2 u& b9 C) ~/ o) f1 C. r
- QUEST = Quest(201, "Tutorial", "Tutorial quest")5 j4 x( [% p1 ]! _# I
- CREATED = State('Start', QUEST)- i, n* {8 h! ?* _' F# k; M& W
- STARTED = State('Started', QUEST)
) o( Y R3 i/ w - COMPLETED = State('Completed', QUEST)8 ?! `. }3 E9 b) M
- * G+ H6 g+ N1 X. i5 t
- QUEST.setInitialState(CREATED)
4 q! X5 `4 j1 N3 R - QUEST.addStartNpc(7056)3 t* Y5 a9 r! f' i: e/ J) F
- QUEST.addStartNpc(7012)7 s: V9 ]4 D$ ?+ P5 B: D5 G2 R5 d6 |
- QUEST.addStartNpc(7009)4 y( Y' c8 w& h+ k$ v, b
- QUEST.addStartNpc(7011)% e8 D, s/ H) e1 \
3 h: i& E' O4 L5 |8 O- STARTED.addQuestDrop(KELTIR_NPC_ID,FANGS_ITEM_ID,DROP_RATE)9 b7 q- a. `) t6 N" F
- STARTED.addKillId(KELTIR_NPC_ID)& ?4 W& Q: [9 ^; Q. P5 t/ y2 `2 b4 n
- STARTED.addTalkId(7056), u5 P* q! d4 s* ~) _
- STARTED.addTalkI d(7012)8 @0 b* q) z; m3 V/ [, y
- STARTED.addTalkId(7009)% g9 y1 @; ~: T: c1 T+ E
- STARTED.addTalkId(7011)
Скопировать код
1 G5 I2 c7 j& H" {( u0 {5 c& N& F4 f2 q6 E3 [' m" X% M
|