Зарегистрируйтесь сейчас чтобы найти еще больше друзей, и получить полноценный доступ ко всем функциям сайта!
Для просмотра Вам необходимо авторизоваться Если Вы еще не зарегистрированы, перейдите по ссылке:Зарегистрироваться
x
Хроники Interlude, U, U3 @: H' g/ o
Сборка L2j* j* a I" u3 B9 f9 _, i* E/ ?
Обратите внимание: в файле htm стартового NCP обязательно должна быть ссылка на квест:2 |* o. t2 V- w
- STARTED.addQuestDrop(KELTIR_NPC_ID,FANGS_ITEM_ID,DROP_RATE)
Скопировать код Для этого квеста больше ничего не надо. Все необходимое для корректной работы квеста уже добавили. Вот полный текст квеста:
$ V! n6 z( V$ j2 J% [, \& G& e" |' }
' s# j% T5 p7 R6 U' y6 p4 v F- z! S- if getCount(st) >= 4 :7 M3 X* {' R( b- S: D5 Z: {
- completed(st)
6 o4 {3 ^2 q& F5 F2 ?' F, I+ @. C - return
, W) l1 o( k& u9 f - ( L" u" Q; K; w9 U) g8 G+ ?6 z# F
- class Quest (JQuest):
0 {# \: V; U2 i% C6 Q- ?4 a9 @$ R - def __init__(self,id,name,descr): JQuest.__init__(self,id,name,descr). @, N |2 S; `/ [0 |; |# W
- def onEvent (self,event,st):/ M5 F, e* N" W: V+ M. P
- id = st.getState(). v* H, o4 L) L. d: x
- if id == CREATED : st.setState(STARTED)
/ V# _9 V+ ?6 J7 w6 T - elif id == COMPLETED: pass
* y* }5 b. ~" D) f5 j1 D - elif id == STARTED : check(st)+ q& Q6 P( i% B2 P# m
- return1 E9 v6 U% p: w6 d$ M
t" }8 I. n5 }* n* X" n6 B5 {- QUEST = Quest(201,"Tutorial", "Tutorial quest")
! E% l$ R5 R1 W2 c* V0 T A - CREATED = State('Start', QUEST)
2 v) J& P# N' ` - STARTED = State('Started', QUEST)
3 F- T0 u, o0 N - COMPLETED = State('Completed', QUEST)9 k; }6 K' e' L: S' N9 w
% p/ e4 h# n+ X; m- QUEST.setInitialState(CREATED)6 w5 }9 P! w) }4 u
- QUEST.addStartNpc(7056)
8 `: I T/ a0 D6 G - STARTED.addQuestDrop(KELTIR_NPC_ID,FANGS_ITEM_ID,DROP_RATE)
Скопировать код Теперь рассмотрим, как это работает.
+ D t) G- o! x$ Z- o iИгрок подходит к начальному NCP (в данном случае 7056), нажимает на «Quest». Квест будет создан и состояние квеста перейдет к CREATED и игроку будет показана страничка Start.htm с описанием квеста. Тогда метод onEvent, поле открытия странички Start.htm переведет состояние квеста в STARTED и игроку будет показана страничка Started.htm, где будет опсание того, как найти keltirs и .т.д.4 @7 a) ~; D$ d. _
$ T9 w* p8 j( c
$ q0 R. k$ R, c) ]' f9 h
При состоянии STARTED будет зарегистрирован дроп «fangs» при убийстве keltirs. Игрок может вернуться к стартовому NCP и спросить о квесте – метод onEvent будет вызван снова. Если у игрока не хватает необходимого количества предметов, то метод check() не переведет квест в следующее состояние и Started.htm будет показана снова. Но если игрок собрал необходимее количество предметов (в данном случае 4 клыка), то метод check() вызовет метод completed() который переведет квест в новое состояние COMPLETED, заберет все клыки, даст карту мира, т.к. это награда за квест, покажет Completed.htm и завершит квест.
* J% I0 V" J9 F5 c/ y2 _; U! `
8 v, d: d) o- X
4 |: g4 c( \* y3 SТеперь давайте сделаем наш квест более похожим на то, что он должен из себя представлять.
! L' W9 f, H: @% E3 uПрежде всего у нас есть 3 метода для объявления их в Яве – onTalk, onKill и onEvent. Если методы onTalk и onKill не объявлены, то за них все будет делать метод onEvent, т.е. определять квестовых монстров и вызывать диалоги NCP. Есть примечание, методы onTalk и onKill будут вызывать только диалоги с NCP в зависимости от текущего состояния квеста. Метод onKill будет вызываться только тогда, когда мы убиваем квестового монстра.. K- }% ` p6 j0 p7 S* T
, X$ m9 D# F, m4 T- [% e- P
$ F# J4 x5 ~$ I; j( B2 i
Давайте рассмотрим как вызывается метод onKill при убийстве keltir в состоянии квеста STARTED:
* k% U" v0 d r' T' M8 S2 p- STARTED.addKillId(KELTIR_NPC_ID)
Скопировать код и метод onKill в классе Quest:' [- X6 A7 y" i
5 B1 k. H$ M" a6 ~) d
- class Quest (JQuest):
* {% j. h: c" i - ...% P8 b! r( [1 {1 Z& B y& o
- def onKill (self,npcId,st):" l, U; y- P7 z M1 M0 S! j* ~
- if npcId == KELTIR_NPC_ID:
. \; z3 G: ^; ~% e, K1 T - n = getCount(st)8 ]0 b5 b0 o( r$ t8 J+ R% Q- \8 ^
- if n == 0:' x, v, E2 S* e8 S8 z* S
- return "Chat0.htm"
+ Z4 h& _# y4 h9 C6 V" Y# n - elif n == 1:
6 x" R- F I( j# s6 N - return "Chat1.htm") a1 l* S9 a3 @% Y& ]* }* F$ b
- elif n >= 4:
; @6 D7 v, f L0 p( V K - return "Chat4.htm"
/ |% d$ y' Z- d - return "Collected "+str(n)+" of 4 fangs"
( J- e9 m9 L+ W$ s6 t r( i - return
Скопировать код Метод onKill (а так же метод onTalk) имеет следующие параметры:# R9 E# @$ ~4 a$ ~+ y( o
2 l m2 l8 C& ~7 b* H) [
+ J! B( `. a- O3 h: J, v2 x
• self – квест6 s; p" n9 q4 h8 x1 \; Z+ K
• npcId – ID NCP, которого мы должны убивать (если это метод onTalk, то ID того NCP, с которым мы должны поговорить).* w9 V3 d' ^& F% @
• st – текущее состояние игрока.
) g0 L+ B1 }3 A1 @0 C
/ H. T5 G! K9 @; k; E% A m) y3 |; D& h6 u; p) g
В этом методе мы проверяем и отмечаем, является ли убитый NCP keltir’ом. В основном эта проверка не нужна, т.к. у нас только KELTIR_NPC_ID.1 l1 H6 K0 Z& D& Q9 p$ y
4 Z9 w% g" c+ H! ^3 A# Z g
6 B- D+ k1 ~! F9 u( d* ?Затем проверяем количество предметов (в данном случае количество клыков), и если их вообще нет, то возвращаем строку "Chat0.htm", если только один предмет, то возвращаем строку "Chat1.htm", если же предметов 4 или больше, то "Chat4.htm". Если строка возвращена из методов onEvent, onKill или onTalk, то сервер покажет соответствующие htm. В Chat0.htm может иметь следующий текст: «Вы не имеете ни одного клыка, возвращайтесь позже, когда соберете 4 штуки и бла, бла, бла…», в Chat1.htm может быть следующий текст: «У Вас всего 1 клык, по этому соберите еще…». В Chat4.htm – «Вы собрали необходимое количество предметов, возвращайтесь к вашему тренеру, что бы завершить квест…»
! l0 _6 d9 `$ N* j, L% F1 |7 _
% H3 o' w) e: ?Примечание: если в строка return начинается с "<html>", то будет показана страничка html с текстом, который стоит далее. Так вместо:( K2 z0 y' ^* j5 S
return "Chat4.htm"% G8 B0 z' ~% W( `
Y& z# T9 @* Z0 ]* D) M4 M. J
+ l* d' w3 ]. M2 b; a$ [. u3 mможно поставить:
# }7 Z* [3 M/ p' L' ~9 U- return "<html><body>Return to your trainer to complete the quest</body></html>"
Скопировать код Так же если строка заканчивается без .htm или в начале нет <html>, то текст будет выведен, как системное сообщение в окне чата. В нашем случае мы сделаем так, что бы при каждом убийстве keltik выводилось системное сообщение: «Собрано N из 4-х клыков».
: W$ ~ j: I% m( L# |8 f B
9 {4 u8 \7 k/ h
2 G' m. C" x0 m! m! zНаш код для onKill имеет один недостаток. Он будет постоянно показывать Chat0.htm, Chat1.htm и Chat4.htm, нам же необходимо, что бы Chat0.htm и Chat1.htm показывались только один раз. Как нам это сделать? С помощью переменных.
# }- B1 o, b$ k' n+ `+ ^- E1 ]5 d+ z ~% T- P) \# i- q6 x/ p
% Q& l( v1 i& C- O4 xВ каждом квесте строки могут храниться с помощью переменных. Эти переменные сохраняются в Вашей БД. В каждом методе мы можем назначить, прочитать и удалить переменные. Давайте изменим метод onKill, так что бы каждый диалог вызывался только один раз.
5 r( O; m% I3 K: Y) B: f- def onKill (self,npcId,st):
! e3 v8 v# o6 U+ A: ^3 b* F - if npcId == KELTIR_NPC_ID:
3 R, E8 M ~$ Y- K# R - n = getCount(st)% S2 A8 e3 G: {) }. w
- if n == 0:
$ D j R$ o. ?# q L6 v - if st.get('chat0') == None :
8 G( c9 f$ a n8 [. y& S3 m2 V" U2 z - st.set("chat0", "true")
/ U. x0 B; p( T: x; k& p# D - return "Chat0.htm"
1 l( s% g0 Y- S7 d+ Y! I. I - elif n == 1:
$ {0 H6 y& b$ y+ ?' V! F" p - if st.get('chat1') == None :
% L& d3 z1 m% n; D( T: p7 ] C) T - st.set("chat1", "true")2 X: n: Y, G% }0 Q) p3 f0 @
- return "Chat1.htm"
( ~" U% h5 C W6 E2 V - elif n >= 4:
1 P. L9 g0 s" P7 p3 X f - return "Chat4.htm"( E) c Z5 m* O3 J: x6 e h
- return "Collected "+str(n)+" of 4 fangs"
4 p* }0 O* E) G - return
Скопировать код Если у игрока нет клыков (n=0), то мы получаем занчение переменной 'chat0'. Когда метод onKill вызван в первый раз, то пока ни каких переменных не имеется и python возвращает значение None. В этом случае объявляется переменная и показывается диалог Chat0.htm. Когда мы убиваем keltir, но не получаем с него клык, функция st.get('chat0') возвращает строку true, а не None. И во второй раз окно с Chat0.htm не появится, но в окне чата появится строчка «Collected 0 of 4 fangs». По тому же принципу сделано и с Chat1.htm.% I- Q* p) E2 l+ b2 R/ M
- |+ Q" }# O0 N s/ J; R+ V
' E; n' h* d6 F# r/ AВот конечный рабочий вариант квеста:
* L% z; z) @; v7 O- import sys
2 |0 G4 X4 W2 M2 T0 z - from net.sf.l2j.gameserver.model.quest import State
8 k4 P5 _# t0 l - from net.sf.l2j.gameserver.model.quest import QuestState
W# {7 n/ t+ H# l# L - from net.sf.l2j.gameserver.model.quest.jython import QuestJython as JQuest& M& Q8 m; N1 ~6 J, ]
: _1 G" h3 {2 m, k' T/ p, Y- KELTIR_NPC_ID = 12082
2 m+ E8 M; x7 A6 B, b, d - FANGS_ITEM_ID = 1859$ J$ h; [/ ?3 }% l0 N. ~5 W- W2 ]
- DROP_RATE = 500000% D5 j, j7 _- T. |
) V c% o6 T: f( Y0 s) w- WORLD_MAP_ITEM_ID = 1665
4 S8 c2 E/ B! z1 {$ M
4 x+ }) o9 K. e% C- def getCount(st) :
7 K: h' L0 C6 R4 |- \ - return st.getQuestItemsCount(FANGS_ITEM_ID), @# q1 D; T9 ~
- % ~2 `( Z( i' g5 V P# n$ j. x
- def completed(st) :
9 d c0 E$ q- t- B# [: b& R2 p: i - st.setState(COMPLETED)8 T8 {9 V& J l0 [# V; r, g
- st.clearQuestDrops()2 d" L' G+ `. C3 y: o
- st.takeItems(FANGS_ITEM_ID,-1)
# q- i: E' L) r. d8 |7 N0 } - st.giveItems(WORLD_MAP_ITEM_ID,1)
\$ `2 U2 o* h' [* Y0 L+ }* J0 v - st.exitQuest(False)9 S+ p& Q# t9 m* V$ B8 Y4 f
- return, [' i% N) J8 ]: k+ T8 @) r A
- 9 P2 i" J0 j4 ^! P0 K7 O! e" ~* X
- def check(st) :
* t6 z; f1 s4 {5 Y7 K - if getCount(st) >= 4 :4 t+ @; X/ ]9 }. x
- completed(st)
! t4 f" f' r1 v) Q: x7 n - return/ e, `) A% F% V# n- [7 H; k* k
- # d; | W% X9 Z, m4 v
- class Quest (JQuest):
0 g7 Q/ P: A2 _" o( b& e3 T - # `7 c U8 ?! D
- def __init__(self,id,name,descr): JQuest.__init__(self,id,name,descr)1 ?5 t- h% s2 k
- ' P" D ?* r' }% H7 C
- def onEvent (self,event,st):
4 _) O+ J$ O5 r6 ?6 q3 v! h - id = st.getState()5 h/ g: T* t5 q3 Q5 x8 ^
- if id == CREATED : st.setState(STARTED)) O* `1 Z4 y7 \2 W+ M. t$ x
- elif id == COMPLETED: pass
2 \ [: b. }# h" e' W: j - elif id == STARTED : check(st)/ I5 |5 c0 `; ~1 k1 M
- return
& e; l4 ~) Q3 L. h. h a: e/ ~ - 9 G% G/ g7 S' F2 K) Q! d7 v; n
- def onKill (self,npcId,st):# O2 S2 N+ I9 x1 }4 L
- if npcId == KELTIR_NPC_ID:9 d9 E* n. s5 f4 h5 P, r" E( q
- n = getCount(st)2 T9 a6 E* t; U; Q8 F$ p
- if n == 0:0 {6 `7 _' l3 U" O% m1 D, I6 r
- if st.get('chat0') == None :- S5 {" ]* \& D1 ?, a4 a9 A
- st.set("chat0", "true")
v0 n U1 z* k; {; H5 {2 s - return "Chat0.htm"
1 n; F9 _. p/ H* ]0 ^* x - elif n == 1: Q0 r7 I) l* f. f0 A* [ S) Z2 q
- if st.get('chat1') == None :7 H+ W1 \" C, K# O( _! |
- st.set("chat1", "true")- C' p; i" d) h# R- j
- return "Chat1.htm"1 w$ z6 y+ A- `
- elif n >= 4:
) r* q0 M, Q2 u9 I* t - return "Chat4.htm"6 Q5 x* M, ?3 a; m$ }; l
- return "Collect "+str(n)+" of 4 fangs"
3 B, i g4 T" G h1 D' S - return5 I: n7 U" e# z6 B+ J
- ) `: g5 o6 w# n+ |. a' J3 e" W+ @
- QUEST = Quest(201, "Tutorial", "Tutorial quest")2 l/ [1 d1 z% s" H. r, E: v* B
- CREATED = State('Start', QUEST)
0 D( c$ e, [+ v G$ m! r ^ - STARTED = State('Started', QUEST)
8 P4 e& i* @, J d6 n1 S" t - COMPLETED = State('Completed', QUEST) M2 H1 t2 [+ \, p4 L
2 ~4 e3 F4 E6 Q' ?- QUEST.setInitialState(CREATED)7 S& ^5 S) t& _
- QUEST.addStartNpc(7056)
6 X# `. }+ l, T, d' K* J - QUEST.addStartNpc(7012)( X/ M, R" U0 |6 g9 v8 ?4 q" x: I
- QUEST.addStartNpc(7009)
# a3 f: t' A$ M2 t/ K3 K6 w; h - QUEST.addStartNpc(7011)
: a% Z' c2 Z' D' Y( b7 x) t2 O - - W8 Q$ Q! I& H! v
- STARTED.addQuestDrop(KELTIR_NPC_ID,FANGS_ITEM_ID,DROP_RATE)
j1 Z4 |) ^1 s( }# n - STARTED.addKillId(KELTIR_NPC_ID); m$ h( A4 H9 g9 F5 `" G# B
- STARTED.addTalkId(7056)
" i% }; w& }( s& ] - STARTED.addTalkI d(7012)3 G1 ]8 a5 m e8 j* |/ N
- STARTED.addTalkId(7009)- g9 A# O- n% w+ \0 @8 P8 ?: ~* b
- STARTED.addTalkId(7011)
Скопировать код
6 W& D' G n" M7 \
* o# |; A4 Y5 J: f |