Зарегистрируйтесь сейчас чтобы найти еще больше друзей, и получить полноценный доступ ко всем функциям сайта!
Для просмотра Вам необходимо авторизоваться Если Вы еще не зарегистрированы, перейдите по ссылке:Зарегистрироваться
x
Хроники Interlude' A! S/ V" m# A" X
Сборка L2j
' F* `: C, W" nОбратите внимание: в файле htm стартового NCP обязательно должна быть ссылка на квест:
! |. @7 j" C" h. U- STARTED.addQuestDrop(KELTIR_NPC_ID,FANGS_ITEM_ID,DROP_RATE)
Скопировать код Для этого квеста больше ничего не надо. Все необходимое для корректной работы квеста уже добавили. Вот полный текст квеста:
% c( ^. G4 [" z6 J5 p' ^6 h6 O0 }2 l. H0 y/ {( ^
- if getCount(st) >= 4 :# Z; l- j* z9 q
- completed(st)6 o- Q" e& r& e( I
- return" i% n( \/ F$ l* G" E" |4 A9 ]! I
- & J [, S5 t1 o3 Y/ T* m3 _* G
- class Quest (JQuest):
0 h2 \1 |# ]4 ^7 |# h; w, o - def __init__(self,id,name,descr): JQuest.__init__(self,id,name,descr)5 p( o7 D. q' O4 K( l
- def onEvent (self,event,st):
6 W5 w+ V& Q' c0 ` - id = st.getState()) p) r4 P' I9 @) E
- if id == CREATED : st.setState(STARTED)
( ^& \. `6 h/ x/ s: \. ], u( Z - elif id == COMPLETED: pass& K$ E, {/ \, B+ a6 x
- elif id == STARTED : check(st); W) B$ G3 K8 F
- return
2 y( c7 B6 l8 a7 L - ! m: b" g7 u. F6 y0 _
- QUEST = Quest(201,"Tutorial", "Tutorial quest")& ?% ~% A& P+ I& r( d- V6 b
- CREATED = State('Start', QUEST)+ D6 ^) _* N- O, Q' t5 a1 d2 ]. H
- STARTED = State('Started', QUEST)
5 l4 O0 a& r9 Z) w1 P3 O - COMPLETED = State('Completed', QUEST)
0 L m+ `5 w: v) h; E3 V8 T
/ `- t9 f1 j3 X. {0 U+ @- QUEST.setInitialState(CREATED)
9 u9 t; T' Q" s2 s3 v' u+ t - QUEST.addStartNpc(7056). H' s( f' f6 ]. C% |
- STARTED.addQuestDrop(KELTIR_NPC_ID,FANGS_ITEM_ID,DROP_RATE)
Скопировать код Теперь рассмотрим, как это работает.* n/ i/ c6 @4 c( _
Игрок подходит к начальному NCP (в данном случае 7056), нажимает на «Quest». Квест будет создан и состояние квеста перейдет к CREATED и игроку будет показана страничка Start.htm с описанием квеста. Тогда метод onEvent, поле открытия странички Start.htm переведет состояние квеста в STARTED и игроку будет показана страничка Started.htm, где будет опсание того, как найти keltirs и .т.д.
! H1 s" I6 }- T. c# f" m* P* R. A0 I$ f" t( ?$ \
/ z. u( Q, ~' G* WПри состоянии STARTED будет зарегистрирован дроп «fangs» при убийстве keltirs. Игрок может вернуться к стартовому NCP и спросить о квесте – метод onEvent будет вызван снова. Если у игрока не хватает необходимого количества предметов, то метод check() не переведет квест в следующее состояние и Started.htm будет показана снова. Но если игрок собрал необходимее количество предметов (в данном случае 4 клыка), то метод check() вызовет метод completed() который переведет квест в новое состояние COMPLETED, заберет все клыки, даст карту мира, т.к. это награда за квест, покажет Completed.htm и завершит квест.
; M1 r* D1 |9 q# A' `$ ^' n$ e5 Q4 _; G0 @6 ] o
( x/ u9 H2 K/ m6 F; L$ {Теперь давайте сделаем наш квест более похожим на то, что он должен из себя представлять.
, ~ x. m4 U9 U# K& t. L) FПрежде всего у нас есть 3 метода для объявления их в Яве – onTalk, onKill и onEvent. Если методы onTalk и onKill не объявлены, то за них все будет делать метод onEvent, т.е. определять квестовых монстров и вызывать диалоги NCP. Есть примечание, методы onTalk и onKill будут вызывать только диалоги с NCP в зависимости от текущего состояния квеста. Метод onKill будет вызываться только тогда, когда мы убиваем квестового монстра.
( W# r( Y, \0 S5 I& ?: M
$ w: X+ n J9 k3 u; Z0 [3 X7 b/ E, P1 ]( H/ f# t
Давайте рассмотрим как вызывается метод onKill при убийстве keltir в состоянии квеста STARTED:
1 `1 Y5 o) b" P- STARTED.addKillId(KELTIR_NPC_ID)
Скопировать код и метод onKill в классе Quest:
; ~/ X: V3 H8 n7 j' A% @' x5 Z8 t) Q7 ?, s: R- ^$ E) ?8 [' D3 \
- class Quest (JQuest):
' @0 ]! e4 `1 z! C+ D - ...
/ ~0 E$ ]7 f8 T" I: I9 U6 V - def onKill (self,npcId,st):
5 V( K# r0 a& ~1 A2 d - if npcId == KELTIR_NPC_ID:1 e+ I K( G8 \* ^
- n = getCount(st)
0 g; A9 |5 `" L# Y( c - if n == 0:
9 a2 J0 @8 z$ M( ~5 g8 a+ @: q4 m* H - return "Chat0.htm"
/ g7 A' S1 i( n. } - elif n == 1:
; \# `3 ~) f% W4 f - return "Chat1.htm"
) n9 W B8 X) B - elif n >= 4:
" [* ]6 E4 i' j1 w0 h( u- W - return "Chat4.htm"
. N: _- `6 v/ H4 E5 d - return "Collected "+str(n)+" of 4 fangs"5 i& M; B7 Y! x T5 |$ `2 F$ z
- return
Скопировать код Метод onKill (а так же метод onTalk) имеет следующие параметры:$ j) S) c: y. g8 j, ~7 J
* t8 d+ M, C% c
' p8 y e/ [* J9 i( o* o7 O: ?• self – квест8 i2 ~& J* H) b
• npcId – ID NCP, которого мы должны убивать (если это метод onTalk, то ID того NCP, с которым мы должны поговорить).
7 U; A: R, a" L3 { }• st – текущее состояние игрока.! d+ @& V$ ?! c# b$ u/ v
' p7 e; i0 Y+ N. @' ^
, U6 m& y7 @; {В этом методе мы проверяем и отмечаем, является ли убитый NCP keltir’ом. В основном эта проверка не нужна, т.к. у нас только KELTIR_NPC_ID.
) G6 R0 _3 u n+ [; i
. M+ g; q0 h Q, s8 v* w* X6 x4 m4 ?* U$ N* i3 Y
Затем проверяем количество предметов (в данном случае количество клыков), и если их вообще нет, то возвращаем строку "Chat0.htm", если только один предмет, то возвращаем строку "Chat1.htm", если же предметов 4 или больше, то "Chat4.htm". Если строка возвращена из методов onEvent, onKill или onTalk, то сервер покажет соответствующие htm. В Chat0.htm может иметь следующий текст: «Вы не имеете ни одного клыка, возвращайтесь позже, когда соберете 4 штуки и бла, бла, бла…», в Chat1.htm может быть следующий текст: «У Вас всего 1 клык, по этому соберите еще…». В Chat4.htm – «Вы собрали необходимое количество предметов, возвращайтесь к вашему тренеру, что бы завершить квест…»+ o) u/ G+ c8 j7 }
7 } i7 W3 Q2 q% o1 i! d
5 _0 ^7 A# h: s' y. a: A& \Примечание: если в строка return начинается с "<html>", то будет показана страничка html с текстом, который стоит далее. Так вместо:
1 ]8 h# O6 A- M3 d6 f2 kreturn "Chat4.htm"
) I8 y3 t2 r6 W7 ~; h& g5 `# ^
1 S8 W% ~+ M7 b! m5 |1 @+ T4 I
% W, r. V- ~* W1 F! D6 \! W2 iможно поставить:6 n# ~* J6 i5 n& [
- return "<html><body>Return to your trainer to complete the quest</body></html>"
Скопировать код Так же если строка заканчивается без .htm или в начале нет <html>, то текст будет выведен, как системное сообщение в окне чата. В нашем случае мы сделаем так, что бы при каждом убийстве keltik выводилось системное сообщение: «Собрано N из 4-х клыков»./ j2 `+ E7 P) i2 t% X) C$ x
, ?: y" E* a+ R: j. U9 {# p
4 j% m' N4 f: f* }8 \7 T- p! GНаш код для onKill имеет один недостаток. Он будет постоянно показывать Chat0.htm, Chat1.htm и Chat4.htm, нам же необходимо, что бы Chat0.htm и Chat1.htm показывались только один раз. Как нам это сделать? С помощью переменных.
( ?0 e+ m( L' i6 I% i# y. ]$ I/ T, s0 x) F
. r4 A* v" }- K" c2 u9 Z. ZВ каждом квесте строки могут храниться с помощью переменных. Эти переменные сохраняются в Вашей БД. В каждом методе мы можем назначить, прочитать и удалить переменные. Давайте изменим метод onKill, так что бы каждый диалог вызывался только один раз.$ @0 V @3 k; T
- def onKill (self,npcId,st):
& P9 Y, ^! G4 l- m - if npcId == KELTIR_NPC_ID:* P4 l+ J" l6 f6 m, p9 ?8 e8 {
- n = getCount(st)6 W7 A% D5 D5 h
- if n == 0:
- b8 f- v7 I6 J+ Y, C0 ? - if st.get('chat0') == None :
& S( n( {6 \0 Z1 @ - st.set("chat0", "true")$ F2 U, m- i, u+ R. ^3 E8 ?
- return "Chat0.htm"
) _1 E* t& _; I3 \ - elif n == 1:* V# O, Q5 V" N' D4 S; n
- if st.get('chat1') == None :
( m! Y6 _8 B% u9 T" ~ - st.set("chat1", "true")
+ h# X1 ~# o- h9 C; ` - return "Chat1.htm"
2 k" {( |6 ^0 V& U - elif n >= 4:6 Z! R0 ?6 t: R$ X, n7 b& n+ ?% q+ X
- return "Chat4.htm"4 C6 |- u7 b; Y2 Y
- return "Collected "+str(n)+" of 4 fangs"$ X6 \% l8 ~/ u, v
- return
Скопировать код Если у игрока нет клыков (n=0), то мы получаем занчение переменной 'chat0'. Когда метод onKill вызван в первый раз, то пока ни каких переменных не имеется и python возвращает значение None. В этом случае объявляется переменная и показывается диалог Chat0.htm. Когда мы убиваем keltir, но не получаем с него клык, функция st.get('chat0') возвращает строку true, а не None. И во второй раз окно с Chat0.htm не появится, но в окне чата появится строчка «Collected 0 of 4 fangs». По тому же принципу сделано и с Chat1.htm.
; X' M) _% A) }0 V4 _
3 k6 h- G( i1 @8 y! y# Z( K$ z5 ^+ N% y. g* ^% k& ? y4 c$ t3 f8 n, `
Вот конечный рабочий вариант квеста:
# ] i2 a" R' g( v8 Y$ A2 G- import sys
$ @. K3 W* i7 t$ T7 ~ - from net.sf.l2j.gameserver.model.quest import State
9 x' e" d' y# \* Y6 g. I - from net.sf.l2j.gameserver.model.quest import QuestState4 [. F) h) o4 x
- from net.sf.l2j.gameserver.model.quest.jython import QuestJython as JQuest; g* h% L; d# S$ [2 I" n
- 7 K3 s, J- H' U" a6 C2 F
- KELTIR_NPC_ID = 12082$ b6 _4 f6 K1 d) N: _! s
- FANGS_ITEM_ID = 1859: G; s3 f# X* Q$ Z8 V+ v0 H
- DROP_RATE = 500000
: E8 P) q% }4 n+ _5 x2 c8 o$ h
D- K5 W% l8 l% M6 G* @# C8 ~- WORLD_MAP_ITEM_ID = 1665
8 `+ e, }, I, ]
2 L! r* X8 ?; X' B' x5 M" X- def getCount(st) :& K2 j. p$ m% _ S9 {
- return st.getQuestItemsCount(FANGS_ITEM_ID). u: G8 `% Q( }
- 9 x; a3 [# y0 I: F
- def completed(st) :
% m v1 x; P; R5 I! D - st.setState(COMPLETED)
( T* {* m5 e) N - st.clearQuestDrops()* L0 O3 c: Y, u: J+ n% o' v
- st.takeItems(FANGS_ITEM_ID,-1)1 C+ | e, x' f% `! _9 F
- st.giveItems(WORLD_MAP_ITEM_ID,1)
. u9 A: K' p3 y! ?0 b7 u# _ - st.exitQuest(False)
Q+ b+ t* F1 e$ Q - return% i) q! y5 ^) S* x6 u- u
. |% O, J* S- G1 N8 g6 @; _- def check(st) :
* |6 k. C+ o; M: R/ v1 ] - if getCount(st) >= 4 :
h! Y, g' ]5 F: Q/ a - completed(st), o8 y( K! M% y1 ~+ @3 A
- return) \& h: y8 m- C; F% g) v
& {# z) |$ [4 E/ p- class Quest (JQuest):7 {+ ]2 R, d6 J1 H$ {4 M
9 F& _) R, f2 g$ H) q+ Z# w- def __init__(self,id,name,descr): JQuest.__init__(self,id,name,descr)
, t& E3 f% t, N, f) f7 d4 C$ g - 7 v$ ~. g; u" F% o4 u7 D1 Y; M% y
- def onEvent (self,event,st):7 W3 p; h2 g" b( T, @- g; G
- id = st.getState()
) v, V/ r, `* O B - if id == CREATED : st.setState(STARTED)
+ S6 a" W6 w6 _' ~8 B Y - elif id == COMPLETED: pass; D5 I9 s: V: |3 B! ^1 f: ?
- elif id == STARTED : check(st)
# \; @: h& ] a5 ]& L) H - return
4 y2 o1 U# y: q; W- M - ! e) {- t. I5 B5 Y7 i1 d
- def onKill (self,npcId,st):
- u( Y7 q3 p1 K2 Q9 b* i5 I - if npcId == KELTIR_NPC_ID:8 K- o% s6 [- G S6 s* k
- n = getCount(st)
! A' F6 i) I* u3 v3 f4 c" H6 F z' f - if n == 0:
& O9 a! h6 ~* X: z - if st.get('chat0') == None :
) @3 \7 Y; z. P - st.set("chat0", "true")1 J) ~4 R) p. c/ z
- return "Chat0.htm"
( Q E% y. B1 I1 p; ?: C) ` - elif n == 1:
, N' G. ^% v9 ~$ R - if st.get('chat1') == None :1 n, [! q2 w' H" h& e9 G7 f8 z
- st.set("chat1", "true")2 P, G4 ]( F' k, I+ R
- return "Chat1.htm"
8 ^7 X8 L- h& i: e& Q4 [0 O2 _ - elif n >= 4:2 y2 b7 k# G) ^3 ^# p* w
- return "Chat4.htm"' Y% P# F" O5 x! J N: D
- return "Collect "+str(n)+" of 4 fangs"! d! S# U0 o" }& t: g& O
- return
$ M7 n- X: ^, O' }8 H - 2 u# v! O" b7 @) i. l- `
- QUEST = Quest(201, "Tutorial", "Tutorial quest")- u3 b+ B7 n& a0 A) y9 Z2 Q8 P
- CREATED = State('Start', QUEST)7 y V. L# a7 A9 y
- STARTED = State('Started', QUEST)
0 C8 Y9 }( \- x: _% g3 _ - COMPLETED = State('Completed', QUEST)6 Y( y& U" k4 g1 |* K! T8 D% |5 o( y
3 a+ Z7 l E, |- QUEST.setInitialState(CREATED)( D4 B, R, ]' n+ i2 |, G5 S
- QUEST.addStartNpc(7056)
/ h: Y" l& e7 v1 N - QUEST.addStartNpc(7012)
9 i7 d5 L0 Y g* t6 | - QUEST.addStartNpc(7009)
6 L! Z0 z1 f. {( P, o - QUEST.addStartNpc(7011)
1 ~- K5 b& K/ ]9 X( J
0 }) F& ]. ?: m( m8 C- STARTED.addQuestDrop(KELTIR_NPC_ID,FANGS_ITEM_ID,DROP_RATE)1 W; x' p, c5 O+ W5 ~6 c
- STARTED.addKillId(KELTIR_NPC_ID): |3 i% [+ r" w, ?* _
- STARTED.addTalkId(7056): X4 }' y( t( x1 }2 u9 g% `" q
- STARTED.addTalkI d(7012)
% ]+ S2 Z, |. N- h1 l9 ?' A - STARTED.addTalkId(7009)2 b: P& w# w$ \8 u) h
- STARTED.addTalkId(7011)
Скопировать код % r. K. X G/ U
' w: v6 l( ?9 a4 K" ] |