Зарегистрируйтесь сейчас чтобы найти еще больше друзей, и получить полноценный доступ ко всем функциям сайта!
Для просмотра Вам необходимо авторизоваться Если Вы еще не зарегистрированы, перейдите по ссылке:Зарегистрироваться
x
Хроники Interlude, t9 ]. f: K" Y' p( C' D/ ]; c% H$ G
Сборка L2j
0 g; Q# d4 `. LОбратите внимание: в файле htm стартового NCP обязательно должна быть ссылка на квест:
2 `0 U4 ~/ ~8 p& F7 F! F" q0 ~; z# g- STARTED.addQuestDrop(KELTIR_NPC_ID,FANGS_ITEM_ID,DROP_RATE)
Скопировать код Для этого квеста больше ничего не надо. Все необходимое для корректной работы квеста уже добавили. Вот полный текст квеста:
6 N7 W8 n* m+ u" h! {
: k# j, t0 Q' e5 w; N2 Y. ~0 O- if getCount(st) >= 4 :8 @, \; I/ Z4 C' r e# H9 E6 m
- completed(st)
0 x. G* T1 O6 Z) \( I/ c+ e - return
8 Q5 C1 J1 Z+ ~ O
$ E% A. G1 Y! z( w. k+ }- class Quest (JQuest):* B* f) g' O7 I, |2 M2 ~
- def __init__(self,id,name,descr): JQuest.__init__(self,id,name,descr)$ q/ a( h9 y2 V( M9 c
- def onEvent (self,event,st):! Y0 J- b& X# R$ x* {
- id = st.getState()1 `$ \5 A; l4 ~7 _# y( R. M. n
- if id == CREATED : st.setState(STARTED)
& P* v3 a F" S6 u) |4 o: C- p6 l, b - elif id == COMPLETED: pass5 C* u% I. w: v% X% e$ Y
- elif id == STARTED : check(st)
& Z# J ~; C7 J, |! M* R - return9 k. K# J+ e1 P
- 4 f2 ^3 R+ @6 I0 G
- QUEST = Quest(201,"Tutorial", "Tutorial quest")
' {- |! g$ Q& @# p0 o% O - CREATED = State('Start', QUEST)
$ F: o7 `" U8 @* r9 s* M% c, q& f0 S - STARTED = State('Started', QUEST)$ w+ U2 Y4 @; R& N: K
- COMPLETED = State('Completed', QUEST): i! S7 \8 D, ?' U
1 `& |+ x, S& s- R- QUEST.setInitialState(CREATED)
8 t" F& B$ j4 ?: T - QUEST.addStartNpc(7056) @/ \8 `3 W& X: \$ b9 U! A
- STARTED.addQuestDrop(KELTIR_NPC_ID,FANGS_ITEM_ID,DROP_RATE)
Скопировать код Теперь рассмотрим, как это работает.
4 \6 q3 Y) e/ N* [Игрок подходит к начальному NCP (в данном случае 7056), нажимает на «Quest». Квест будет создан и состояние квеста перейдет к CREATED и игроку будет показана страничка Start.htm с описанием квеста. Тогда метод onEvent, поле открытия странички Start.htm переведет состояние квеста в STARTED и игроку будет показана страничка Started.htm, где будет опсание того, как найти keltirs и .т.д.8 E8 b- y M+ c5 I( @
+ V9 D4 R# o( m5 B' e! j
0 a! c2 c. G# k+ @При состоянии STARTED будет зарегистрирован дроп «fangs» при убийстве keltirs. Игрок может вернуться к стартовому NCP и спросить о квесте – метод onEvent будет вызван снова. Если у игрока не хватает необходимого количества предметов, то метод check() не переведет квест в следующее состояние и Started.htm будет показана снова. Но если игрок собрал необходимее количество предметов (в данном случае 4 клыка), то метод check() вызовет метод completed() который переведет квест в новое состояние COMPLETED, заберет все клыки, даст карту мира, т.к. это награда за квест, покажет Completed.htm и завершит квест.
6 N. Q0 o6 p, `) i. Q H4 a, B" t" O: Q; a
N3 A$ Q8 q, R% [
Теперь давайте сделаем наш квест более похожим на то, что он должен из себя представлять. w* H% M. F* E5 @8 q* D* M, c3 ~- f
Прежде всего у нас есть 3 метода для объявления их в Яве – onTalk, onKill и onEvent. Если методы onTalk и onKill не объявлены, то за них все будет делать метод onEvent, т.е. определять квестовых монстров и вызывать диалоги NCP. Есть примечание, методы onTalk и onKill будут вызывать только диалоги с NCP в зависимости от текущего состояния квеста. Метод onKill будет вызываться только тогда, когда мы убиваем квестового монстра.
. X; n# W. C! X. S+ Z! z3 B
) x- t" C( Q, U1 E% d
8 B. w! C& ~2 i2 f+ q8 @$ [; HДавайте рассмотрим как вызывается метод onKill при убийстве keltir в состоянии квеста STARTED:
T% w& e# ?; R0 g7 y- STARTED.addKillId(KELTIR_NPC_ID)
Скопировать код и метод onKill в классе Quest:
. I$ J6 w9 Y5 R% B. M6 O, ?6 @5 Y! y0 ^
- class Quest (JQuest):2 g$ b$ F9 A. Y
- ...
! _3 T: \9 y4 U0 q - def onKill (self,npcId,st):3 Q9 s* U1 D. V
- if npcId == KELTIR_NPC_ID:
* H. J0 X; f$ r0 ^ - n = getCount(st)) S0 x. R, i z. n/ c! p& m
- if n == 0:
0 x- ]( ]7 I/ H+ Y1 _6 u9 _0 b8 O - return "Chat0.htm"
. a' d P. q: B - elif n == 1:, l- x3 B4 S2 l/ k" Q9 T: d
- return "Chat1.htm"
" z9 _' e* a4 F" {9 Y$ a) ]2 R! D - elif n >= 4:$ f5 N2 m5 s( q; ]8 [
- return "Chat4.htm"0 M# \- j5 k/ t
- return "Collected "+str(n)+" of 4 fangs"
5 x Y- X8 e y0 k5 k, E8 g) q - return
Скопировать код Метод onKill (а так же метод onTalk) имеет следующие параметры:
w- Q: u8 h. |" ^& N1 C, f: L6 L i: ?% X5 _! D. Q
- b/ |5 l1 H6 K) E8 g
• self – квест' d, I& _6 @% I* t, y2 w
• npcId – ID NCP, которого мы должны убивать (если это метод onTalk, то ID того NCP, с которым мы должны поговорить). S! a+ Y. @2 \) X4 X) F
• st – текущее состояние игрока.$ M- @1 x$ c+ K5 A& Q( K! l( @& }
# y1 H$ f0 Z# U% H% a6 u
+ B( _( l3 _% u. p* T8 IВ этом методе мы проверяем и отмечаем, является ли убитый NCP keltir’ом. В основном эта проверка не нужна, т.к. у нас только KELTIR_NPC_ID.: O+ x6 E; h# z. W6 f# [* z; N$ [
" F* d* L& L$ A5 T% b, n$ p
6 t S. ]. C; }; ]/ g- BЗатем проверяем количество предметов (в данном случае количество клыков), и если их вообще нет, то возвращаем строку "Chat0.htm", если только один предмет, то возвращаем строку "Chat1.htm", если же предметов 4 или больше, то "Chat4.htm". Если строка возвращена из методов onEvent, onKill или onTalk, то сервер покажет соответствующие htm. В Chat0.htm может иметь следующий текст: «Вы не имеете ни одного клыка, возвращайтесь позже, когда соберете 4 штуки и бла, бла, бла…», в Chat1.htm может быть следующий текст: «У Вас всего 1 клык, по этому соберите еще…». В Chat4.htm – «Вы собрали необходимое количество предметов, возвращайтесь к вашему тренеру, что бы завершить квест…»9 K+ `% n# b7 L, z; [
' L5 z' `4 B* x( @+ R1 R3 j2 F- E2 F5 B; @# q# u$ }1 N/ p* X
Примечание: если в строка return начинается с "<html>", то будет показана страничка html с текстом, который стоит далее. Так вместо:
" t6 B$ I# z. b! Yreturn "Chat4.htm"7 x+ a# B) d3 U; b$ i& D
1 I. C" j- Q$ C* J \7 t' {: n
1 A% T B' C8 f0 E; y# H
можно поставить:) O, {; K$ z! `5 V' _% X h
- return "<html><body>Return to your trainer to complete the quest</body></html>"
Скопировать код Так же если строка заканчивается без .htm или в начале нет <html>, то текст будет выведен, как системное сообщение в окне чата. В нашем случае мы сделаем так, что бы при каждом убийстве keltik выводилось системное сообщение: «Собрано N из 4-х клыков»./ J' I$ @& m2 y5 J
9 G/ L. T( Q5 C% U, s
9 |2 ?& l& X# S& z+ D8 b2 P4 S1 K. \
Наш код для onKill имеет один недостаток. Он будет постоянно показывать Chat0.htm, Chat1.htm и Chat4.htm, нам же необходимо, что бы Chat0.htm и Chat1.htm показывались только один раз. Как нам это сделать? С помощью переменных., Z: C, P' A }0 n8 U0 o* b! h
# L5 e" ~! \5 H8 g: V) R @' M( y' |: F, r
В каждом квесте строки могут храниться с помощью переменных. Эти переменные сохраняются в Вашей БД. В каждом методе мы можем назначить, прочитать и удалить переменные. Давайте изменим метод onKill, так что бы каждый диалог вызывался только один раз., @0 b/ Q& z: ^1 ~) F( o
- def onKill (self,npcId,st):
3 y( R7 G* c6 y6 j; x& E - if npcId == KELTIR_NPC_ID:
) @1 N8 _4 p, E. F, Y0 w! z& x - n = getCount(st)
+ P5 ^5 S5 w% w - if n == 0:7 A+ I, \# x" {9 r$ e
- if st.get('chat0') == None :
" O/ K2 {( \' i - st.set("chat0", "true")
, { q8 _2 l: A8 P) h - return "Chat0.htm"1 ]. r+ z" i3 b# S8 \1 R A& |
- elif n == 1:
% o8 L) f3 n6 y# s( j - if st.get('chat1') == None :$ Z" D/ u2 T7 X9 o0 b
- st.set("chat1", "true")7 K: z$ _; d/ a S) g/ H! b
- return "Chat1.htm"
- x0 S: s8 P: p0 `; m2 c9 v3 v/ }+ a - elif n >= 4:
1 x- f# G; r8 v8 ]* Z, R& f - return "Chat4.htm"
6 [8 ~' ]( y1 |9 R" e - return "Collected "+str(n)+" of 4 fangs" M+ q6 H- _0 N5 n! D$ 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.7 Z! H" W; E: P( U3 {% i. v
+ _" N$ [. X, p
+ p6 e# W1 r9 V c& @. j/ yВот конечный рабочий вариант квеста:
0 e& T7 r' D1 A+ T5 P- }" F, m- import sys
w' X) Y/ q* S& j1 G8 Q2 { - from net.sf.l2j.gameserver.model.quest import State
2 R) K& g. {6 Z" X# l5 a4 Q4 d - from net.sf.l2j.gameserver.model.quest import QuestState
" n& z3 Y. F. F7 e& `, }; T - from net.sf.l2j.gameserver.model.quest.jython import QuestJython as JQuest
5 D5 k6 K! g. v* ?9 h# S/ H! E - - P3 Z6 p8 g% v# i
- KELTIR_NPC_ID = 12082' q. Y. K7 P. j4 H6 ]7 K9 j
- FANGS_ITEM_ID = 18599 G) ], m# { [4 T
- DROP_RATE = 500000
$ W8 ^: N) t$ z4 F# @
" l. x$ R' Z5 y6 Y- WORLD_MAP_ITEM_ID = 1665
1 h p2 w( U) `" Z8 Z
& w5 b" U6 j: A, `% R- v- def getCount(st) :3 |5 E# {4 H& [. V- b5 i
- return st.getQuestItemsCount(FANGS_ITEM_ID)
5 P. Q/ x/ F- g: M2 a
. Y9 Y2 `) b* I- def completed(st) :
/ {2 ^ V {' |; K. u - st.setState(COMPLETED)
3 _' |: J* r& n4 h/ o' o - st.clearQuestDrops()
7 \, m- {; n- x0 p9 C - st.takeItems(FANGS_ITEM_ID,-1)7 I% X; D/ B$ x' e& P
- st.giveItems(WORLD_MAP_ITEM_ID,1)- M0 j+ q( Z. X
- st.exitQuest(False)
! B& d' c- r: }+ c5 @0 w - return
8 C- P2 k" G7 {- }
- ]! S* \ d2 e3 G% j- def check(st) :
1 @3 C+ A5 h6 ~! w0 x/ X4 q3 d& V - if getCount(st) >= 4 :* Q0 _, @( [" B/ f' C& k8 Z( K
- completed(st)
8 R1 D% E6 z8 O- B - return
1 Y+ ?! U" y/ y8 f( N* |" k1 V - 5 R* P O( S: R- f; A9 e$ N5 c
- class Quest (JQuest):- `+ e# g3 M e3 {; f$ ?+ K
- 1 p2 ~& Z7 f9 e! E5 o5 c1 E% V
- def __init__(self,id,name,descr): JQuest.__init__(self,id,name,descr)+ O( k) B2 i7 X" p) `
; [; k% ?! p3 [- def onEvent (self,event,st):) S l8 d3 ^ @( h5 v6 Z- g
- id = st.getState()
; L6 ^" V0 `0 G$ R - if id == CREATED : st.setState(STARTED)& T3 N! |% D) p) r; X( }
- elif id == COMPLETED: pass5 u2 x7 e3 I# S& F5 p F. p# k
- elif id == STARTED : check(st), t7 r) k ]5 z0 y5 n8 n0 Q
- return V$ X; e' J: `1 e& T3 z+ d
$ m+ {% i$ U9 \2 u5 A: J- def onKill (self,npcId,st):# l1 u# V7 r& v( g7 ^# B4 V
- if npcId == KELTIR_NPC_ID:) e2 f p, W E& x* Q# s/ F
- n = getCount(st)
; F0 m, w5 `. W) X! i! A/ \( G( v - if n == 0:) @+ F# D( z, i1 i
- if st.get('chat0') == None :
) ?" s" ~: F- Z$ C7 D - st.set("chat0", "true")
8 W$ V6 |% _, X" J* c - return "Chat0.htm"
, l% C% Y/ L2 c5 e- L* L4 G - elif n == 1:
. \( Z+ M7 R8 y" R6 |5 @; w - if st.get('chat1') == None :% ~4 j& F5 N# Z6 Z2 b: W
- st.set("chat1", "true")
/ y; M7 F: P+ A! ^# o9 W3 f - return "Chat1.htm"
8 Z4 U- P1 [& k4 c5 r - elif n >= 4:3 v. G. h0 W4 F9 P
- return "Chat4.htm"6 `4 ]( A, y+ F4 I7 M$ A- R8 ~
- return "Collect "+str(n)+" of 4 fangs"
+ B; h7 F+ I6 j$ s- @8 P) m: }3 I! Y - return0 U' L7 @9 o, R8 n- c' B6 A3 `. P
- ( a E) k% ~1 i
- QUEST = Quest(201, "Tutorial", "Tutorial quest")
$ g6 w, H2 F/ b( [6 ?1 f& P - CREATED = State('Start', QUEST)
( }2 Z u2 N: N1 ^ - STARTED = State('Started', QUEST)% D- ^; P T e% \0 z0 o
- COMPLETED = State('Completed', QUEST)* n, f& b9 D: M
- ) G" U7 K! b- @( q# N
- QUEST.setInitialState(CREATED)) k; M1 m, }* @" I `; A
- QUEST.addStartNpc(7056)/ j' h9 j5 Y0 h% E" [
- QUEST.addStartNpc(7012), D: Y( `7 W! h% E! T7 ~- X
- QUEST.addStartNpc(7009)2 G8 \% m+ ]! w6 \
- QUEST.addStartNpc(7011)0 t+ |- |+ b+ G0 E3 B, d# \
8 W4 Z* t8 W+ d5 L) p! I# b5 o- STARTED.addQuestDrop(KELTIR_NPC_ID,FANGS_ITEM_ID,DROP_RATE)
7 t* u. n/ o. b# ]; C - STARTED.addKillId(KELTIR_NPC_ID)5 L R3 x/ H* h- C7 ~
- STARTED.addTalkId(7056)+ H$ {9 e5 [# B! q' d
- STARTED.addTalkI d(7012)/ ]4 z' p) O( }, P- M# K: {
- STARTED.addTalkId(7009)
' m4 z% l7 a% [2 B( o - STARTED.addTalkId(7011)
Скопировать код % @0 C, B% h* n
& p/ a6 k L! v8 n# K
|