Зарегистрируйтесь сейчас чтобы найти еще больше друзей, и получить полноценный доступ ко всем функциям сайта!
Для просмотра Вам необходимо авторизоваться Если Вы еще не зарегистрированы, перейдите по ссылке:Зарегистрироваться
x
Хроники Interlude. p* u4 E8 g1 {: J0 g# X
Сборка L2j
1 S2 u- A7 H0 q6 w Z) XОбратите внимание: в файле htm стартового NCP обязательно должна быть ссылка на квест:* _& F! C( _# D4 [/ ?
- STARTED.addQuestDrop(KELTIR_NPC_ID,FANGS_ITEM_ID,DROP_RATE)
Скопировать код Для этого квеста больше ничего не надо. Все необходимое для корректной работы квеста уже добавили. Вот полный текст квеста:" n& d% n ^8 W, w
' H1 x A+ V$ k D- if getCount(st) >= 4 :
, R+ E: C! P& t, Q! D7 w( M- h - completed(st) F& X, B2 f1 `
- return
; `( \1 `/ V6 I+ A
2 b2 \; O I( E, E- class Quest (JQuest):# A& Y2 Z+ }: L5 r
- def __init__(self,id,name,descr): JQuest.__init__(self,id,name,descr)
# |* Z. ]" j4 o/ o. b' C) d - def onEvent (self,event,st):" r$ G' m9 w+ t% _: X
- id = st.getState()0 S3 Q: V- [6 M: c- j7 ]
- if id == CREATED : st.setState(STARTED): S! w0 P, s% z5 s' f* V
- elif id == COMPLETED: pass) Y2 t7 O( g5 O: Y' N
- elif id == STARTED : check(st) i1 [: M' ?/ L, E( ?5 X1 {: b
- return( r0 d1 S! |! e: G! s% k
4 `$ E0 S' y+ S- Y! n% @! x- QUEST = Quest(201,"Tutorial", "Tutorial quest")& U2 ]4 Z5 D3 h' K9 {
- CREATED = State('Start', QUEST)( u0 L- p! K3 e
- STARTED = State('Started', QUEST); p. j4 f/ S4 I1 |) g
- COMPLETED = State('Completed', QUEST)
7 \( A. A' o0 `* U( M
1 H; r) ^) b* g* w3 n3 H2 q- QUEST.setInitialState(CREATED)
0 Y* i# I; b* V$ G$ _* z) T, V8 X - QUEST.addStartNpc(7056)
- W# Y2 @% L! g/ V5 [. K! t - STARTED.addQuestDrop(KELTIR_NPC_ID,FANGS_ITEM_ID,DROP_RATE)
Скопировать код Теперь рассмотрим, как это работает.
B$ C7 J% i3 G- {Игрок подходит к начальному NCP (в данном случае 7056), нажимает на «Quest». Квест будет создан и состояние квеста перейдет к CREATED и игроку будет показана страничка Start.htm с описанием квеста. Тогда метод onEvent, поле открытия странички Start.htm переведет состояние квеста в STARTED и игроку будет показана страничка Started.htm, где будет опсание того, как найти keltirs и .т.д.7 V) @! R, A8 u; X
5 d, E: F; F$ e: [: `0 ~
; V: l$ j3 d, h, {" I
При состоянии STARTED будет зарегистрирован дроп «fangs» при убийстве keltirs. Игрок может вернуться к стартовому NCP и спросить о квесте – метод onEvent будет вызван снова. Если у игрока не хватает необходимого количества предметов, то метод check() не переведет квест в следующее состояние и Started.htm будет показана снова. Но если игрок собрал необходимее количество предметов (в данном случае 4 клыка), то метод check() вызовет метод completed() который переведет квест в новое состояние COMPLETED, заберет все клыки, даст карту мира, т.к. это награда за квест, покажет Completed.htm и завершит квест./ c) h- _1 b& t4 O! d, i
; X2 _5 c9 Y1 o& } p6 ?0 e6 _# @0 G- m: \& |) E
Теперь давайте сделаем наш квест более похожим на то, что он должен из себя представлять.7 k- M A4 K. X, e9 `- i
Прежде всего у нас есть 3 метода для объявления их в Яве – onTalk, onKill и onEvent. Если методы onTalk и onKill не объявлены, то за них все будет делать метод onEvent, т.е. определять квестовых монстров и вызывать диалоги NCP. Есть примечание, методы onTalk и onKill будут вызывать только диалоги с NCP в зависимости от текущего состояния квеста. Метод onKill будет вызываться только тогда, когда мы убиваем квестового монстра.
# n h. [# ^9 f& f; [/ F* h/ g* R) P0 G$ F# M! ^4 I$ C; k: R
7 y/ B1 h+ a) Y" Z- A
Давайте рассмотрим как вызывается метод onKill при убийстве keltir в состоянии квеста STARTED:
7 `, I5 X3 \9 | B8 \* ~/ b3 g- STARTED.addKillId(KELTIR_NPC_ID)
Скопировать код и метод onKill в классе Quest:7 S1 ^5 w2 O* x2 @" f
( q r" m! D+ d) X3 E5 B" n
- class Quest (JQuest):/ V9 G) M1 I7 u: W! a; r- w+ h% Q/ x
- ... B0 L1 ^* L- Y
- def onKill (self,npcId,st):
' C5 S! G* g& d; n- X6 c+ q* x - if npcId == KELTIR_NPC_ID:+ X0 b9 o. v# y# a
- n = getCount(st)
( p$ ~3 A3 a4 u0 r0 N/ }9 v - if n == 0:$ l& X! R- R2 k, g
- return "Chat0.htm"
, q+ E4 h+ u6 O' T8 t6 F - elif n == 1:1 P; p6 @: A; x+ n3 U4 L
- return "Chat1.htm"
1 K F' {7 ?( `- z5 o5 N" ?6 a5 p - elif n >= 4:
! h# C# F; S- @ - return "Chat4.htm"0 `: n$ o7 H: g! U! J4 n* y' t
- return "Collected "+str(n)+" of 4 fangs"
$ T f% k B1 v1 b0 [* a - return
Скопировать код Метод onKill (а так же метод onTalk) имеет следующие параметры:
1 D' P. v! t% F& v* B- ~) W/ a0 E9 b
1 I& j, D/ W( A4 b2 p. L9 M) y
• self – квест+ X! b8 T1 r* E* j; d
• npcId – ID NCP, которого мы должны убивать (если это метод onTalk, то ID того NCP, с которым мы должны поговорить).& b/ |1 o4 d R, H! X
• st – текущее состояние игрока.
9 k {. a5 j1 H* |2 n( I# E. Q$ q I/ t7 o& l; ^
, |3 m4 q( h+ C- i% sВ этом методе мы проверяем и отмечаем, является ли убитый NCP keltir’ом. В основном эта проверка не нужна, т.к. у нас только KELTIR_NPC_ID.8 l1 T; s0 C- _( i- l
0 K$ r9 B3 D- d: ^2 {. O1 u* m( ?, k: @( R
Затем проверяем количество предметов (в данном случае количество клыков), и если их вообще нет, то возвращаем строку "Chat0.htm", если только один предмет, то возвращаем строку "Chat1.htm", если же предметов 4 или больше, то "Chat4.htm". Если строка возвращена из методов onEvent, onKill или onTalk, то сервер покажет соответствующие htm. В Chat0.htm может иметь следующий текст: «Вы не имеете ни одного клыка, возвращайтесь позже, когда соберете 4 штуки и бла, бла, бла…», в Chat1.htm может быть следующий текст: «У Вас всего 1 клык, по этому соберите еще…». В Chat4.htm – «Вы собрали необходимое количество предметов, возвращайтесь к вашему тренеру, что бы завершить квест…»
6 D3 y. `' n9 H+ d2 u* r' f. F _3 s/ u" P# A" I& Z+ n5 b$ y
L* n8 s' m, W4 @Примечание: если в строка return начинается с "<html>", то будет показана страничка html с текстом, который стоит далее. Так вместо:' e% M* \3 e! Z `
return "Chat4.htm"
& W u. f; \9 Y7 J- e
; o* D+ x5 m# @5 x
# U# a& f- j R Z. p) Dможно поставить:- A% `4 w/ I( ?/ u: C: r( ^
- return "<html><body>Return to your trainer to complete the quest</body></html>"
Скопировать код Так же если строка заканчивается без .htm или в начале нет <html>, то текст будет выведен, как системное сообщение в окне чата. В нашем случае мы сделаем так, что бы при каждом убийстве keltik выводилось системное сообщение: «Собрано N из 4-х клыков».
3 V, i8 g# _8 U! a7 H2 H3 e o u; I6 n0 ]
) R3 H6 w" b# ^7 c9 e( |% w$ }
Наш код для onKill имеет один недостаток. Он будет постоянно показывать Chat0.htm, Chat1.htm и Chat4.htm, нам же необходимо, что бы Chat0.htm и Chat1.htm показывались только один раз. Как нам это сделать? С помощью переменных.4 m- {2 a; h) a4 C l! c7 E. t. ^
" b; y& p; y* u9 U, W/ T7 N* s
2 x, _3 H9 ?$ y9 }$ [В каждом квесте строки могут храниться с помощью переменных. Эти переменные сохраняются в Вашей БД. В каждом методе мы можем назначить, прочитать и удалить переменные. Давайте изменим метод onKill, так что бы каждый диалог вызывался только один раз.7 B1 g- \( ~' V$ b- p2 N
- def onKill (self,npcId,st):
9 s' d5 I) m: T1 E0 a( S$ K; B# Z - if npcId == KELTIR_NPC_ID:
7 ^$ X8 @2 x3 O& q8 t - n = getCount(st)8 d+ C" _, p6 ^
- if n == 0:* t+ n% Q5 z1 D4 Y: f
- if st.get('chat0') == None :
' @( I. @4 l/ S3 \ - st.set("chat0", "true")
4 R( M# a7 S# a0 f1 l: \- b - return "Chat0.htm"
8 g+ d; m$ C+ N! v) i5 T3 I& b. P - elif n == 1:
( ^0 S) W* Z$ y - if st.get('chat1') == None :7 ~' g5 t) E) e2 I8 d3 }, H# q7 B
- st.set("chat1", "true")
+ u' q/ T% Y, V! a' ~ - return "Chat1.htm"
. L, J1 z" b7 }; U- A5 ` - elif n >= 4:
u1 k: D3 p+ A1 h$ C! _ C - return "Chat4.htm"7 v! {* U; p1 @ |
- return "Collected "+str(n)+" of 4 fangs") R% W; h1 A+ B
- return
Скопировать код Если у игрока нет клыков (n=0), то мы получаем занчение переменной 'chat0'. Когда метод onKill вызван в первый раз, то пока ни каких переменных не имеется и python возвращает значение None. В этом случае объявляется переменная и показывается диалог Chat0.htm. Когда мы убиваем keltir, но не получаем с него клык, функция st.get('chat0') возвращает строку true, а не None. И во второй раз окно с Chat0.htm не появится, но в окне чата появится строчка «Collected 0 of 4 fangs». По тому же принципу сделано и с Chat1.htm.
. F4 h0 B! p. h8 k( C$ j' {# h( d
/ O' A& z- }" J' N( { i# m
Вот конечный рабочий вариант квеста:2 F" |9 f- F% H M
- import sys9 z% U! n* w. ~( D1 K7 X
- from net.sf.l2j.gameserver.model.quest import State; @/ j$ l6 j* n" u S& l
- from net.sf.l2j.gameserver.model.quest import QuestState* N }3 L+ H+ m& K" k6 g6 E/ T1 Q
- from net.sf.l2j.gameserver.model.quest.jython import QuestJython as JQuest) z2 G' E, ~( O( p
" r: T. K) v. J/ q- KELTIR_NPC_ID = 12082$ L4 Y, w3 S, j1 m# x" T7 O
- FANGS_ITEM_ID = 1859; E2 I, U' o5 e7 X- i) d) f
- DROP_RATE = 500000* \& ]; S& O8 {) Z: C
- # L8 y' I+ W3 s7 p7 M) H8 T# }
- WORLD_MAP_ITEM_ID = 1665( v$ B! r+ d* Z! o9 h* d1 |
- 9 K1 h1 V4 b& G! a7 y
- def getCount(st) :
* Y. a" {9 d$ g4 h, x - return st.getQuestItemsCount(FANGS_ITEM_ID)& Y/ N4 R) F$ C
: W0 @9 |3 F& r/ s* J# K! c+ @- def completed(st) :6 s' S7 d/ B9 q+ [ K2 V+ J
- st.setState(COMPLETED)
9 ^! W! i! N6 V: P( U3 u - st.clearQuestDrops()
/ D. z' w% l! T9 H4 o4 E; ?; Q - st.takeItems(FANGS_ITEM_ID,-1)1 G& M' x! o1 J
- st.giveItems(WORLD_MAP_ITEM_ID,1)
+ t/ _5 h/ U1 m1 Y/ _0 e - st.exitQuest(False)
?; M, k0 j! m. c, t/ P - return
. j5 @0 S+ Q0 S% \4 e6 e - 2 H S1 q. a4 |- I& H2 @
- def check(st) :
; p7 D5 M% a: w" m: I# }& x0 w5 f - if getCount(st) >= 4 :8 N2 X2 p4 @; n9 M4 L
- completed(st)
$ w( ]$ {9 d7 J0 d/ z6 Y - return% D5 Z h, j# l0 ^. D9 z* a
/ K, K* {9 m& ? p b) e+ G9 ~- class Quest (JQuest):
: x9 u$ c* ~$ s& A. ]( C: D) |3 w; ]0 |
& p: {" i! g) h2 ]- def __init__(self,id,name,descr): JQuest.__init__(self,id,name,descr)
6 _7 L+ ]& G5 D' h% C
3 ~% |6 {% r* [5 f J4 c- def onEvent (self,event,st):9 Y- v7 v; `) ^+ @" {
- id = st.getState()
: l9 a2 e# \" v, ]$ |, Z - if id == CREATED : st.setState(STARTED)) T+ K/ g6 \( |2 U
- elif id == COMPLETED: pass9 K7 T0 Q3 S; c( o. B, ~. _
- elif id == STARTED : check(st)
9 g* c) k$ O. \; Y7 ?7 }1 B - return- c0 X3 r! g7 B i& @$ G& |/ y. }# w
# `0 F$ Y7 y) {2 F9 |- def onKill (self,npcId,st):1 u. \& t9 ~1 w( J
- if npcId == KELTIR_NPC_ID:
! o2 {( h9 w: O2 f+ n - n = getCount(st)2 y( y" i# z, V" a- y) }
- if n == 0:4 @6 B; j& E% T, c
- if st.get('chat0') == None :
- z/ A2 ?7 \: q - st.set("chat0", "true")
( O4 x& t1 @) m } - return "Chat0.htm"
4 D0 L; i8 Y& m - elif n == 1:
& }" F8 [5 L( Y2 `6 A n! O* X - if st.get('chat1') == None :
X0 U8 `8 _; z8 }7 I" L9 ^* v - st.set("chat1", "true")) ^6 y9 t% j% o$ {) L+ m2 p
- return "Chat1.htm"/ R$ o9 v3 Z& U) ~* Z! {
- elif n >= 4:: [: _8 T& X, D7 ?) `# ]
- return "Chat4.htm"
& j0 b7 w* J! {5 D: f& b$ i, R - return "Collect "+str(n)+" of 4 fangs"! \4 @! @- F: ^ L6 F
- return5 l# T9 _$ e4 T' _
' H1 R6 J. n9 q( N- QUEST = Quest(201, "Tutorial", "Tutorial quest")
/ w1 j; i- H, b, N8 L. f - CREATED = State('Start', QUEST)
% Z- q9 T/ H* h1 K- } - STARTED = State('Started', QUEST)
8 ]2 a9 a) _) e2 w% l: |$ A; v7 ^ - COMPLETED = State('Completed', QUEST)
]1 a0 c$ Q1 j7 R5 l- o; W7 f - ' j5 X4 N2 ` ^
- QUEST.setInitialState(CREATED)
" S) k7 d" s) \1 Z$ p - QUEST.addStartNpc(7056)
6 t/ A% c! j) T3 o6 J# N - QUEST.addStartNpc(7012)
3 D9 r: F* b, | - QUEST.addStartNpc(7009)
2 O/ I4 l, |. n4 f% Z% C - QUEST.addStartNpc(7011)* M. ~7 s$ |, q) ~: Q1 k
- . D+ i5 Z) e# C4 O7 |# m
- STARTED.addQuestDrop(KELTIR_NPC_ID,FANGS_ITEM_ID,DROP_RATE)
+ j2 a$ Y( W; v- C) r - STARTED.addKillId(KELTIR_NPC_ID)5 w4 [ }$ b; w8 t+ y! W
- STARTED.addTalkId(7056)3 `! r0 o( X8 A5 |7 Z
- STARTED.addTalkI d(7012)3 s% L- m: H) ^9 }9 @9 D
- STARTED.addTalkId(7009)
) S1 q' B% T' P) u( y0 K. z - STARTED.addTalkId(7011)
Скопировать код ( w9 V# V7 F7 K( B z
W' ^ m0 c6 X& z! s: l |