Зарегистрируйтесь сейчас чтобы найти еще больше друзей, и получить полноценный доступ ко всем функциям сайта!
Для просмотра Вам необходимо авторизоваться Если Вы еще не зарегистрированы, перейдите по ссылке:Зарегистрироваться
x
Хроники Interlude
/ J/ M+ M/ h# U$ c/ MСборка L2j) W0 v2 A: N/ \) a7 F
Обратите внимание: в файле htm стартового NCP обязательно должна быть ссылка на квест:
; {! r7 Q2 N6 L! i) p% e& ]$ V6 T- STARTED.addQuestDrop(KELTIR_NPC_ID,FANGS_ITEM_ID,DROP_RATE)
Скопировать код Для этого квеста больше ничего не надо. Все необходимое для корректной работы квеста уже добавили. Вот полный текст квеста:% Z$ h/ B; L% I; P! s. X
& B8 t! o3 Y) m" R- if getCount(st) >= 4 :+ X# M/ O% W" T0 K8 C
- completed(st)
4 e* `3 A0 Q) l7 d* n8 u! r1 A - return3 @% [9 Z% _- A
- ' u) p' z) P5 J7 L6 K; C) O1 d v
- class Quest (JQuest):5 V ~8 y5 \$ J3 C+ q6 n
- def __init__(self,id,name,descr): JQuest.__init__(self,id,name,descr)) r }! e5 y% S
- def onEvent (self,event,st):5 y/ t2 [2 }: S
- id = st.getState(). D/ ]! O; R. n l8 c/ F% Z4 W ]7 m
- if id == CREATED : st.setState(STARTED)5 u8 `3 ?- Z6 ]; D0 T- |% }% v, }9 ]
- elif id == COMPLETED: pass3 S6 L5 D9 r0 U' R; W
- elif id == STARTED : check(st)9 Y% s* q, d V* q
- return. o" y1 u! S, |4 S0 b5 m
$ h6 f2 ?; \# p0 I7 ?& _- QUEST = Quest(201,"Tutorial", "Tutorial quest")# r, `% I- v) g
- CREATED = State('Start', QUEST)
7 g3 i! V, U9 M7 s - STARTED = State('Started', QUEST)
# G5 }) N/ l0 i' D& W1 k6 w. @ - COMPLETED = State('Completed', QUEST)
9 u. b4 Q4 ?# c) `4 J$ z- F6 { - * q, P/ u2 P0 y% H% W1 @6 T
- QUEST.setInitialState(CREATED)
$ W) p$ N6 x: W! Q- i" i8 b - QUEST.addStartNpc(7056)
: q& s* ~5 s: p6 w! N2 w+ k8 w+ `& Y - STARTED.addQuestDrop(KELTIR_NPC_ID,FANGS_ITEM_ID,DROP_RATE)
Скопировать код Теперь рассмотрим, как это работает.
& y3 N) U+ s) l7 t2 a3 T# B: ~Игрок подходит к начальному NCP (в данном случае 7056), нажимает на «Quest». Квест будет создан и состояние квеста перейдет к CREATED и игроку будет показана страничка Start.htm с описанием квеста. Тогда метод onEvent, поле открытия странички Start.htm переведет состояние квеста в STARTED и игроку будет показана страничка Started.htm, где будет опсание того, как найти keltirs и .т.д.7 Q. U/ d1 [$ j
2 N7 l0 m ?4 p8 G/ c$ F
0 w! I/ Y/ ~, n) m- g. SПри состоянии STARTED будет зарегистрирован дроп «fangs» при убийстве keltirs. Игрок может вернуться к стартовому NCP и спросить о квесте – метод onEvent будет вызван снова. Если у игрока не хватает необходимого количества предметов, то метод check() не переведет квест в следующее состояние и Started.htm будет показана снова. Но если игрок собрал необходимее количество предметов (в данном случае 4 клыка), то метод check() вызовет метод completed() который переведет квест в новое состояние COMPLETED, заберет все клыки, даст карту мира, т.к. это награда за квест, покажет Completed.htm и завершит квест.& N, V, j+ P) } a5 Q$ y. t; g* l! v- P/ [
' d) a0 { f9 v/ |$ |( ~: S4 m D' Y& v5 ? f4 i8 G, G8 n4 J
Теперь давайте сделаем наш квест более похожим на то, что он должен из себя представлять., H4 M4 j/ M4 r B, J4 I3 b/ _5 B6 t
Прежде всего у нас есть 3 метода для объявления их в Яве – onTalk, onKill и onEvent. Если методы onTalk и onKill не объявлены, то за них все будет делать метод onEvent, т.е. определять квестовых монстров и вызывать диалоги NCP. Есть примечание, методы onTalk и onKill будут вызывать только диалоги с NCP в зависимости от текущего состояния квеста. Метод onKill будет вызываться только тогда, когда мы убиваем квестового монстра., @( s0 ?3 j3 P# \, X# k( I5 j8 q
2 A1 y! T5 i" e/ Z
; R% v& \; N' S" H; SДавайте рассмотрим как вызывается метод onKill при убийстве keltir в состоянии квеста STARTED:
2 l- D7 x8 Q6 M9 f4 K- STARTED.addKillId(KELTIR_NPC_ID)
Скопировать код и метод onKill в классе Quest:
' N2 ]5 p& G) D! `& y7 b
' D; }% S: s% g- class Quest (JQuest):( w+ R( J7 t9 ~ p$ J
- ...
! a1 _; W; |3 A; q/ t - def onKill (self,npcId,st):. E+ g: e, _% c$ `" t
- if npcId == KELTIR_NPC_ID:% X2 A7 Y, T1 d( x
- n = getCount(st)
9 T6 B. _4 G) N5 h! t2 R - if n == 0:
0 Z( V/ n. |5 X& ? H. |& {8 Z - return "Chat0.htm"
& k2 H( k" o0 X* j/ I1 }9 ?) [ - elif n == 1:
3 {3 ?8 c8 @. ?' J# C - return "Chat1.htm"1 Z s+ Z, {3 M c! y
- elif n >= 4:
! M1 M$ O* R4 ~ - return "Chat4.htm"
6 Q2 W3 _$ n/ P* u) D% N2 z" _ - return "Collected "+str(n)+" of 4 fangs"9 v1 \* m9 |! W' `, y9 k. B
- return
Скопировать код Метод onKill (а так же метод onTalk) имеет следующие параметры: O& h- X6 D7 M. h- y
* q3 ?9 w- y- N l4 [- T* v' P
Y0 n7 A' q6 o( ]• self – квест
6 q; g6 Q' u, Q7 D- d• npcId – ID NCP, которого мы должны убивать (если это метод onTalk, то ID того NCP, с которым мы должны поговорить).0 E, ?) W1 ~6 x
• st – текущее состояние игрока.
* ^( F, B0 j: ]% z2 G2 k& K3 y- S- i; Y0 ]& ?$ h4 g/ t T
1 O1 q! S% ^+ O! q6 i# ~3 ?# P
В этом методе мы проверяем и отмечаем, является ли убитый NCP keltir’ом. В основном эта проверка не нужна, т.к. у нас только KELTIR_NPC_ID.
! v2 x8 L; Z% p' Z% k
" p6 o) o( B3 B
+ R& @) a9 R+ n( P' R* B, gЗатем проверяем количество предметов (в данном случае количество клыков), и если их вообще нет, то возвращаем строку "Chat0.htm", если только один предмет, то возвращаем строку "Chat1.htm", если же предметов 4 или больше, то "Chat4.htm". Если строка возвращена из методов onEvent, onKill или onTalk, то сервер покажет соответствующие htm. В Chat0.htm может иметь следующий текст: «Вы не имеете ни одного клыка, возвращайтесь позже, когда соберете 4 штуки и бла, бла, бла…», в Chat1.htm может быть следующий текст: «У Вас всего 1 клык, по этому соберите еще…». В Chat4.htm – «Вы собрали необходимое количество предметов, возвращайтесь к вашему тренеру, что бы завершить квест…»0 G" ~, s2 k8 D) R* H
2 n! C3 T( C* u) e0 a5 W
( ?7 B" A. O% ` c; \Примечание: если в строка return начинается с "<html>", то будет показана страничка html с текстом, который стоит далее. Так вместо:3 I o) U) j x! [( A5 |
return "Chat4.htm", B1 Z E @/ e" z' }; s
! |- V3 g+ n! T; Y. i
- F$ P4 A4 P" d0 Iможно поставить:8 c2 G9 t9 ?) Y2 k( j8 y# |3 U
- return "<html><body>Return to your trainer to complete the quest</body></html>"
Скопировать код Так же если строка заканчивается без .htm или в начале нет <html>, то текст будет выведен, как системное сообщение в окне чата. В нашем случае мы сделаем так, что бы при каждом убийстве keltik выводилось системное сообщение: «Собрано N из 4-х клыков».
6 R% F: l) A# F' Q' Y0 [, Q D( T: j* j( e! A
8 ? S* o' ]% c4 d; g5 t
Наш код для onKill имеет один недостаток. Он будет постоянно показывать Chat0.htm, Chat1.htm и Chat4.htm, нам же необходимо, что бы Chat0.htm и Chat1.htm показывались только один раз. Как нам это сделать? С помощью переменных.
" M3 u9 _) [9 A* v
( p: W" j8 Q. r1 O
3 W1 V% x; R3 w& bВ каждом квесте строки могут храниться с помощью переменных. Эти переменные сохраняются в Вашей БД. В каждом методе мы можем назначить, прочитать и удалить переменные. Давайте изменим метод onKill, так что бы каждый диалог вызывался только один раз.- h9 i! h5 g4 g2 g; K5 F
- def onKill (self,npcId,st):5 F% J; C8 p/ ?: f/ i# M0 C6 x
- if npcId == KELTIR_NPC_ID:$ M4 Z! o+ A" {& P
- n = getCount(st)& d/ Z; f2 Z/ [/ ?" C- {' J' X
- if n == 0:
5 U0 P& C! ?) I9 s9 \ - if st.get('chat0') == None :
8 g# g. X( t! K, Z E( _1 }4 f - st.set("chat0", "true")2 ~3 T# n; m9 H$ R- Q$ D6 B
- return "Chat0.htm"5 q2 H2 w! L3 y
- elif n == 1:; F3 @+ I2 K* w$ ]0 v* F4 `% D1 c
- if st.get('chat1') == None :
. q# @' m. D4 r - st.set("chat1", "true")
% U( [; p4 Y+ B+ E! m - return "Chat1.htm"
* W" q" K/ i0 k7 y$ ]$ m+ R - elif n >= 4: L8 G1 n$ F# {5 w g. q
- return "Chat4.htm"0 [+ i g8 ?, e7 l- @# }& u2 K
- return "Collected "+str(n)+" of 4 fangs"
! n0 |. G# C; b3 Z3 `/ p. F - return
Скопировать код Если у игрока нет клыков (n=0), то мы получаем занчение переменной 'chat0'. Когда метод onKill вызван в первый раз, то пока ни каких переменных не имеется и python возвращает значение None. В этом случае объявляется переменная и показывается диалог Chat0.htm. Когда мы убиваем keltir, но не получаем с него клык, функция st.get('chat0') возвращает строку true, а не None. И во второй раз окно с Chat0.htm не появится, но в окне чата появится строчка «Collected 0 of 4 fangs». По тому же принципу сделано и с Chat1.htm.% ~2 e! I) B# f' U9 W" B
* r; ^/ ]$ a+ k; A, x K+ \) e
3 \* q7 P0 r# l: E7 EВот конечный рабочий вариант квеста:2 ^7 Q8 O+ e. J1 `. H
- import sys
0 t# y) f5 x# `4 A6 h - from net.sf.l2j.gameserver.model.quest import State0 Z1 C" i. [ X
- from net.sf.l2j.gameserver.model.quest import QuestState
5 f5 {8 [- k+ _' b1 _% e0 @; b8 N - from net.sf.l2j.gameserver.model.quest.jython import QuestJython as JQuest
( m& a# K% |3 k1 f0 P3 a$ D - z8 f0 o; g5 Y ] h5 G& Y
- KELTIR_NPC_ID = 12082& P1 C/ O- U' z: E o0 m0 M2 T
- FANGS_ITEM_ID = 1859; Y" G# S( ^) B: `& J
- DROP_RATE = 500000# a8 ]$ ^6 U7 R# D: o, r
# h, c5 n- y' L6 t- WORLD_MAP_ITEM_ID = 1665
% [+ E8 }: J# H; v& S6 h5 m
4 i ]4 i; K# ~) a y8 l3 o- def getCount(st) :
; y/ H4 @8 ^0 Q+ ]) g8 r$ A; T - return st.getQuestItemsCount(FANGS_ITEM_ID)5 v/ J I" P5 E# M
% O/ ^' G6 d' Y$ I- def completed(st) :1 V5 D9 j. \; B4 A+ w' r
- st.setState(COMPLETED)5 i$ h& S+ j& L6 t! T' [
- st.clearQuestDrops()
( S4 U9 }% m/ ~( v - st.takeItems(FANGS_ITEM_ID,-1)6 R7 ^, C0 C" h. Y+ A2 {
- st.giveItems(WORLD_MAP_ITEM_ID,1)/ y4 d6 H, i0 I9 b; {
- st.exitQuest(False)
1 a! m2 g6 ?9 [- a- G - return
0 t& v3 N5 J+ O+ k! p - - l3 E9 J, P& Z" B6 ?& `3 _
- def check(st) :# }( G0 Z, ?5 ?8 r) |
- if getCount(st) >= 4 :" t5 l( W$ J: s, I. ?( [5 r$ f
- completed(st)
* ~1 q) F/ I6 ]5 a) m1 }1 T' ~0 ] - return) g- x5 h9 J+ d! k9 o3 E/ p
- 6 N' a5 ~" y) S6 i" H, Q
- class Quest (JQuest):) w2 `. e! d5 e6 B
" d4 w3 j/ ?0 ^/ D, D0 p( w- def __init__(self,id,name,descr): JQuest.__init__(self,id,name,descr)
5 \0 C5 E, M3 z: R* v
( d' ~+ Q% Y2 s5 R3 ?- def onEvent (self,event,st):
* P" S$ O! P E( W9 ~& V4 g - id = st.getState()' s' }6 H: |9 e U- W3 l
- if id == CREATED : st.setState(STARTED)
7 A5 R7 D; J* ?- a9 {: M; w - elif id == COMPLETED: pass* x6 R) T5 h% E- x! U# n7 m
- elif id == STARTED : check(st)& x+ c$ T* Q- _# S4 ^. Z
- return, H5 f# e! ^3 v* b I) ^! N- I
- ; i t+ Q' ?. `9 ^% ?3 T% l) j
- def onKill (self,npcId,st):
8 U: w1 c. t( v - if npcId == KELTIR_NPC_ID:
% O& _8 Q: f4 j' t - n = getCount(st)
' Q: k. I9 n9 @; f+ H$ i - if n == 0:
. @" ?! G" x% \; P6 \( v2 S - if st.get('chat0') == None :4 X& W: \- M* a# U/ W% l
- st.set("chat0", "true")
1 h, Y0 \- F6 l - return "Chat0.htm"1 H- g/ `# w; k) v+ h& L- N
- elif n == 1:0 t; {. h/ q: z" u3 d; a+ N! g
- if st.get('chat1') == None :
7 J8 L& ~+ K) Z% k9 f9 c" w- t - st.set("chat1", "true")
! I. Y% P6 V, P- }/ t. k - return "Chat1.htm"
: Z+ m# X1 L F; J0 e, W - elif n >= 4:( X+ F9 P3 P8 ], {3 o
- return "Chat4.htm"! i7 m, F$ _9 d+ j X
- return "Collect "+str(n)+" of 4 fangs"' d( I# E9 ^; M T8 l7 U" N
- return( b M( T/ I4 u4 z# J
6 Q0 i0 y# e2 a; M- p- B# O- QUEST = Quest(201, "Tutorial", "Tutorial quest")7 d$ V6 g9 N1 X' D" x
- CREATED = State('Start', QUEST)
" O. O! q7 M0 k7 ^8 a( u4 } - STARTED = State('Started', QUEST)- h( ~9 r& W, G1 P( b6 D
- COMPLETED = State('Completed', QUEST)& W! ]& w' l/ }" N
0 Q" K, r, N' D8 I; X {% Z- QUEST.setInitialState(CREATED)
7 _6 a: c& c4 h - QUEST.addStartNpc(7056)
! ^* C) D; } ]1 Q - QUEST.addStartNpc(7012); T6 F8 q" Z; o! O
- QUEST.addStartNpc(7009)
# v* Y, C' w. A7 w/ Z7 w - QUEST.addStartNpc(7011)7 W3 F# N( X/ C) }9 P9 Y( y' V
# I1 q1 \" h7 i6 \- STARTED.addQuestDrop(KELTIR_NPC_ID,FANGS_ITEM_ID,DROP_RATE)
. `1 H& Z0 N0 H; u# z( Z4 M4 C - STARTED.addKillId(KELTIR_NPC_ID)
: Q/ ^& H t9 ?# b! u C# `8 G# L- S; a - STARTED.addTalkId(7056)
) M g) n5 o! [% u, D - STARTED.addTalkI d(7012)8 c5 X$ z. F) T* R+ {4 i
- STARTED.addTalkId(7009)
7 Y! F5 ~) D6 S - STARTED.addTalkId(7011)
Скопировать код 7 ^$ B- w4 x+ D! o4 X) D
, F8 e. P( a# [3 m) f, r! H |