Зарегистрируйтесь сейчас чтобы найти еще больше друзей, и получить полноценный доступ ко всем функциям сайта!
Для просмотра Вам необходимо авторизоваться Если Вы еще не зарегистрированы, перейдите по ссылке:Зарегистрироваться
x
Хроники Interlude
8 X7 b# U0 j6 NСборка L2j
) K' |8 e* |' P5 Y( Y$ I( ]Обратите внимание: в файле htm стартового NCP обязательно должна быть ссылка на квест:
* x: ]( `9 c8 J% t' P5 z( }- STARTED.addQuestDrop(KELTIR_NPC_ID,FANGS_ITEM_ID,DROP_RATE)
Скопировать код Для этого квеста больше ничего не надо. Все необходимое для корректной работы квеста уже добавили. Вот полный текст квеста:, `7 t7 s: u$ z- D6 Q) w" W
1 \$ u r2 Q* k$ g% u; v7 P1 m9 K- if getCount(st) >= 4 :4 D: N3 e3 H; ^$ O" g. l# T
- completed(st), }6 P) V; V; T. E
- return
$ B* w% N) Y2 O# k
8 K- y- `9 e" H- p- Z; @: Z# Z- class Quest (JQuest):
$ N0 x9 \* U9 y - def __init__(self,id,name,descr): JQuest.__init__(self,id,name,descr)( s' D7 @ _. O+ J/ g' O; u
- def onEvent (self,event,st):
2 c8 m, m, T, M - id = st.getState()- D [, ?+ d/ R% b3 ^
- if id == CREATED : st.setState(STARTED)
: g Y0 F0 ?/ E2 y1 r, u, h3 i - elif id == COMPLETED: pass
! E4 p8 _* T _ - elif id == STARTED : check(st)
( u4 c& ], Z; p - return
( R5 u, R+ C. v& k. Z2 a$ d - 6 s* C4 C2 |. u7 M0 n1 O Z
- QUEST = Quest(201,"Tutorial", "Tutorial quest")$ {6 p' x- v8 m' d$ c1 Q
- CREATED = State('Start', QUEST)
- Q! u5 b& F2 ?0 R) @" W& h - STARTED = State('Started', QUEST)
* o1 F: H1 Y3 P# q9 {& T9 ? - COMPLETED = State('Completed', QUEST); \' Q$ e0 f6 ^9 o% u
- f* D# G# q! E$ F- QUEST.setInitialState(CREATED)$ {3 l* \9 J( f/ d+ `
- QUEST.addStartNpc(7056)
, h5 a7 C4 N. k( M8 R - STARTED.addQuestDrop(KELTIR_NPC_ID,FANGS_ITEM_ID,DROP_RATE)
Скопировать код Теперь рассмотрим, как это работает.
8 ?+ B) R3 ^, H$ U+ x% aИгрок подходит к начальному NCP (в данном случае 7056), нажимает на «Quest». Квест будет создан и состояние квеста перейдет к CREATED и игроку будет показана страничка Start.htm с описанием квеста. Тогда метод onEvent, поле открытия странички Start.htm переведет состояние квеста в STARTED и игроку будет показана страничка Started.htm, где будет опсание того, как найти keltirs и .т.д., E' p7 {' y( Z
. B1 S. I) K: d! V# g8 h2 D0 @
" z$ K- s! o2 B5 H* B3 V3 U2 p- A" F
При состоянии STARTED будет зарегистрирован дроп «fangs» при убийстве keltirs. Игрок может вернуться к стартовому NCP и спросить о квесте – метод onEvent будет вызван снова. Если у игрока не хватает необходимого количества предметов, то метод check() не переведет квест в следующее состояние и Started.htm будет показана снова. Но если игрок собрал необходимее количество предметов (в данном случае 4 клыка), то метод check() вызовет метод completed() который переведет квест в новое состояние COMPLETED, заберет все клыки, даст карту мира, т.к. это награда за квест, покажет Completed.htm и завершит квест.
0 `6 B R3 x7 g7 B4 u3 t5 d4 a5 }; ?) P- J
7 _1 N& ]3 L8 C3 E) Y$ @; }! F8 |Теперь давайте сделаем наш квест более похожим на то, что он должен из себя представлять.3 A2 z* w, e+ Z3 s' u2 H+ \
Прежде всего у нас есть 3 метода для объявления их в Яве – onTalk, onKill и onEvent. Если методы onTalk и onKill не объявлены, то за них все будет делать метод onEvent, т.е. определять квестовых монстров и вызывать диалоги NCP. Есть примечание, методы onTalk и onKill будут вызывать только диалоги с NCP в зависимости от текущего состояния квеста. Метод onKill будет вызываться только тогда, когда мы убиваем квестового монстра.2 S' w0 t K1 ]! j: E
g7 y; E: }+ r$ }( ?
, `' H0 ]& B# o2 N' L. \+ O: ]
Давайте рассмотрим как вызывается метод onKill при убийстве keltir в состоянии квеста STARTED:3 L( }% N/ l3 I% `* C" P
- STARTED.addKillId(KELTIR_NPC_ID)
Скопировать код и метод onKill в классе Quest:9 H$ r( P) `- y8 o( ]
2 x! b1 q6 T9 P0 k* W
- class Quest (JQuest):/ P/ q6 U. C2 I
- ...
; a/ Y. \/ s$ H - def onKill (self,npcId,st):
- P- c o1 V. \' b - if npcId == KELTIR_NPC_ID:
9 S ?! J' J/ i& ?. m - n = getCount(st)' o; u7 v' l+ W
- if n == 0:7 L3 w# ]4 K! H: Q$ y8 p+ R! [
- return "Chat0.htm". y+ M1 m$ R6 {; [: {. m ^6 |+ m
- elif n == 1:6 n8 R: t7 ~1 I% V8 Y* m3 L
- return "Chat1.htm"+ n$ K* k% V' E4 ?, K
- elif n >= 4:: Q! q; Y: p1 j4 X
- return "Chat4.htm"
: a( l2 X! U: o: Q+ u$ |" ?) j - return "Collected "+str(n)+" of 4 fangs"- W+ w- E8 c5 z- B
- return
Скопировать код Метод onKill (а так же метод onTalk) имеет следующие параметры:
, e+ J3 z P4 D" ?; H- u, c: d8 ]
( S' k/ r( Q7 h+ r7 d8 K
• self – квест
2 f" n. i# k% ? U$ t0 D9 v. r' g5 i• npcId – ID NCP, которого мы должны убивать (если это метод onTalk, то ID того NCP, с которым мы должны поговорить).
5 f; i, m' W; o P ]* e• st – текущее состояние игрока.
( W+ C6 V# }0 g- c
+ O0 {4 g. g5 m, ?& V2 N) m+ S. k$ C% R' F
В этом методе мы проверяем и отмечаем, является ли убитый NCP keltir’ом. В основном эта проверка не нужна, т.к. у нас только KELTIR_NPC_ID.4 Z2 f3 ]1 w3 a9 ]
2 e: L2 ^3 D9 b$ |% q0 B# T1 ?* g3 h
& u+ F. b# K9 QЗатем проверяем количество предметов (в данном случае количество клыков), и если их вообще нет, то возвращаем строку "Chat0.htm", если только один предмет, то возвращаем строку "Chat1.htm", если же предметов 4 или больше, то "Chat4.htm". Если строка возвращена из методов onEvent, onKill или onTalk, то сервер покажет соответствующие htm. В Chat0.htm может иметь следующий текст: «Вы не имеете ни одного клыка, возвращайтесь позже, когда соберете 4 штуки и бла, бла, бла…», в Chat1.htm может быть следующий текст: «У Вас всего 1 клык, по этому соберите еще…». В Chat4.htm – «Вы собрали необходимое количество предметов, возвращайтесь к вашему тренеру, что бы завершить квест…»
( X& l) \: p* l' n5 J, E2 ~# b
: i: e L+ _9 S$ c# [9 w, N: G" J( a* X: v* u
Примечание: если в строка return начинается с "<html>", то будет показана страничка html с текстом, который стоит далее. Так вместо:% e, t2 z/ u z
return "Chat4.htm"6 M$ z, d4 z+ N" y$ |
& e1 h) f; `3 R: Q# `5 r
& R6 \: ]# x: v8 M6 Z( V tможно поставить:' S. F! O$ \0 k2 m$ o! U5 M i
- return "<html><body>Return to your trainer to complete the quest</body></html>"
Скопировать код Так же если строка заканчивается без .htm или в начале нет <html>, то текст будет выведен, как системное сообщение в окне чата. В нашем случае мы сделаем так, что бы при каждом убийстве keltik выводилось системное сообщение: «Собрано N из 4-х клыков».7 \- ~ J7 I, c
! @" @6 t2 i5 c4 O. g( c3 f
/ j) }1 m8 u/ N; mНаш код для onKill имеет один недостаток. Он будет постоянно показывать Chat0.htm, Chat1.htm и Chat4.htm, нам же необходимо, что бы Chat0.htm и Chat1.htm показывались только один раз. Как нам это сделать? С помощью переменных." _0 z: T7 {) g: h1 @
6 F1 A8 z" w- L: X o3 H1 R
2 \% ^( s5 h1 `В каждом квесте строки могут храниться с помощью переменных. Эти переменные сохраняются в Вашей БД. В каждом методе мы можем назначить, прочитать и удалить переменные. Давайте изменим метод onKill, так что бы каждый диалог вызывался только один раз.# X7 k/ K5 Q' Z: O3 ]# {
- def onKill (self,npcId,st):1 K; w( `8 B8 u/ S% W& T& O9 ]
- if npcId == KELTIR_NPC_ID:+ r% i2 A! B; A0 p* R+ X* f
- n = getCount(st)" u1 @* ^, X6 y' Y* q
- if n == 0:
# l1 A: \$ i& J/ r7 c - if st.get('chat0') == None :7 o$ m5 {2 P8 b$ u f: B: E& S; Y
- st.set("chat0", "true")
s5 r6 X) y P' D - return "Chat0.htm"
5 }. {- W# K1 r6 n m i - elif n == 1:; x3 l. `4 ~! V2 W5 A( T
- if st.get('chat1') == None :( {, @. m& s3 O0 _6 K
- st.set("chat1", "true")
9 }6 }2 L6 Z1 } z - return "Chat1.htm"
* `8 [' x1 V1 ]4 y - elif n >= 4:9 u% m* s) K' {
- return "Chat4.htm"
/ K# m/ Y/ k" Y) U# ^& @ - return "Collected "+str(n)+" of 4 fangs"
4 _ \: y9 q, J% S! V! v - return
Скопировать код Если у игрока нет клыков (n=0), то мы получаем занчение переменной 'chat0'. Когда метод onKill вызван в первый раз, то пока ни каких переменных не имеется и python возвращает значение None. В этом случае объявляется переменная и показывается диалог Chat0.htm. Когда мы убиваем keltir, но не получаем с него клык, функция st.get('chat0') возвращает строку true, а не None. И во второй раз окно с Chat0.htm не появится, но в окне чата появится строчка «Collected 0 of 4 fangs». По тому же принципу сделано и с Chat1.htm.) ^* ^: l" v! _) S$ X: X
4 W4 V9 s. v4 e3 d2 x
) D4 @5 u/ R2 O/ W+ p
Вот конечный рабочий вариант квеста:' j' r+ a0 `8 }( \1 {: F. a! ]
- import sys
5 Y. L9 z4 U6 i. B; j - from net.sf.l2j.gameserver.model.quest import State0 _1 ?7 @3 x9 D+ l8 V; |* F* s" ?
- from net.sf.l2j.gameserver.model.quest import QuestState8 ?1 Z; A* }4 B6 b" i) _
- from net.sf.l2j.gameserver.model.quest.jython import QuestJython as JQuest
' ]7 J7 ], Q: z8 {+ F4 u! r* x9 N7 } - ( j' b8 m: J* }* z: {6 ?, V2 D/ ^
- KELTIR_NPC_ID = 12082
& t2 C2 O, G* \1 f/ o: V6 X+ v - FANGS_ITEM_ID = 1859
' z, ~# U. {: [ - DROP_RATE = 500000; N6 a; Y+ d: O& u v3 L8 {4 u
- * t0 s4 B% _. a( u/ y; }$ Y" z
- WORLD_MAP_ITEM_ID = 1665
: ]! p" p# e3 }+ e- V - ; l* F5 _0 W' L2 D
- def getCount(st) :6 z) J! P5 w. k% Z3 q) [& ~
- return st.getQuestItemsCount(FANGS_ITEM_ID)- c, y; @! F7 i: p4 {
- / k$ e; O6 Y p3 I: n/ u3 `$ A" n8 |
- def completed(st) :5 V# E6 F1 b6 o) ^5 W
- st.setState(COMPLETED)
# ~$ C* o- ~+ ~. ^ - st.clearQuestDrops()
/ \* J+ {, e8 e) ]) P: k$ d - st.takeItems(FANGS_ITEM_ID,-1)
& o, ~+ C% e; F" r, {6 O: _ - st.giveItems(WORLD_MAP_ITEM_ID,1)
+ N9 _: T1 ~/ d! `- Q8 Z; R% ` - st.exitQuest(False)
9 Q2 Y- l' S% D+ K - return
$ L( D) ]* G5 X6 }' _0 y+ b- ^& ]" y/ \( u
4 f% D5 H1 {1 J) l- def check(st) :
5 `; [( Z% @% L1 i, w - if getCount(st) >= 4 :* B) H# S( P9 x k0 u* h
- completed(st)
( q* o8 ]- Q2 `( ~% Y3 ^ - return
' d, i" ?( r0 a5 J! L
" g! a1 e4 h8 K! b( G/ B- class Quest (JQuest):
( T2 S, {4 b) b0 V3 i4 c4 t - " ?6 M- ~; e. w5 O) D K/ C
- def __init__(self,id,name,descr): JQuest.__init__(self,id,name,descr) m, C5 M* ]# |- o! `( g8 x
- 1 ?& j% |) h: ^. ]- r# y* q
- def onEvent (self,event,st):+ _. Z, C* U) o0 @
- id = st.getState(), I& q- T: P0 W6 |$ L6 a3 j
- if id == CREATED : st.setState(STARTED)
2 Q% G& J. n) v8 c4 U( [ - elif id == COMPLETED: pass8 v% T6 `! Z) b8 |+ C
- elif id == STARTED : check(st)0 {) ^7 s7 w& f" C% Y, {
- return
4 o* t/ B+ Q& F" H% R1 e/ P5 ^ - . ?1 H5 Q3 j$ @5 W0 F
- def onKill (self,npcId,st):
* b/ |, c8 ?" V$ d5 t/ \2 @ - if npcId == KELTIR_NPC_ID:( I% B, v0 X, \+ ?3 o
- n = getCount(st)
" P- c4 E) z8 y% c R1 v - if n == 0:+ _" b$ a: L! E( i( m5 q. h( m
- if st.get('chat0') == None :
1 D Z! }. A# G5 H3 \4 | - st.set("chat0", "true")$ T3 A' J* P" D4 ?
- return "Chat0.htm"8 G$ }3 j& u( M
- elif n == 1:/ d" j T9 t8 |! Y
- if st.get('chat1') == None :
* x( T& [& }) C+ [% E5 L0 H - st.set("chat1", "true")/ x; P& K, a2 _ p/ }* n
- return "Chat1.htm" A0 Q& h \6 B
- elif n >= 4:
* u/ U# Z4 y# c7 S* R - return "Chat4.htm"$ x9 k5 l/ v# f( [# L* z. g
- return "Collect "+str(n)+" of 4 fangs"4 q' ]) k: c$ f
- return
+ `9 S/ z" R& l" [8 q/ `0 F - $ h9 C0 a' [& F7 |8 E0 _# ?; Q
- QUEST = Quest(201, "Tutorial", "Tutorial quest")
9 n8 E2 e3 n# I3 ?. ? - CREATED = State('Start', QUEST)% n: }2 M# ?) W7 b" T
- STARTED = State('Started', QUEST)
: a7 I4 ^& X. c* D) f Z) p6 u - COMPLETED = State('Completed', QUEST)
- z" j1 O8 d) j+ B7 D - * b( w% s! ^7 E) [1 y: H
- QUEST.setInitialState(CREATED)
# t& C3 {# @5 F4 j/ U) @ - QUEST.addStartNpc(7056)
# m( w5 L# _1 ?# I; z( f, V3 u - QUEST.addStartNpc(7012)
4 {" h" F+ L' b4 z/ ?' G7 C - QUEST.addStartNpc(7009)4 u$ v& v3 Z6 y, c* X! A* t9 C
- QUEST.addStartNpc(7011)
@( }) `0 a0 X' D: T
! M- Y; \- W% F; ?- STARTED.addQuestDrop(KELTIR_NPC_ID,FANGS_ITEM_ID,DROP_RATE)
) y0 Y$ S* k0 }/ g% s - STARTED.addKillId(KELTIR_NPC_ID)
2 m8 Q0 x- ~9 n, N- |. g! @ - STARTED.addTalkId(7056)
' R* `5 D& H6 @8 G, \0 h - STARTED.addTalkI d(7012); d5 k- c2 F7 k# o( K
- STARTED.addTalkId(7009)
: `% G6 Y- Q9 N: }% ~/ d+ f9 f - STARTED.addTalkId(7011)
Скопировать код
3 m2 `! L6 E# c+ Q9 W* W% Y$ }* D' I% ~# K& R& k4 t4 d# ]0 ^
|