Зарегистрируйтесь сейчас чтобы найти еще больше друзей, и получить полноценный доступ ко всем функциям сайта!
Для просмотра Вам необходимо авторизоваться Если Вы еще не зарегистрированы, перейдите по ссылке:Зарегистрироваться
x
Хроники Interlude
" G* W3 r) ^8 _) U( B4 mСборка L2j- a \) D/ `! K$ _* B
Обратите внимание: в файле htm стартового NCP обязательно должна быть ссылка на квест:
4 @0 W }7 |# p/ h3 w0 R/ v- STARTED.addQuestDrop(KELTIR_NPC_ID,FANGS_ITEM_ID,DROP_RATE)
Скопировать код Для этого квеста больше ничего не надо. Все необходимое для корректной работы квеста уже добавили. Вот полный текст квеста:8 }2 q4 }% E. L) G0 ` c r- n
1 X" G6 L& Y" ~: K- w6 q
- if getCount(st) >= 4 :
/ n' R5 O7 C1 `2 L - completed(st)' d" y! V/ N( i, Q; T, e3 p- r, c9 k
- return# r- H6 b3 s8 l& o Q+ t$ u0 t
/ L2 L9 D7 A }' w# W: m- class Quest (JQuest):
( ]$ f9 b! ^! D1 m - def __init__(self,id,name,descr): JQuest.__init__(self,id,name,descr)' d; n8 ^$ L9 G, v6 R& C* \
- def onEvent (self,event,st):2 C! ~# U8 k3 ~. a& z6 [2 l I
- id = st.getState()
* r n D% y+ V( K - if id == CREATED : st.setState(STARTED)2 T( t8 G! v' s/ \6 {
- elif id == COMPLETED: pass% |/ b: t6 {1 @. h
- elif id == STARTED : check(st)
( ~3 z! I% N. K* u7 h0 T' R - return/ I! E0 q9 Z9 L h& i ^; ? j1 Z
" H6 S! s4 {# G0 l( i/ a- QUEST = Quest(201,"Tutorial", "Tutorial quest")
2 u, S/ ?1 T* D: x1 k, a2 p+ }" [ - CREATED = State('Start', QUEST)
# M E& v/ F' D0 |8 h8 p( S - STARTED = State('Started', QUEST)
& m: o, p2 v* W5 |9 d& W - COMPLETED = State('Completed', QUEST)
; V! d0 I, _$ _& r' ~, Q0 C( O
# Z) @ B# s) `, ~& ~7 [. s- QUEST.setInitialState(CREATED)7 L; q9 h- d% i% j
- QUEST.addStartNpc(7056)2 N' q6 Q# [# c8 u u: k% j
- STARTED.addQuestDrop(KELTIR_NPC_ID,FANGS_ITEM_ID,DROP_RATE)
Скопировать код Теперь рассмотрим, как это работает. p7 K7 N8 x4 t) I
Игрок подходит к начальному NCP (в данном случае 7056), нажимает на «Quest». Квест будет создан и состояние квеста перейдет к CREATED и игроку будет показана страничка Start.htm с описанием квеста. Тогда метод onEvent, поле открытия странички Start.htm переведет состояние квеста в STARTED и игроку будет показана страничка Started.htm, где будет опсание того, как найти keltirs и .т.д.
- G+ G" m# a4 ^/ M$ {% I
; T W; ^* g7 Z0 {" [# J
0 e$ Q! I' Y: y' [! WПри состоянии STARTED будет зарегистрирован дроп «fangs» при убийстве keltirs. Игрок может вернуться к стартовому NCP и спросить о квесте – метод onEvent будет вызван снова. Если у игрока не хватает необходимого количества предметов, то метод check() не переведет квест в следующее состояние и Started.htm будет показана снова. Но если игрок собрал необходимее количество предметов (в данном случае 4 клыка), то метод check() вызовет метод completed() который переведет квест в новое состояние COMPLETED, заберет все клыки, даст карту мира, т.к. это награда за квест, покажет Completed.htm и завершит квест.
2 O8 L& J* y' D! F! y& K; y; C
$ T. A# G) d9 I
# ?) A! d0 e' m E7 w4 d. wТеперь давайте сделаем наш квест более похожим на то, что он должен из себя представлять. p2 r( p7 D ^- h h6 h
Прежде всего у нас есть 3 метода для объявления их в Яве – onTalk, onKill и onEvent. Если методы onTalk и onKill не объявлены, то за них все будет делать метод onEvent, т.е. определять квестовых монстров и вызывать диалоги NCP. Есть примечание, методы onTalk и onKill будут вызывать только диалоги с NCP в зависимости от текущего состояния квеста. Метод onKill будет вызываться только тогда, когда мы убиваем квестового монстра.3 U$ P' l' B! V. j% T
5 Z7 O$ G* K; k% U4 e
: b" V9 U3 O4 m; ^) ]Давайте рассмотрим как вызывается метод onKill при убийстве keltir в состоянии квеста STARTED:
L4 a* G; c d# d5 ^- STARTED.addKillId(KELTIR_NPC_ID)
Скопировать код и метод onKill в классе Quest:0 f; \& r3 D( S5 o# B+ i
. T# ?( @. i* s2 k/ Q4 L- class Quest (JQuest):" T- n' v. w: z* l
- ...0 s ^* J8 M( R4 z R4 H* h
- def onKill (self,npcId,st):- d8 R- C9 k' S3 R" V* |
- if npcId == KELTIR_NPC_ID:
6 Y y3 ?) B/ q7 A( x - n = getCount(st)/ @7 `$ v2 j) C; e/ m" u, {* s
- if n == 0:
8 E5 w! B* t& {) t! ]. {5 m - return "Chat0.htm"
, D, M1 w0 B7 r4 N0 e - elif n == 1:$ o. Y, {$ g$ Z6 ?! e7 B( h5 d
- return "Chat1.htm"
! n* l! o6 i; z9 Y$ [7 F$ _4 w - elif n >= 4:. n$ F S% `. k& I4 ~9 }
- return "Chat4.htm"$ x1 k i$ t9 m0 P7 y4 j4 E
- return "Collected "+str(n)+" of 4 fangs"
) l! X9 C/ p# ?6 v1 { - return
Скопировать код Метод onKill (а так же метод onTalk) имеет следующие параметры:9 _ Y/ v! u0 g$ |* \ k; @
3 K8 k- ]. I5 ^! ` A8 G8 N
' s- u' S8 v9 Y4 t2 t* X7 H; a2 Y; r• self – квест
& n A; d4 }. X% C& C. u• npcId – ID NCP, которого мы должны убивать (если это метод onTalk, то ID того NCP, с которым мы должны поговорить).
/ P% J; I0 c$ d+ l• st – текущее состояние игрока.0 @+ q/ C w; l7 f @3 G
! q4 s: n2 \6 [! }8 @4 `4 Z; y
2 U0 u; _# x5 UВ этом методе мы проверяем и отмечаем, является ли убитый NCP keltir’ом. В основном эта проверка не нужна, т.к. у нас только KELTIR_NPC_ID.
/ Q; a1 X& P z/ ?( \) {
K- y- q$ K, E% W& z+ {
1 V9 L0 n" ^* n1 G- j7 V& AЗатем проверяем количество предметов (в данном случае количество клыков), и если их вообще нет, то возвращаем строку "Chat0.htm", если только один предмет, то возвращаем строку "Chat1.htm", если же предметов 4 или больше, то "Chat4.htm". Если строка возвращена из методов onEvent, onKill или onTalk, то сервер покажет соответствующие htm. В Chat0.htm может иметь следующий текст: «Вы не имеете ни одного клыка, возвращайтесь позже, когда соберете 4 штуки и бла, бла, бла…», в Chat1.htm может быть следующий текст: «У Вас всего 1 клык, по этому соберите еще…». В Chat4.htm – «Вы собрали необходимое количество предметов, возвращайтесь к вашему тренеру, что бы завершить квест…»4 F6 U% d6 F X$ [0 ?7 f
9 L& [) u& [ i i: K( ?, F+ x
$ q, X0 I0 q4 |8 R+ kПримечание: если в строка return начинается с "<html>", то будет показана страничка html с текстом, который стоит далее. Так вместо:
. x- w8 U" N2 s e7 |& Preturn "Chat4.htm"
; D- S* j M3 u( m* M; k" A0 h+ N) e' _$ _0 P( Q e4 g
V) B. ?4 V _! t2 s' Q6 j$ B
можно поставить:" k) m1 T3 O1 @
- return "<html><body>Return to your trainer to complete the quest</body></html>"
Скопировать код Так же если строка заканчивается без .htm или в начале нет <html>, то текст будет выведен, как системное сообщение в окне чата. В нашем случае мы сделаем так, что бы при каждом убийстве keltik выводилось системное сообщение: «Собрано N из 4-х клыков». o, c% ~2 I8 P! b) ~( d: }1 A
+ J0 v# W( h8 y% F4 J0 s# h: t
. Y& S4 [8 [; \Наш код для onKill имеет один недостаток. Он будет постоянно показывать Chat0.htm, Chat1.htm и Chat4.htm, нам же необходимо, что бы Chat0.htm и Chat1.htm показывались только один раз. Как нам это сделать? С помощью переменных.
% d1 P- b# ~/ F. `' z) ~( ^! x
$ r, U8 R: |0 `& P$ A/ v2 L$ h: z- e2 r4 _1 _5 t* Y5 Y* R+ C
В каждом квесте строки могут храниться с помощью переменных. Эти переменные сохраняются в Вашей БД. В каждом методе мы можем назначить, прочитать и удалить переменные. Давайте изменим метод onKill, так что бы каждый диалог вызывался только один раз.5 C/ N4 Z: @/ Q ]( |/ S/ W$ b
- def onKill (self,npcId,st):* C# T2 w0 Y- `8 H
- if npcId == KELTIR_NPC_ID:
- Q+ o5 D3 V" X4 w - n = getCount(st)0 {0 q' G9 S$ h* Z2 Y& T# N5 H
- if n == 0:
' j5 x' ~% }# ]2 ?- J - if st.get('chat0') == None :
. V, r/ M% d- ^2 I - st.set("chat0", "true")
b6 U( h" G8 d - return "Chat0.htm"# H# w( R$ Q, H( C0 q% ?5 D3 \
- elif n == 1:
4 N. e N F- ~4 R4 e; e- Q - if st.get('chat1') == None : j' o& O/ Q- {# r. {" A
- st.set("chat1", "true")
2 b( j0 v. o/ m% F5 I" } - return "Chat1.htm"; |9 q2 O5 k1 V/ t0 N( B* }' r
- elif n >= 4:# `0 p$ z- y# L4 ]6 O- u1 F4 [: z
- return "Chat4.htm"! H) M% y- T) X- ~
- return "Collected "+str(n)+" of 4 fangs"
' k& N2 a4 T7 z4 y4 x - return
Скопировать код Если у игрока нет клыков (n=0), то мы получаем занчение переменной 'chat0'. Когда метод onKill вызван в первый раз, то пока ни каких переменных не имеется и python возвращает значение None. В этом случае объявляется переменная и показывается диалог Chat0.htm. Когда мы убиваем keltir, но не получаем с него клык, функция st.get('chat0') возвращает строку true, а не None. И во второй раз окно с Chat0.htm не появится, но в окне чата появится строчка «Collected 0 of 4 fangs». По тому же принципу сделано и с Chat1.htm.' [" c8 q" x# K/ |7 d2 K
- B+ I! u% z8 m. S$ O |4 ~
3 I# j* x. y) G+ d+ M" ^
Вот конечный рабочий вариант квеста:
6 J Y1 v9 Z2 I. k/ S- import sys5 J [4 Q2 _0 y) P' e
- from net.sf.l2j.gameserver.model.quest import State2 T* i6 f1 Q U6 F: Y' H
- from net.sf.l2j.gameserver.model.quest import QuestState# m- ]9 ]* e# H5 c
- from net.sf.l2j.gameserver.model.quest.jython import QuestJython as JQuest
9 [' i7 U7 c1 j$ y6 d- V5 `
7 |' z8 t! a0 D4 e- KELTIR_NPC_ID = 120824 t: f' E. f5 k, `3 n
- FANGS_ITEM_ID = 1859! Z* O% f' S- I; @" S/ h$ Z+ C
- DROP_RATE = 5000002 ?0 x: z8 C" s; `% Y. j
- 3 X* C; |0 F( w8 z. _
- WORLD_MAP_ITEM_ID = 1665' U! d4 b+ S1 Q1 {. s; \9 n7 ^: N
- $ d. Z R0 p% w) l
- def getCount(st) :
' j, n$ Q* Y& o5 }7 f6 }$ T - return st.getQuestItemsCount(FANGS_ITEM_ID)5 g/ x# Y$ W: U
- L7 t( w0 D# P% j3 d
- def completed(st) :. _0 ^, t q3 B8 l( \7 U3 |, F r9 u
- st.setState(COMPLETED)
( J5 k! `: W) G% B4 x# ?7 g - st.clearQuestDrops()* ?1 F9 D; Y* W+ K
- st.takeItems(FANGS_ITEM_ID,-1)+ t: U# |+ A4 t* J: T5 w
- st.giveItems(WORLD_MAP_ITEM_ID,1)
, h+ n$ e, B& S L0 `% q - st.exitQuest(False)5 B/ ?0 S. C X5 x- H( E+ f( j
- return6 U1 ]! C4 d5 [' H2 q9 q2 b8 w& v
- . _& N6 ^1 ?8 W$ _
- def check(st) :
a6 f: O5 w/ r* j - if getCount(st) >= 4 :0 R# O# r' _' `# R( t: e1 ~
- completed(st)
" Q# \% h- A. U% Y - return
e( @( b3 u% N5 T& f
& R, q8 K( _) s# X. ~1 w; h1 z& s& ]- class Quest (JQuest):
, t. l8 g; b9 M+ [) K& `
' H. [1 V$ F; Q& X0 V6 P' K- def __init__(self,id,name,descr): JQuest.__init__(self,id,name,descr)
- Q$ s# Z. N1 ?+ T- s
" t' L* ] R' Z- def onEvent (self,event,st):
( I* a, q2 H- l - id = st.getState()
; w$ Z+ A+ i7 U7 N" [) y4 _4 x - if id == CREATED : st.setState(STARTED)
, [$ e1 G) W# e2 i) _ - elif id == COMPLETED: pass3 K2 R' u0 m0 M# z! I ?3 ~0 G# ]
- elif id == STARTED : check(st)
; v" Y- y V) Y - return
/ K& @& |( O7 L0 L0 g; I0 i - 4 z) B( r: J8 O) N& l5 _
- def onKill (self,npcId,st):
& X. `3 x' e7 ?. V& }) A - if npcId == KELTIR_NPC_ID:
8 O1 G, N1 f5 i- R# B8 L: { - n = getCount(st)
$ u1 T8 V8 h1 ? M2 K' w9 l6 m - if n == 0:
& g- u; u/ m) a7 U! Z - if st.get('chat0') == None : p$ z! F, E2 c* q( H) J
- st.set("chat0", "true")
6 ^" Z1 v3 |0 x - return "Chat0.htm"
6 y* S* y0 Y+ v - elif n == 1:2 _; G6 Q5 Q. L- L+ r) H
- if st.get('chat1') == None :
: j3 C& i! R4 R0 N& t Q - st.set("chat1", "true")
+ A V) `& i0 r8 w6 b3 ?9 U - return "Chat1.htm"! S6 ~+ T4 `7 Y$ ], b f0 X
- elif n >= 4:
6 T4 o; d4 L. _: ~* b - return "Chat4.htm"3 y8 j! n5 }' {+ H- i
- return "Collect "+str(n)+" of 4 fangs"" J; [* V, X" D' k# _. P( Y* ~
- return8 b- j% E3 `" ?0 R% E
1 t3 n Z7 C' ]; i# B- QUEST = Quest(201, "Tutorial", "Tutorial quest")/ m1 z* A A" M
- CREATED = State('Start', QUEST)
6 i& c$ v+ a: n0 ^/ _% S9 [ - STARTED = State('Started', QUEST)
4 i) P; }( p6 b# | - COMPLETED = State('Completed', QUEST)
f9 W7 |/ F9 K
7 \/ i" J' K2 f- QUEST.setInitialState(CREATED)2 p' N+ q! m& X7 \2 ]
- QUEST.addStartNpc(7056)
" v9 L& U! F6 v* X0 J) b' R( M - QUEST.addStartNpc(7012)! w6 @( l( d+ {1 s* @' g
- QUEST.addStartNpc(7009)+ Q7 ~2 [( R! m: l* I5 U m
- QUEST.addStartNpc(7011) K8 p; q7 [5 Q6 Q" P2 m$ I* v
. Q! h8 M% C- P- STARTED.addQuestDrop(KELTIR_NPC_ID,FANGS_ITEM_ID,DROP_RATE)9 M& V. _+ N5 o: s
- STARTED.addKillId(KELTIR_NPC_ID)
( q$ M7 U3 E* ~7 V3 q - STARTED.addTalkId(7056)# W; e2 z, ~% o4 w- i) g
- STARTED.addTalkI d(7012)
' I0 m0 O) r# e g6 i" y! r/ r - STARTED.addTalkId(7009)
1 N1 |: ]( u d - STARTED.addTalkId(7011)
Скопировать код
! Y7 h; F, r( i, D! Q0 @1 l( R4 Z; Z' T$ ^9 s
|