Зарегистрируйтесь сейчас чтобы найти еще больше друзей, и получить полноценный доступ ко всем функциям сайта!
Для просмотра Вам необходимо авторизоваться Если Вы еще не зарегистрированы, перейдите по ссылке:Зарегистрироваться
x
Хроники Interlude
' ?3 t$ r" O6 _4 e7 C$ W1 M lСборка L2j
7 K) M, T$ c4 c9 RОбратите внимание: в файле htm стартового NCP обязательно должна быть ссылка на квест:* t# D$ p' L* E1 d7 |9 o
- STARTED.addQuestDrop(KELTIR_NPC_ID,FANGS_ITEM_ID,DROP_RATE)
Скопировать код Для этого квеста больше ничего не надо. Все необходимое для корректной работы квеста уже добавили. Вот полный текст квеста:
5 N9 }6 s2 E4 H( ]( j+ [# y) S# q1 Z: X S. C
- if getCount(st) >= 4 :
# e% ^8 T5 }# Q) F - completed(st)/ _* b: V+ Y' Y& V2 B5 _
- return# h$ R+ ]& }2 T- b: F8 S
- 8 W3 x2 v) j2 M* d- A c6 [& s) }' s
- class Quest (JQuest):
! k. q& U8 Z& j4 a/ x" q - def __init__(self,id,name,descr): JQuest.__init__(self,id,name,descr)1 ]% k3 Y6 h* H+ v0 ]$ m
- def onEvent (self,event,st):% t& h1 B: a9 d9 v
- id = st.getState()
+ d2 `, ]5 ]& c6 K - if id == CREATED : st.setState(STARTED)
( g5 |( g3 C }% L. g+ v! G - elif id == COMPLETED: pass3 _! _0 ?2 H# `9 t5 B0 G. T
- elif id == STARTED : check(st)
$ x5 [0 e9 u& W% `1 u% [3 U3 A4 i - return
2 G0 J. K6 N" ~# F0 h9 ] - ) p5 @! p# [% e: m7 d
- QUEST = Quest(201,"Tutorial", "Tutorial quest")
( i7 I- _0 ]! k. e3 O) ]! P$ t - CREATED = State('Start', QUEST)! h' n4 V; j4 A# S j' q& O& r
- STARTED = State('Started', QUEST)) k) u! s( ~6 b6 U3 V
- COMPLETED = State('Completed', QUEST)
7 O( y- G' I* @* E, C - ( J7 [" i' O% ]/ h
- QUEST.setInitialState(CREATED). @" G8 ~/ b; O; w1 I7 b. e
- QUEST.addStartNpc(7056) y: Q0 E; Q) C, N" O2 _
- STARTED.addQuestDrop(KELTIR_NPC_ID,FANGS_ITEM_ID,DROP_RATE)
Скопировать код Теперь рассмотрим, как это работает.. g) ^* e4 C. Y! V/ I/ Z( v5 Y3 q
Игрок подходит к начальному NCP (в данном случае 7056), нажимает на «Quest». Квест будет создан и состояние квеста перейдет к CREATED и игроку будет показана страничка Start.htm с описанием квеста. Тогда метод onEvent, поле открытия странички Start.htm переведет состояние квеста в STARTED и игроку будет показана страничка Started.htm, где будет опсание того, как найти keltirs и .т.д.5 x" M) |! Y; j* m3 S6 k4 I
O, B/ ^8 m; r# _, k0 p# T+ v! C9 z1 m; r1 J# S' ~, | u! M
При состоянии STARTED будет зарегистрирован дроп «fangs» при убийстве keltirs. Игрок может вернуться к стартовому NCP и спросить о квесте – метод onEvent будет вызван снова. Если у игрока не хватает необходимого количества предметов, то метод check() не переведет квест в следующее состояние и Started.htm будет показана снова. Но если игрок собрал необходимее количество предметов (в данном случае 4 клыка), то метод check() вызовет метод completed() который переведет квест в новое состояние COMPLETED, заберет все клыки, даст карту мира, т.к. это награда за квест, покажет Completed.htm и завершит квест.; U4 D! e$ H! D2 V. t! R S
% m5 h5 y" |5 e. O/ R2 x, E' |
. M9 F8 b# g' {6 `& mТеперь давайте сделаем наш квест более похожим на то, что он должен из себя представлять.
m" x+ Y: A0 `" l1 {Прежде всего у нас есть 3 метода для объявления их в Яве – onTalk, onKill и onEvent. Если методы onTalk и onKill не объявлены, то за них все будет делать метод onEvent, т.е. определять квестовых монстров и вызывать диалоги NCP. Есть примечание, методы onTalk и onKill будут вызывать только диалоги с NCP в зависимости от текущего состояния квеста. Метод onKill будет вызываться только тогда, когда мы убиваем квестового монстра.
' R3 l2 g$ i. O/ p9 \) j, @1 n, S0 q/ X7 T
+ i% n9 N; x& m. K1 n' C1 L, D' RДавайте рассмотрим как вызывается метод onKill при убийстве keltir в состоянии квеста STARTED:
0 ^" b7 l! }' M) \% }- STARTED.addKillId(KELTIR_NPC_ID)
Скопировать код и метод onKill в классе Quest:
0 `" i1 ?5 H# `1 a4 w& Y) Y/ v3 j* d% J7 x5 p
- class Quest (JQuest):
2 m, O& ~2 g7 K1 `0 i - ...
& T% ^, G1 h; R$ M" q - def onKill (self,npcId,st):
6 R/ z6 Q* C% X$ u; u: I - if npcId == KELTIR_NPC_ID:* V. L1 u' `" P
- n = getCount(st)* q' t0 l: }* s
- if n == 0:
5 f- H* W) h* u( x4 Z - return "Chat0.htm"; \( i. \5 f6 F+ [! G" w. F! ~7 z' H9 s
- elif n == 1:
& A3 b; r9 Q" v0 v# U. \# [6 D7 g - return "Chat1.htm"- ^3 f; |# d! J) G
- elif n >= 4:
# R( D& _2 E" A* ]% F - return "Chat4.htm"
: a3 Y: L$ n( T1 r, ^" @# {, D - return "Collected "+str(n)+" of 4 fangs"
* h7 }; D& ~0 [: B' S1 S* [ - return
Скопировать код Метод onKill (а так же метод onTalk) имеет следующие параметры:
$ u. H$ e1 G) _
! P! Z& K2 }5 O: J/ e( |$ A1 p( L
: V8 m) G* V. f0 a& {• self – квест! f4 F, V) W. _; r
• npcId – ID NCP, которого мы должны убивать (если это метод onTalk, то ID того NCP, с которым мы должны поговорить).2 l, d1 }2 t0 D0 G, a) ^
• st – текущее состояние игрока.
# e) {% P! B% Q
p/ @6 P1 I' | m- p
: ]# I3 H* ^% x- FВ этом методе мы проверяем и отмечаем, является ли убитый NCP keltir’ом. В основном эта проверка не нужна, т.к. у нас только KELTIR_NPC_ID.
2 v/ y2 U$ \0 D5 Y f9 a; N) s) b) F' W' k
* X! q3 S' f, E7 V0 v/ fЗатем проверяем количество предметов (в данном случае количество клыков), и если их вообще нет, то возвращаем строку "Chat0.htm", если только один предмет, то возвращаем строку "Chat1.htm", если же предметов 4 или больше, то "Chat4.htm". Если строка возвращена из методов onEvent, onKill или onTalk, то сервер покажет соответствующие htm. В Chat0.htm может иметь следующий текст: «Вы не имеете ни одного клыка, возвращайтесь позже, когда соберете 4 штуки и бла, бла, бла…», в Chat1.htm может быть следующий текст: «У Вас всего 1 клык, по этому соберите еще…». В Chat4.htm – «Вы собрали необходимое количество предметов, возвращайтесь к вашему тренеру, что бы завершить квест…»
7 u( }& A9 J4 T4 ^1 s+ O/ p( @( P; h2 p
2 I5 ?6 y, `# U, a4 aПримечание: если в строка return начинается с "<html>", то будет показана страничка html с текстом, который стоит далее. Так вместо:
+ S: l1 V4 X4 E% m4 P3 S. Rreturn "Chat4.htm"4 H! T" ?1 `/ r1 a& _* A) j% |# f
3 C( T+ [7 b8 q$ w0 _. t7 O8 z% s8 n1 c* b0 U3 K2 c8 r; M/ C
можно поставить:# o0 i$ i& X7 E' g8 @$ R% p7 x# k
- return "<html><body>Return to your trainer to complete the quest</body></html>"
Скопировать код Так же если строка заканчивается без .htm или в начале нет <html>, то текст будет выведен, как системное сообщение в окне чата. В нашем случае мы сделаем так, что бы при каждом убийстве keltik выводилось системное сообщение: «Собрано N из 4-х клыков».) d5 A' {% E+ S5 B7 o- C
* E1 H6 J2 Z8 {" G1 g
: t* T5 T4 |% S" j
Наш код для onKill имеет один недостаток. Он будет постоянно показывать Chat0.htm, Chat1.htm и Chat4.htm, нам же необходимо, что бы Chat0.htm и Chat1.htm показывались только один раз. Как нам это сделать? С помощью переменных.2 @& C6 b* _7 _" b& O& J
6 ~ B: D" n0 O$ Y' C
; R2 V/ O4 i1 g5 _0 z) E
В каждом квесте строки могут храниться с помощью переменных. Эти переменные сохраняются в Вашей БД. В каждом методе мы можем назначить, прочитать и удалить переменные. Давайте изменим метод onKill, так что бы каждый диалог вызывался только один раз.5 l, N3 H2 w4 i
- def onKill (self,npcId,st):
6 W( h* e6 [" m3 N' i - if npcId == KELTIR_NPC_ID:
, x) G9 F( {8 n, D9 G5 l - n = getCount(st)
* x! B3 l0 T V6 k4 u - if n == 0:
7 A! b/ v0 }1 A8 S" Z: H - if st.get('chat0') == None :
; p4 H8 W, T" u - st.set("chat0", "true")
( A% z3 ^9 X% Z9 I5 y" w - return "Chat0.htm"( R# _( {- ~8 T5 G3 w6 z. L2 e
- elif n == 1:' B/ [: O6 T+ c5 y* f0 t! U; P9 L
- if st.get('chat1') == None :
! W5 k9 b( P( [ - st.set("chat1", "true")' }. h) D m& u; t3 F
- return "Chat1.htm"
3 U% H0 Y; G) [( {/ B - elif n >= 4:$ _! P. n- a( q$ k0 C) E, q
- return "Chat4.htm"
5 h8 f9 Y3 i; H - return "Collected "+str(n)+" of 4 fangs"
* W+ B! _% q) K: k7 e - return
Скопировать код Если у игрока нет клыков (n=0), то мы получаем занчение переменной 'chat0'. Когда метод onKill вызван в первый раз, то пока ни каких переменных не имеется и python возвращает значение None. В этом случае объявляется переменная и показывается диалог Chat0.htm. Когда мы убиваем keltir, но не получаем с него клык, функция st.get('chat0') возвращает строку true, а не None. И во второй раз окно с Chat0.htm не появится, но в окне чата появится строчка «Collected 0 of 4 fangs». По тому же принципу сделано и с Chat1.htm.
' \+ \0 W2 b- L- D$ A
$ ~# g5 v G+ q. g+ I$ j, T: r. A5 O8 X8 c
Вот конечный рабочий вариант квеста:9 d& K7 S/ d+ x6 Q
- import sys9 \ ~: z" d: l/ z' v1 W0 x" S3 @
- from net.sf.l2j.gameserver.model.quest import State; `; c) G; ], b% o( y
- from net.sf.l2j.gameserver.model.quest import QuestState8 Q; p/ y+ e" x
- from net.sf.l2j.gameserver.model.quest.jython import QuestJython as JQuest
4 i1 X+ f5 A% n4 o* A- W - & m& O5 R9 f. P) F( D
- KELTIR_NPC_ID = 12082
9 j2 C4 J: P' q: N- a - FANGS_ITEM_ID = 18595 d4 K/ R- z# C0 A
- DROP_RATE = 500000. _3 {: V6 s2 j& _: n* i
- 7 K( H, F1 s6 y( f7 S
- WORLD_MAP_ITEM_ID = 1665) i" J. [9 E2 c& C4 n2 J( x; y7 U
- , M# ~( o; w( N8 n( Y
- def getCount(st) :) h, b% Z- Z; c$ C& ?
- return st.getQuestItemsCount(FANGS_ITEM_ID). J- J7 v7 Y# ]+ C
- 3 F+ F+ o: Q- M D6 }' d
- def completed(st) :
: W ^; l) B6 P7 n) m - st.setState(COMPLETED)0 I4 r4 ^; S# J; Y4 ^! I
- st.clearQuestDrops()' p4 N" {( {4 {4 y* \* @/ ^# o
- st.takeItems(FANGS_ITEM_ID,-1)
0 o$ ^" Y* d A {9 r9 W1 S# W; _ - st.giveItems(WORLD_MAP_ITEM_ID,1)& A) u2 _' n4 W% ~# k
- st.exitQuest(False); j: @1 M8 K' @; I' v$ @
- return
8 b8 z! J" z; R7 }3 X7 ^" ? - h8 z- _* n! @. M k- x5 J
- def check(st) :; c/ [0 j( v2 `
- if getCount(st) >= 4 :
, j% C( ]0 q% D( c0 Z/ V4 O/ a/ r - completed(st)
- t& t9 Z' R5 W - return9 D8 p8 I% j+ f9 I
- `9 {! x# y8 D. J9 I
- class Quest (JQuest):
7 U3 T4 Q1 D6 Z* l: K% A/ Z% ` - 0 z& v" @; `# D! J
- def __init__(self,id,name,descr): JQuest.__init__(self,id,name,descr)6 q/ b& c) g/ R* O* ?" F
: ~5 x9 P; J& C7 X& K5 ]4 c- def onEvent (self,event,st):7 P$ Y3 J1 R" B# Y1 ?
- id = st.getState()0 W7 R4 @# N9 y0 y+ S
- if id == CREATED : st.setState(STARTED)
- x- x8 E7 J$ f6 h$ Y - elif id == COMPLETED: pass; R* ?7 @! d2 n: _
- elif id == STARTED : check(st)) t2 ]/ f2 ?+ G5 {
- return( [8 G* }. a/ u; N, g( d* L! ~
- 8 l" Z0 E) \3 H, C
- def onKill (self,npcId,st):
( v4 O& U! p# [0 T8 g" J - if npcId == KELTIR_NPC_ID:1 }/ j/ S' v0 f5 h ~% U
- n = getCount(st)! X& K, K7 Y4 t( i4 _$ T. L8 g
- if n == 0:& L# I- |6 z1 A
- if st.get('chat0') == None :
" F% B) ~ {2 b: S# A$ K - st.set("chat0", "true")
! P. t' p& W3 {+ ? - return "Chat0.htm", O3 A8 ?) b, v( D; K
- elif n == 1:
& g+ {3 v1 _- Y/ U - if st.get('chat1') == None :7 d" d. G! y& N% X# f
- st.set("chat1", "true")8 D3 F7 a1 D( j8 O
- return "Chat1.htm"* Q4 n' t6 l5 S, v6 K% h- j' K
- elif n >= 4:" I- }. e! i4 w+ W# \: O: ?
- return "Chat4.htm"8 v& ^( x' v/ G1 S+ k# `
- return "Collect "+str(n)+" of 4 fangs"8 H# m# n `% G" \! F4 c9 S
- return9 b0 ~, F) V; a
% a* o Q x! o) G: r, c, ~. }- QUEST = Quest(201, "Tutorial", "Tutorial quest")
" o7 Z; B* l D: i) G - CREATED = State('Start', QUEST)
J1 b/ m# T! y. A Y1 M - STARTED = State('Started', QUEST)
7 ~9 h G+ U" N5 a' }, r: F) r - COMPLETED = State('Completed', QUEST)
" H7 r; }! j w - ) B- v/ j' m) t; m0 N
- QUEST.setInitialState(CREATED). J- l# a6 i/ B+ e- C5 l' K/ w2 z
- QUEST.addStartNpc(7056)
5 G7 ^7 k& \1 M( b - QUEST.addStartNpc(7012)
7 M; Y9 C/ o8 y& ^8 D - QUEST.addStartNpc(7009)
E1 a) B" N8 ~+ P - QUEST.addStartNpc(7011)2 g' V& D; e9 L; i* \1 c2 h
- 7 D9 i; @* A6 j" s/ C9 }9 o- R
- STARTED.addQuestDrop(KELTIR_NPC_ID,FANGS_ITEM_ID,DROP_RATE)
k b! B3 Q4 p) _! a. S2 O - STARTED.addKillId(KELTIR_NPC_ID)) i- L }/ m- f# q
- STARTED.addTalkId(7056)
8 _: h$ ?7 q% D4 `" t7 B - STARTED.addTalkI d(7012)
2 E7 }4 s* p d" L: j: C - STARTED.addTalkId(7009)
9 a* ~) p3 X5 ?5 z7 ^# Q6 h2 H - STARTED.addTalkId(7011)
Скопировать код 5 v7 `" S( J" K9 W/ r; m/ I
* a* @- W' Z; G
|