Зарегистрируйтесь сейчас чтобы найти еще больше друзей, и получить полноценный доступ ко всем функциям сайта!
Для просмотра Вам необходимо авторизоваться Если Вы еще не зарегистрированы, перейдите по ссылке:Зарегистрироваться
x
Хроники Interlude1 z7 i3 j% a, M- N. ~' i
Сборка L2j
2 a% X2 Q6 k2 b5 l# iОбратите внимание: в файле htm стартового NCP обязательно должна быть ссылка на квест:0 ]1 A) R, a$ d! E
- STARTED.addQuestDrop(KELTIR_NPC_ID,FANGS_ITEM_ID,DROP_RATE)
Скопировать код Для этого квеста больше ничего не надо. Все необходимое для корректной работы квеста уже добавили. Вот полный текст квеста: C. ^) u6 \: i- A* n, z
! x, X: C# c2 y* T9 c- [
- if getCount(st) >= 4 :
- [7 d* P+ W6 ?. L - completed(st)
& a7 U, } K% {% J- N9 S% c* v - return
) W& _% s" Z3 M7 U
z( ?' Z8 f- S6 U: N- class Quest (JQuest):9 b- l% T) y8 Y9 D8 L6 ^. e
- def __init__(self,id,name,descr): JQuest.__init__(self,id,name,descr)* e, S' `' j5 X
- def onEvent (self,event,st):) e) z$ b+ t$ q( {! _. B( L* [! J
- id = st.getState()+ J' r+ t1 t& H V( I
- if id == CREATED : st.setState(STARTED)
; w0 [ o g I- M p+ r8 P+ I - elif id == COMPLETED: pass2 r7 M* t/ }) R
- elif id == STARTED : check(st)
4 Y0 Q* ^: a3 |$ K" f. t0 l, m M - return& P" e' X& l9 C- Z H# ?- l
' G+ U2 f- l `% P- QUEST = Quest(201,"Tutorial", "Tutorial quest")
/ r) T: i" E [" ^$ B$ K - CREATED = State('Start', QUEST)6 V+ [9 h$ m! ?7 e! `
- STARTED = State('Started', QUEST)2 b" W; M# F& F/ n
- COMPLETED = State('Completed', QUEST); {2 l( Q5 }4 d! W
- 8 A7 m) L8 @8 R, \0 ?/ C
- QUEST.setInitialState(CREATED)0 q: R3 g. h& `# |1 P' ?, b4 h
- QUEST.addStartNpc(7056) i/ n/ H9 u3 f/ \( d
- STARTED.addQuestDrop(KELTIR_NPC_ID,FANGS_ITEM_ID,DROP_RATE)
Скопировать код Теперь рассмотрим, как это работает.
8 ^( s" c) `7 Y0 ]* ]4 a2 IИгрок подходит к начальному NCP (в данном случае 7056), нажимает на «Quest». Квест будет создан и состояние квеста перейдет к CREATED и игроку будет показана страничка Start.htm с описанием квеста. Тогда метод onEvent, поле открытия странички Start.htm переведет состояние квеста в STARTED и игроку будет показана страничка Started.htm, где будет опсание того, как найти keltirs и .т.д.
8 I3 a% h: p3 f# i/ N6 _1 M( f! ], Z7 Y( _; \; r L
+ }1 S( e$ E' `5 u5 ?. t0 f4 N" e
При состоянии STARTED будет зарегистрирован дроп «fangs» при убийстве keltirs. Игрок может вернуться к стартовому NCP и спросить о квесте – метод onEvent будет вызван снова. Если у игрока не хватает необходимого количества предметов, то метод check() не переведет квест в следующее состояние и Started.htm будет показана снова. Но если игрок собрал необходимее количество предметов (в данном случае 4 клыка), то метод check() вызовет метод completed() который переведет квест в новое состояние COMPLETED, заберет все клыки, даст карту мира, т.к. это награда за квест, покажет Completed.htm и завершит квест./ W" l" a) |1 Z2 w
, x; E. _* h% H. I& G( m. X
* F0 a+ k! |7 u9 K7 N. PТеперь давайте сделаем наш квест более похожим на то, что он должен из себя представлять.
1 ?$ y5 o3 g! D3 S3 D; YПрежде всего у нас есть 3 метода для объявления их в Яве – onTalk, onKill и onEvent. Если методы onTalk и onKill не объявлены, то за них все будет делать метод onEvent, т.е. определять квестовых монстров и вызывать диалоги NCP. Есть примечание, методы onTalk и onKill будут вызывать только диалоги с NCP в зависимости от текущего состояния квеста. Метод onKill будет вызываться только тогда, когда мы убиваем квестового монстра.
/ Y6 f' ]* f+ \1 c$ ]# a+ }! u& w7 w9 ]' x
* Z0 X- K( v9 z7 X0 e: ^
Давайте рассмотрим как вызывается метод onKill при убийстве keltir в состоянии квеста STARTED:
: C& B) u& F9 Y& x/ z$ _" w5 e- STARTED.addKillId(KELTIR_NPC_ID)
Скопировать код и метод onKill в классе Quest:1 {2 H6 b8 k4 ]0 A- b
( h+ w% g/ F/ L! {1 [% ]7 I- class Quest (JQuest):8 z. W. w/ i z3 Y
- ...; Y; E4 T2 c: i9 e& U/ z: w
- def onKill (self,npcId,st):
8 ^; R2 R6 N" e6 \6 t) C - if npcId == KELTIR_NPC_ID:
; W$ K6 f+ K; v) f( L, K - n = getCount(st)% W2 h5 M6 P+ ?/ e! Y3 ^0 @4 P
- if n == 0:
2 e/ l1 h$ G! b, B& Y - return "Chat0.htm"+ b9 _! F1 ^9 F; W, d8 i& @7 g( l
- elif n == 1:8 I/ `. l. M$ K- p5 g, H1 b7 p
- return "Chat1.htm": e) x6 D1 r! ^
- elif n >= 4:& F2 p7 Y* v& e/ q0 P- R% e
- return "Chat4.htm"7 J6 q5 h) V2 u9 ]. l3 R
- return "Collected "+str(n)+" of 4 fangs"
% w$ G2 f2 d" F9 Q; ` - return
Скопировать код Метод onKill (а так же метод onTalk) имеет следующие параметры:, n6 ]+ l! t7 u0 u5 P8 u. Z
. ]) i9 A' T+ D$ ~- h' ~
, M+ e8 B, z; {" \" ?5 ^( }5 X• self – квест- o- x9 a* r* B) t3 `' d: U
• npcId – ID NCP, которого мы должны убивать (если это метод onTalk, то ID того NCP, с которым мы должны поговорить).( f! h( { H; G
• st – текущее состояние игрока.
1 `3 d% k: O4 L5 \
( z! L6 u+ R- C8 d: A1 v
: h% H; h6 o5 ^4 S8 AВ этом методе мы проверяем и отмечаем, является ли убитый NCP keltir’ом. В основном эта проверка не нужна, т.к. у нас только KELTIR_NPC_ID.
8 h0 o2 i. G' u: n! }% R9 R: x1 C4 l+ P+ T
6 i: I, }, [. t+ I7 w( i q7 R
Затем проверяем количество предметов (в данном случае количество клыков), и если их вообще нет, то возвращаем строку "Chat0.htm", если только один предмет, то возвращаем строку "Chat1.htm", если же предметов 4 или больше, то "Chat4.htm". Если строка возвращена из методов onEvent, onKill или onTalk, то сервер покажет соответствующие htm. В Chat0.htm может иметь следующий текст: «Вы не имеете ни одного клыка, возвращайтесь позже, когда соберете 4 штуки и бла, бла, бла…», в Chat1.htm может быть следующий текст: «У Вас всего 1 клык, по этому соберите еще…». В Chat4.htm – «Вы собрали необходимое количество предметов, возвращайтесь к вашему тренеру, что бы завершить квест…»
& G- I( A+ q8 W' x
% [/ G. U1 P2 j/ q, [/ x G0 L) h2 n( L. g
Примечание: если в строка return начинается с "<html>", то будет показана страничка html с текстом, который стоит далее. Так вместо:' I, ]8 T% m9 F- _
return "Chat4.htm"
1 D) F" @. k+ |6 ]+ ]+ d' K0 Q: F1 i* j0 J8 i
6 O+ W, a7 S$ s. Z! Nможно поставить:
: E: _/ d. y" W4 H% Z+ X6 N" u, S- return "<html><body>Return to your trainer to complete the quest</body></html>"
Скопировать код Так же если строка заканчивается без .htm или в начале нет <html>, то текст будет выведен, как системное сообщение в окне чата. В нашем случае мы сделаем так, что бы при каждом убийстве keltik выводилось системное сообщение: «Собрано N из 4-х клыков».4 M0 b* I0 n4 @ C9 f2 G9 V
X" h/ J) N2 l+ P* f
- B- B: ?1 E3 r; p# H4 U! ^: FНаш код для onKill имеет один недостаток. Он будет постоянно показывать Chat0.htm, Chat1.htm и Chat4.htm, нам же необходимо, что бы Chat0.htm и Chat1.htm показывались только один раз. Как нам это сделать? С помощью переменных./ i d# v1 D# q3 \' x0 U
/ v. g& b4 q" `7 g0 ]$ u# R; M v
: |* x$ z5 T) C) C/ L
В каждом квесте строки могут храниться с помощью переменных. Эти переменные сохраняются в Вашей БД. В каждом методе мы можем назначить, прочитать и удалить переменные. Давайте изменим метод onKill, так что бы каждый диалог вызывался только один раз. v2 f! b$ v1 E6 [9 s1 E' |7 ^' m
- def onKill (self,npcId,st):
8 e/ q$ l0 B* w& v0 A' X% J - if npcId == KELTIR_NPC_ID:
# T4 A) s5 p3 j2 d - n = getCount(st)
9 I" v% a: W$ s u$ ^' H - if n == 0:' ~' S' q4 ] ~ a) V- F4 E% j' F
- if st.get('chat0') == None :
' v# ^4 X0 T) p - st.set("chat0", "true")+ T6 t0 C$ A; {# c4 b
- return "Chat0.htm" h( m! A) E" X
- elif n == 1:
5 I& o- c: m( x$ ?% K! [ - if st.get('chat1') == None :# d, b% i9 c$ @. n+ V8 U$ C* `! N
- st.set("chat1", "true")$ @4 }- l/ l* L: L- u, h( \
- return "Chat1.htm"
9 h# S- n9 o3 ]9 r - elif n >= 4:
3 C& n" i1 j, I7 c5 [2 M4 l- b: h$ Y - return "Chat4.htm"2 m: Y- j7 v& R7 t
- return "Collected "+str(n)+" of 4 fangs"
; |8 [# T4 D% p0 @$ ~ - return
Скопировать код Если у игрока нет клыков (n=0), то мы получаем занчение переменной 'chat0'. Когда метод onKill вызван в первый раз, то пока ни каких переменных не имеется и python возвращает значение None. В этом случае объявляется переменная и показывается диалог Chat0.htm. Когда мы убиваем keltir, но не получаем с него клык, функция st.get('chat0') возвращает строку true, а не None. И во второй раз окно с Chat0.htm не появится, но в окне чата появится строчка «Collected 0 of 4 fangs». По тому же принципу сделано и с Chat1.htm. P# t4 b! S9 j, M9 G
$ w1 _) l2 ?/ {3 p9 r% @. X2 I
9 ~ I) T& s4 w6 G m7 z5 w. a9 x/ o% m
Вот конечный рабочий вариант квеста:% h" ~5 e" \4 U" W
- import sys! ~- y/ K) b* J" ]9 ^
- from net.sf.l2j.gameserver.model.quest import State; o( Z) _" O9 {/ C; u5 D: c: R. i
- from net.sf.l2j.gameserver.model.quest import QuestState6 F0 w+ t) H |- ?4 L; Y) r. r& ?
- from net.sf.l2j.gameserver.model.quest.jython import QuestJython as JQuest
- W: p, Z% P9 ~( h - , [0 S, x) ^1 O5 i0 g! u3 L4 z5 o
- KELTIR_NPC_ID = 120826 d/ F: w) g& ^! T
- FANGS_ITEM_ID = 1859+ ?5 Y$ H- v7 J
- DROP_RATE = 500000; X& Q6 D! A, d+ z6 q
+ {( D% D Q* c3 o( [- Y, B- WORLD_MAP_ITEM_ID = 1665! r$ P1 L$ |& M/ O4 i
' T# Q3 B8 N( M: L- def getCount(st) :7 j0 S2 |! o5 f# Y4 \
- return st.getQuestItemsCount(FANGS_ITEM_ID); E! I* C) e7 h# V
- % s+ R+ M% M6 A* k
- def completed(st) :
2 y& l- R: W+ P# |3 z# o3 q - st.setState(COMPLETED)
2 `, T4 C, d, d7 j% r - st.clearQuestDrops()7 T8 f# O* E, L" W
- st.takeItems(FANGS_ITEM_ID,-1)% R6 c. @6 s; n1 u: w
- st.giveItems(WORLD_MAP_ITEM_ID,1)
3 w2 i% R' ]0 o - st.exitQuest(False)5 j, x B1 K; B6 }3 l5 ?3 t9 z, B
- return
& ^2 O2 G/ W3 ]- z
* `; N8 `* S1 y* p" y5 k- def check(st) :$ L! U, o1 _% ~# W# U8 H
- if getCount(st) >= 4 :! }. C# k8 ?- W$ L6 b
- completed(st)
- H! C" x3 [* h) v0 v - return, O, U- |& c |3 j% j
) V" m/ b$ h; Y5 u; q) c- class Quest (JQuest):
/ w) ^6 V# L& N' G2 k0 x) } - % Q/ _$ ~/ a% p* o: ?- V1 G. r
- def __init__(self,id,name,descr): JQuest.__init__(self,id,name,descr)
: f, h/ l# w& [6 r q - 2 I" p; n# G" d$ U; Z4 H# y
- def onEvent (self,event,st):8 t* i) Z1 ~& _8 j, d* b, |
- id = st.getState(). O; Q. t( h9 \& ?
- if id == CREATED : st.setState(STARTED)
' b* J( T& E5 I/ g1 Q9 f# d2 [ - elif id == COMPLETED: pass* b" _+ b" J5 S, F+ T
- elif id == STARTED : check(st)
7 l+ e1 V) M0 L2 g6 a- l; B6 s - return
$ P$ @7 S8 W* V6 H - ) Q: b* h: \# D4 h' |2 ~$ r2 I
- def onKill (self,npcId,st):9 U8 S$ z2 }3 I* o! ]+ p
- if npcId == KELTIR_NPC_ID:8 u" u& L2 j) ]) C ]% z! W
- n = getCount(st)$ r, ?/ V# s- Y1 o' p
- if n == 0:
" ^' k, W6 z. F+ W# D - if st.get('chat0') == None :! X' s+ G5 w+ J# }2 Q& d/ P' H" x4 U
- st.set("chat0", "true")% S( G% `& x9 Q5 e' C' S8 ]0 x
- return "Chat0.htm"& M6 I- r9 [' g, W" `; K( |4 u4 i
- elif n == 1:& Q/ q5 M# W9 O
- if st.get('chat1') == None :9 j# y, r5 ^4 n* j. G
- st.set("chat1", "true")
. N& j6 R% N% J1 U$ e; \, e - return "Chat1.htm"
% Y H' z3 c3 l; I) S- |9 n" N - elif n >= 4:
$ W) ]4 C; Q4 v8 A' @1 P' a( O - return "Chat4.htm"8 d9 S c1 r/ g# u8 s: _
- return "Collect "+str(n)+" of 4 fangs"
, k# `9 w6 Z! L4 n7 q; u - return
2 N: P. ]2 |! R$ p d( R2 t - 9 D! X6 l- t7 G1 K9 ]8 R
- QUEST = Quest(201, "Tutorial", "Tutorial quest")9 ]- G" B! { B6 j; K( u3 T
- CREATED = State('Start', QUEST)' w- N+ @7 F; m6 U2 A a. i" h$ d
- STARTED = State('Started', QUEST)
/ U! ]1 b* p0 c1 v ^/ v, j& C - COMPLETED = State('Completed', QUEST)
' O$ ~* B: G5 I- G U2 l6 p - 7 h, h5 p' D' ~: s
- QUEST.setInitialState(CREATED)
+ |& [6 y$ o6 ~) q% h - QUEST.addStartNpc(7056)# f, R1 r) C! x& n1 Z) l
- QUEST.addStartNpc(7012)
+ c$ k0 I( W* e- y- E2 h2 E - QUEST.addStartNpc(7009)
$ c8 Y3 f2 P2 l! {1 V7 P - QUEST.addStartNpc(7011). X1 C9 ~6 V4 i1 o7 D2 g
- 5 k) ~ b F0 k8 @7 j
- STARTED.addQuestDrop(KELTIR_NPC_ID,FANGS_ITEM_ID,DROP_RATE)( |# b) t; h' H+ G
- STARTED.addKillId(KELTIR_NPC_ID)
7 ~% c; ^- O( _2 h" t& v& Y- j- y - STARTED.addTalkId(7056)
( J7 n: H( B. \8 `" U - STARTED.addTalkI d(7012)
1 O% @$ s! l2 O* Q1 V9 @& B - STARTED.addTalkId(7009)
# Y7 y3 D1 p. k( E/ G! W - STARTED.addTalkId(7011)
Скопировать код
1 r1 ]" v8 `3 F7 I* p, n& k8 I( m, s" b2 c# j9 o, B: s& v
|