Зарегистрируйтесь сейчас чтобы найти еще больше друзей, и получить полноценный доступ ко всем функциям сайта!
Для просмотра Вам необходимо авторизоваться Если Вы еще не зарегистрированы, перейдите по ссылке:Зарегистрироваться
x
Хроники Interlude) l; S3 z6 Y; k8 |
Сборка L2j R0 d+ x# y9 }, \ x. Y0 [+ Z
Обратите внимание: в файле htm стартового NCP обязательно должна быть ссылка на квест:3 w5 i1 Z' ]; q! s( O
- STARTED.addQuestDrop(KELTIR_NPC_ID,FANGS_ITEM_ID,DROP_RATE)
Скопировать код Для этого квеста больше ничего не надо. Все необходимое для корректной работы квеста уже добавили. Вот полный текст квеста:
( p! f/ a4 t8 }8 e2 O/ M' R: f* Y5 ?( i9 I. J
- if getCount(st) >= 4 :3 M; L/ Y; h, z3 X" d7 ~4 U
- completed(st)
$ R' E7 b) Y' n* r) g: f4 A - return' |. h+ v8 }2 C8 @ _" c9 E
; Z; A( {& v8 K( z; ?- class Quest (JQuest):
- p2 C6 ^$ c L( B: {+ h' F - def __init__(self,id,name,descr): JQuest.__init__(self,id,name,descr)* q- z9 X5 i) U+ o! n$ [+ n
- def onEvent (self,event,st):
: m9 h9 h7 I: b* S7 T+ y7 O - id = st.getState()
# h7 I' z% G" T. P0 ?/ b' X! M - if id == CREATED : st.setState(STARTED)
+ h. ]0 o+ ]7 a2 _3 d - elif id == COMPLETED: pass
* E, U" u6 E/ o% O - elif id == STARTED : check(st)7 S4 W$ S" r! D& k+ `$ s" N" s# y
- return
4 H' }" _, J/ m/ K+ d# k2 p - ' w( R0 r3 X$ ?) V
- QUEST = Quest(201,"Tutorial", "Tutorial quest")& a) `% A* e' N0 z
- CREATED = State('Start', QUEST)
, j$ D- y" o2 D6 e - STARTED = State('Started', QUEST)# {* S# X- }' F, H$ b$ m
- COMPLETED = State('Completed', QUEST)
$ f [$ a( I2 q) p2 g0 _ - 8 f; e r; L. Y7 l; P
- QUEST.setInitialState(CREATED)& _. q" T) c+ N. ]2 G& x
- QUEST.addStartNpc(7056)' N; b2 |3 Y {, b6 U' o
- STARTED.addQuestDrop(KELTIR_NPC_ID,FANGS_ITEM_ID,DROP_RATE)
Скопировать код Теперь рассмотрим, как это работает.+ L, F" K' B5 F5 [; {
Игрок подходит к начальному NCP (в данном случае 7056), нажимает на «Quest». Квест будет создан и состояние квеста перейдет к CREATED и игроку будет показана страничка Start.htm с описанием квеста. Тогда метод onEvent, поле открытия странички Start.htm переведет состояние квеста в STARTED и игроку будет показана страничка Started.htm, где будет опсание того, как найти keltirs и .т.д.4 ]& z7 H2 ]5 M' H% F( m, |
; W6 J* {7 W# X/ N# n- i2 e* R3 I' x
При состоянии STARTED будет зарегистрирован дроп «fangs» при убийстве keltirs. Игрок может вернуться к стартовому NCP и спросить о квесте – метод onEvent будет вызван снова. Если у игрока не хватает необходимого количества предметов, то метод check() не переведет квест в следующее состояние и Started.htm будет показана снова. Но если игрок собрал необходимее количество предметов (в данном случае 4 клыка), то метод check() вызовет метод completed() который переведет квест в новое состояние COMPLETED, заберет все клыки, даст карту мира, т.к. это награда за квест, покажет Completed.htm и завершит квест.1 N4 K( B* h9 Q: X- L; f
5 w1 V- z# P% n
; i1 E% ^9 e3 V0 W3 s
Теперь давайте сделаем наш квест более похожим на то, что он должен из себя представлять.
/ h" v3 y x4 Z. u1 o j. JПрежде всего у нас есть 3 метода для объявления их в Яве – onTalk, onKill и onEvent. Если методы onTalk и onKill не объявлены, то за них все будет делать метод onEvent, т.е. определять квестовых монстров и вызывать диалоги NCP. Есть примечание, методы onTalk и onKill будут вызывать только диалоги с NCP в зависимости от текущего состояния квеста. Метод onKill будет вызываться только тогда, когда мы убиваем квестового монстра.. I6 X- B" Z3 r& j- X' A
P8 R+ W) y0 z2 G/ E# j
+ K5 [4 ~- } D! T: F4 O9 n& w$ ` ]Давайте рассмотрим как вызывается метод onKill при убийстве keltir в состоянии квеста STARTED:
: U& \0 ^$ d$ L4 L8 H# f- STARTED.addKillId(KELTIR_NPC_ID)
Скопировать код и метод onKill в классе Quest:
7 n/ p, A: j0 c0 P- q7 B4 E( i& j6 T1 @1 t
- class Quest (JQuest):+ ~; R& s, R7 h2 p1 D7 D
- ...& N6 x) ~4 Z( q9 P9 ]
- def onKill (self,npcId,st):1 s' h: d* C. I" P; h
- if npcId == KELTIR_NPC_ID:# `) M1 E2 ~# l" ]8 ~3 g( Y: J
- n = getCount(st)' w: S, m7 K& S% u6 M
- if n == 0:" M$ I& v! t6 L& N
- return "Chat0.htm"4 X; T7 x: E4 O8 O7 `
- elif n == 1:+ M0 ?/ v" }/ M3 f }5 i+ ^
- return "Chat1.htm"
9 f) ^6 G' c# Q; j2 U9 h8 o - elif n >= 4:' q, `3 Q# i& K: E0 v
- return "Chat4.htm"% t' Y8 f& {% g* W0 }- z
- return "Collected "+str(n)+" of 4 fangs"8 b* I& j& e8 ]3 Y
- return
Скопировать код Метод onKill (а так же метод onTalk) имеет следующие параметры:" S! X- G# x3 N+ J9 K& f
3 T7 F Y$ S5 v" f
' |" T0 f- Q" Q: E5 D/ G• self – квест0 ^6 R- Z1 Y9 Q* H
• npcId – ID NCP, которого мы должны убивать (если это метод onTalk, то ID того NCP, с которым мы должны поговорить).
2 G* [% v' @0 b5 I! F• st – текущее состояние игрока.
) _: g4 q2 }4 l* o
* v3 `- N3 E4 `& ?, ^6 z, _* |
6 M9 r& d/ V( j1 q4 }& c& u JВ этом методе мы проверяем и отмечаем, является ли убитый NCP keltir’ом. В основном эта проверка не нужна, т.к. у нас только KELTIR_NPC_ID.
6 T3 {3 \% U5 W$ _5 [: U3 X1 \3 ~2 y
' J& ]: F3 I7 m* ^, D6 R$ U' w
" c( w# h( [% S6 tЗатем проверяем количество предметов (в данном случае количество клыков), и если их вообще нет, то возвращаем строку "Chat0.htm", если только один предмет, то возвращаем строку "Chat1.htm", если же предметов 4 или больше, то "Chat4.htm". Если строка возвращена из методов onEvent, onKill или onTalk, то сервер покажет соответствующие htm. В Chat0.htm может иметь следующий текст: «Вы не имеете ни одного клыка, возвращайтесь позже, когда соберете 4 штуки и бла, бла, бла…», в Chat1.htm может быть следующий текст: «У Вас всего 1 клык, по этому соберите еще…». В Chat4.htm – «Вы собрали необходимое количество предметов, возвращайтесь к вашему тренеру, что бы завершить квест…»
: m7 X. a7 H7 R! I3 r, W1 \- M6 ~8 h1 L
* V1 |1 y% L4 w% f" MПримечание: если в строка return начинается с "<html>", то будет показана страничка html с текстом, который стоит далее. Так вместо:5 n( w6 y5 U$ F3 }; M2 d- R. x% z
return "Chat4.htm", o. R! c# j: K6 u" G6 ]( H2 g! Q
4 x8 o: \! [0 k! H2 v) R! T) W) ]8 ~
можно поставить:
* {* o! J T- O9 V# y% l% }- return "<html><body>Return to your trainer to complete the quest</body></html>"
Скопировать код Так же если строка заканчивается без .htm или в начале нет <html>, то текст будет выведен, как системное сообщение в окне чата. В нашем случае мы сделаем так, что бы при каждом убийстве keltik выводилось системное сообщение: «Собрано N из 4-х клыков».3 M# T2 ]. v& R
* b. Q. ~& T& T! l$ k1 n0 V: l2 O
6 S9 \& n5 d5 E i! nНаш код для onKill имеет один недостаток. Он будет постоянно показывать Chat0.htm, Chat1.htm и Chat4.htm, нам же необходимо, что бы Chat0.htm и Chat1.htm показывались только один раз. Как нам это сделать? С помощью переменных.
& J' o$ {6 A6 n# v2 f" X
, j: m, \0 c$ Y& z, n& a8 t# I& L' p8 o; r3 q
В каждом квесте строки могут храниться с помощью переменных. Эти переменные сохраняются в Вашей БД. В каждом методе мы можем назначить, прочитать и удалить переменные. Давайте изменим метод onKill, так что бы каждый диалог вызывался только один раз.
+ p" y0 l9 X4 C! g& q- def onKill (self,npcId,st):
$ ^0 c0 b9 ^4 E - if npcId == KELTIR_NPC_ID:/ x% M/ W! x! S
- n = getCount(st)1 S: t% U8 r2 v- e. n: @
- if n == 0:+ R4 B; e9 L( Q5 y5 ]; U5 E
- if st.get('chat0') == None :
$ r1 y$ k# s6 B - st.set("chat0", "true")
6 e& g1 Q: I2 h - return "Chat0.htm" G g2 \. g+ d7 k4 m1 w
- elif n == 1:
; s# C9 n# n7 s - if st.get('chat1') == None :0 x$ b. ?* i2 j. A
- st.set("chat1", "true")6 ]8 E' n+ p0 t+ t
- return "Chat1.htm"2 S; B$ ^7 [! N% C0 L9 l
- elif n >= 4:: U1 ?$ r% ?" Y, O8 F+ J
- return "Chat4.htm", B1 {/ M. w- `; k" F! d/ x5 Z
- return "Collected "+str(n)+" of 4 fangs"( `- c" p6 u# l- `$ s
- return
Скопировать код Если у игрока нет клыков (n=0), то мы получаем занчение переменной 'chat0'. Когда метод onKill вызван в первый раз, то пока ни каких переменных не имеется и python возвращает значение None. В этом случае объявляется переменная и показывается диалог Chat0.htm. Когда мы убиваем keltir, но не получаем с него клык, функция st.get('chat0') возвращает строку true, а не None. И во второй раз окно с Chat0.htm не появится, но в окне чата появится строчка «Collected 0 of 4 fangs». По тому же принципу сделано и с Chat1.htm.4 d) N" H. F' [! e0 y. U1 u; N9 k5 E! E
+ h% F8 V2 ]' ?) `
3 d' r& M: F( R* {5 Z9 T" R- ^' rВот конечный рабочий вариант квеста:$ e, _6 ]8 s3 x
- import sys
( I3 o+ Q P _: p' F# G! a) U; e - from net.sf.l2j.gameserver.model.quest import State% ?8 I' t( ^2 o8 d- ~+ N
- from net.sf.l2j.gameserver.model.quest import QuestState
8 `+ A5 i4 d% E' Z+ D# y1 \ - from net.sf.l2j.gameserver.model.quest.jython import QuestJython as JQuest
4 I" T& }8 ?5 r
* D; U G( ~/ F2 v( `+ r E- KELTIR_NPC_ID = 12082
, j7 \7 h% H# o - FANGS_ITEM_ID = 1859% m5 f! |1 C- d* N( m
- DROP_RATE = 5000007 a; w5 F! @+ b9 a& }# c- K" k
- " W. o8 ^5 e6 f
- WORLD_MAP_ITEM_ID = 1665
/ o* ?5 \9 _2 Q' x( ]
9 {; Y) p u' U9 ]/ N8 J$ Q# B- K- def getCount(st) :
# V0 t. K% u" a$ G. } - return st.getQuestItemsCount(FANGS_ITEM_ID)
, N n/ l2 n8 m8 V9 O. y7 p
+ r, r+ E4 [ @7 @- def completed(st) :
6 W8 C8 p# S9 U( C0 a/ J C6 O# o/ ` - st.setState(COMPLETED)
% D, X3 Q/ p! w( d - st.clearQuestDrops()
0 I- |7 R" {* P" g- I7 Z# x& \ - st.takeItems(FANGS_ITEM_ID,-1)3 m7 u& b6 Q- k) L
- st.giveItems(WORLD_MAP_ITEM_ID,1)6 J6 N7 W: H: h3 Z! i% g# \( z
- st.exitQuest(False)
- d1 V% f8 |! v( i9 j: ]* F - return% A0 s4 S) ?2 @6 v+ W# j
* Z+ D4 |! x) q, ] Y- def check(st) :
" B: }' b$ l5 e2 C \3 t - if getCount(st) >= 4 :+ P" Y/ w5 d/ B9 t) b
- completed(st): J4 h4 U$ M: A( u! G" B) [
- return7 _1 t0 _6 Z' v; Q
- . z1 z2 C& l) u4 m! d
- class Quest (JQuest):% `9 _) z8 B$ b2 a
- / j. d' B8 @- K5 p4 |' \
- def __init__(self,id,name,descr): JQuest.__init__(self,id,name,descr)
+ l: x2 r6 {; a$ k( q - 4 T' G+ K# ^0 I# `* \8 ?0 i
- def onEvent (self,event,st):
5 `8 F8 f4 f% n/ Y - id = st.getState()
% Y2 i0 X7 l# {1 P, T - if id == CREATED : st.setState(STARTED): d G( \5 P2 P. Z, F
- elif id == COMPLETED: pass
9 F" t& m) K+ E* x' d - elif id == STARTED : check(st)
0 C* W" L# d1 }& `- A* u - return
5 i2 |: T/ B" o; u' x
9 Z1 S3 ?+ h n5 ~: Q( m4 K- def onKill (self,npcId,st):
' V$ x0 I/ _9 P' i - if npcId == KELTIR_NPC_ID:
, a) O3 X# N9 x* F7 U, N* s - n = getCount(st)
7 G- p7 j9 a" o$ m. k - if n == 0:
. V* C ]. } }/ }: V/ |1 t) y - if st.get('chat0') == None :
3 O$ L! G9 d* G - st.set("chat0", "true")
1 F- g r% E7 h9 e/ ? - return "Chat0.htm"5 S' u! B3 D Z q$ K0 z' R
- elif n == 1:
: V- w% q) P- O# U- P - if st.get('chat1') == None :7 R4 s3 C; p3 R) w/ |8 @
- st.set("chat1", "true")% x1 n( t) M0 C7 z' Z4 e# W' q
- return "Chat1.htm"% P! A% d' b. _0 W+ H# ~* N$ L9 w
- elif n >= 4:
2 ?3 s+ Q+ e3 z8 a4 ? - return "Chat4.htm"/ N( ]6 M) t- J \! _3 ~
- return "Collect "+str(n)+" of 4 fangs"( z v _3 \6 [& S
- return
9 }/ ]8 i$ z8 B# `- F
* ~9 S# B; I' Y& p/ F7 T8 X- QUEST = Quest(201, "Tutorial", "Tutorial quest")9 }5 r# \( }% j% {
- CREATED = State('Start', QUEST)
! O2 I7 K o& Y1 u4 _' f5 `! u - STARTED = State('Started', QUEST)9 M; G2 p( |5 H0 P! i
- COMPLETED = State('Completed', QUEST)
& y4 U5 i) v- {+ M% o$ x- f
( I0 y e8 t6 s. o6 t8 t- QUEST.setInitialState(CREATED)
3 i$ a# l2 n2 | - QUEST.addStartNpc(7056)
# v2 U1 o4 ]5 @7 ] - QUEST.addStartNpc(7012)
+ j& \, `, a8 r1 U. A - QUEST.addStartNpc(7009)' x: ~6 V' r/ f! I1 G3 T
- QUEST.addStartNpc(7011)
% e" i% [4 G+ F0 a7 D& e, P" W - ) D4 l* C! _0 n; v. n" U
- STARTED.addQuestDrop(KELTIR_NPC_ID,FANGS_ITEM_ID,DROP_RATE)7 ^! g2 F* w4 ^/ y
- STARTED.addKillId(KELTIR_NPC_ID)9 ]- w7 d, D* T1 O! p5 Z
- STARTED.addTalkId(7056)
: `, \) I& w( H. H7 Z4 m - STARTED.addTalkI d(7012), w0 K4 z, v' t+ |
- STARTED.addTalkId(7009)
+ C0 r1 s5 V, b. z$ U; S) Z$ y# Q: X - STARTED.addTalkId(7011)
Скопировать код
- q, G2 F' Z, ~' K; u$ U$ U/ N- M
|