Зарегистрируйтесь сейчас чтобы найти еще больше друзей, и получить полноценный доступ ко всем функциям сайта!
Для просмотра Вам необходимо авторизоваться Если Вы еще не зарегистрированы, перейдите по ссылке:Зарегистрироваться
x
Хроники Interlude
# [0 g4 b0 i. C- \% QСборка L2j' Z3 g5 U0 [3 m5 M6 P& G3 C5 K# }
Обратите внимание: в файле htm стартового NCP обязательно должна быть ссылка на квест:. _" D. L$ P# v( `
- STARTED.addQuestDrop(KELTIR_NPC_ID,FANGS_ITEM_ID,DROP_RATE)
Скопировать код Для этого квеста больше ничего не надо. Все необходимое для корректной работы квеста уже добавили. Вот полный текст квеста:
8 o# \* W7 s! B1 | C" S, `) i2 q: D- }
- if getCount(st) >= 4 :
! X6 X3 d0 P( v! t - completed(st)
' `* g! X, S# Q; I9 q - return
5 x$ e/ M- J9 M W# \7 g$ F3 r - # ^$ p5 z' r b. Z( ?! \* {
- class Quest (JQuest):, i& z, _' g# U+ Q1 P7 J
- def __init__(self,id,name,descr): JQuest.__init__(self,id,name,descr)
) |$ e7 U/ X# S6 E - def onEvent (self,event,st):! [9 @" o8 G. Z! O" l# h
- id = st.getState()) t) @; k6 c1 g/ N2 E
- if id == CREATED : st.setState(STARTED)6 j6 q" y4 U# T2 T, N. Z
- elif id == COMPLETED: pass
3 H; [% U. [1 K* s6 | W' ~8 k - elif id == STARTED : check(st)
6 C. J9 A5 t1 ~ }* z - return
9 F* R7 ]7 f- V" {
6 f/ o6 _" {9 _- QUEST = Quest(201,"Tutorial", "Tutorial quest")
: j* Z% a2 u! g" ~ - CREATED = State('Start', QUEST)
; k' \& {2 Y: w N& B" m3 } - STARTED = State('Started', QUEST)
2 c9 `. ~* M& e* K4 h# E4 I - COMPLETED = State('Completed', QUEST)
\6 |4 G5 k, ^7 `7 r7 t
' \! x* Y- a# {3 l! K% e# \+ S' Y- QUEST.setInitialState(CREATED)& k; E3 A! ]' R/ j: {; a1 x
- QUEST.addStartNpc(7056)1 I) d# `7 e3 Q* I5 s( a
- STARTED.addQuestDrop(KELTIR_NPC_ID,FANGS_ITEM_ID,DROP_RATE)
Скопировать код Теперь рассмотрим, как это работает.2 k& v; }. G0 q+ X
Игрок подходит к начальному NCP (в данном случае 7056), нажимает на «Quest». Квест будет создан и состояние квеста перейдет к CREATED и игроку будет показана страничка Start.htm с описанием квеста. Тогда метод onEvent, поле открытия странички Start.htm переведет состояние квеста в STARTED и игроку будет показана страничка Started.htm, где будет опсание того, как найти keltirs и .т.д.
7 |+ l% j$ b) d2 k b$ o: N4 p0 o" R% s
# \0 j5 y' E4 `. ?& H6 z5 R' t
При состоянии STARTED будет зарегистрирован дроп «fangs» при убийстве keltirs. Игрок может вернуться к стартовому NCP и спросить о квесте – метод onEvent будет вызван снова. Если у игрока не хватает необходимого количества предметов, то метод check() не переведет квест в следующее состояние и Started.htm будет показана снова. Но если игрок собрал необходимее количество предметов (в данном случае 4 клыка), то метод check() вызовет метод completed() который переведет квест в новое состояние COMPLETED, заберет все клыки, даст карту мира, т.к. это награда за квест, покажет Completed.htm и завершит квест.0 b& A7 _9 x2 ~# j
2 R, o7 b. D3 k/ G
: \" T# r4 j6 Q `Теперь давайте сделаем наш квест более похожим на то, что он должен из себя представлять.
7 M* e4 o3 k8 @: YПрежде всего у нас есть 3 метода для объявления их в Яве – onTalk, onKill и onEvent. Если методы onTalk и onKill не объявлены, то за них все будет делать метод onEvent, т.е. определять квестовых монстров и вызывать диалоги NCP. Есть примечание, методы onTalk и onKill будут вызывать только диалоги с NCP в зависимости от текущего состояния квеста. Метод onKill будет вызываться только тогда, когда мы убиваем квестового монстра.
# S, R& n+ b' F5 I% ?8 A+ Y) n. c% H9 h; P
4 @' D/ R4 t* [ }; P. g# xДавайте рассмотрим как вызывается метод onKill при убийстве keltir в состоянии квеста STARTED:" L* ?& B6 f8 t& j5 e7 H
- STARTED.addKillId(KELTIR_NPC_ID)
Скопировать код и метод onKill в классе Quest:' H( b0 n. D" `) r* ~4 ^& F
5 Y4 ~6 v3 M! I$ C
- class Quest (JQuest):* m4 d% e: V/ O) H2 [
- ...1 w" Z, S# l+ N. e5 d; K- A! k2 Q
- def onKill (self,npcId,st):
2 `( E3 v. e% \ Z& ^ V - if npcId == KELTIR_NPC_ID:7 V% \- `. E/ j
- n = getCount(st)
4 p" ?3 c$ T) R# i2 j5 { - if n == 0:* u! V! u% W5 W
- return "Chat0.htm"7 i( M, k9 w" V5 | I
- elif n == 1:7 `$ I6 i3 P, N7 @
- return "Chat1.htm") n! q4 X- h- o+ m
- elif n >= 4:
" h5 L w! L1 `/ N; R& h) w - return "Chat4.htm"
- V( m! |# `; l$ w5 p4 b - return "Collected "+str(n)+" of 4 fangs", F1 _4 _& l4 W4 f, U
- return
Скопировать код Метод onKill (а так же метод onTalk) имеет следующие параметры:- _9 F4 {* R. F7 N, I! T
7 C( ^+ E* X2 L
& m( i- J. J; j2 m; r9 P• self – квест! f8 X" ?+ y! R0 p X G
• npcId – ID NCP, которого мы должны убивать (если это метод onTalk, то ID того NCP, с которым мы должны поговорить).1 x1 I9 E y6 @$ I$ l
• st – текущее состояние игрока.
( v3 Q' b S- E0 B
; R* }4 y; K, p1 |/ R
7 {2 n' ?! y/ j" y RВ этом методе мы проверяем и отмечаем, является ли убитый NCP keltir’ом. В основном эта проверка не нужна, т.к. у нас только KELTIR_NPC_ID.
5 r% C3 S: S/ Y2 D$ m* |7 N, {0 `# P _6 _1 [* Z
+ G6 ~; m, X+ ZЗатем проверяем количество предметов (в данном случае количество клыков), и если их вообще нет, то возвращаем строку "Chat0.htm", если только один предмет, то возвращаем строку "Chat1.htm", если же предметов 4 или больше, то "Chat4.htm". Если строка возвращена из методов onEvent, onKill или onTalk, то сервер покажет соответствующие htm. В Chat0.htm может иметь следующий текст: «Вы не имеете ни одного клыка, возвращайтесь позже, когда соберете 4 штуки и бла, бла, бла…», в Chat1.htm может быть следующий текст: «У Вас всего 1 клык, по этому соберите еще…». В Chat4.htm – «Вы собрали необходимое количество предметов, возвращайтесь к вашему тренеру, что бы завершить квест…»
/ y [8 N" H" |5 I
; ?; \0 o7 y" j- c# J
1 d6 X/ S- Q5 o6 k6 tПримечание: если в строка return начинается с "<html>", то будет показана страничка html с текстом, который стоит далее. Так вместо:" H# F( ^+ M3 b: @
return "Chat4.htm"
" l9 X. j& w$ A+ u( t; Q
) S1 J8 [ c; ^5 b
/ U! a2 Q. f4 t! a5 h* ~* a# h! nможно поставить:
, ?' m e& G9 a$ A: f, p) K- return "<html><body>Return to your trainer to complete the quest</body></html>"
Скопировать код Так же если строка заканчивается без .htm или в начале нет <html>, то текст будет выведен, как системное сообщение в окне чата. В нашем случае мы сделаем так, что бы при каждом убийстве keltik выводилось системное сообщение: «Собрано N из 4-х клыков».
* Y" k: q7 ]2 w. s! y* o
a; D* N5 v* j% V; t
: `/ c6 C" f0 [( q5 [Наш код для onKill имеет один недостаток. Он будет постоянно показывать Chat0.htm, Chat1.htm и Chat4.htm, нам же необходимо, что бы Chat0.htm и Chat1.htm показывались только один раз. Как нам это сделать? С помощью переменных.
" a9 [: [8 Y8 ~2 ] x2 t$ k* U( K6 M Y! B! K! J
2 U! X" T( g0 z! w* w2 D& C
В каждом квесте строки могут храниться с помощью переменных. Эти переменные сохраняются в Вашей БД. В каждом методе мы можем назначить, прочитать и удалить переменные. Давайте изменим метод onKill, так что бы каждый диалог вызывался только один раз.
' [) ]# s, G! H0 d- def onKill (self,npcId,st):
$ \5 l# K/ e7 u& r+ c7 H6 m) B - if npcId == KELTIR_NPC_ID:- c9 r4 J4 I' l- ?- _# _
- n = getCount(st)9 t4 Y+ c# \6 D( o, m* |
- if n == 0:
1 H" \% l6 Y+ ^& }2 o) E# |% S/ X8 T - if st.get('chat0') == None :
5 V6 M9 b) \2 P! f5 W( | - st.set("chat0", "true")
8 q& T' G4 I C8 s" m9 { D) o0 f - return "Chat0.htm"0 X# V0 w* V& g G; }
- elif n == 1:
) W8 }& w0 [' x5 k4 U' J9 U7 E/ |3 n - if st.get('chat1') == None :
9 ~5 q7 V, H' e; q* F - st.set("chat1", "true")
6 K& r t4 X- m } - return "Chat1.htm"
* G- y9 P* @8 o7 z5 a - elif n >= 4:- o" ^) e$ X8 c) m x4 `1 O
- return "Chat4.htm": ~6 J# \, y; O5 \9 p. G$ `
- return "Collected "+str(n)+" of 4 fangs"$ ]0 y+ p7 e- [* l3 O" K2 h
- return
Скопировать код Если у игрока нет клыков (n=0), то мы получаем занчение переменной 'chat0'. Когда метод onKill вызван в первый раз, то пока ни каких переменных не имеется и python возвращает значение None. В этом случае объявляется переменная и показывается диалог Chat0.htm. Когда мы убиваем keltir, но не получаем с него клык, функция st.get('chat0') возвращает строку true, а не None. И во второй раз окно с Chat0.htm не появится, но в окне чата появится строчка «Collected 0 of 4 fangs». По тому же принципу сделано и с Chat1.htm.
* H( v4 d: A' D2 T5 @ Z! ?5 _ F3 F) w- g d Z
% j" r: U2 ]9 h. t/ c
Вот конечный рабочий вариант квеста:
2 b: a) c# b- [9 ?+ L- import sys
: n5 {: r5 m* F, e" Z6 [, s - from net.sf.l2j.gameserver.model.quest import State- K, L5 P9 S1 D$ u
- from net.sf.l2j.gameserver.model.quest import QuestState" @0 b9 [1 n7 |: O6 n7 p& a
- from net.sf.l2j.gameserver.model.quest.jython import QuestJython as JQuest
- \% F0 x. g; j: I2 ~
+ f* |" k+ z4 S8 v! h" h- KELTIR_NPC_ID = 12082& k6 A" ~8 [% k S! G$ g% u
- FANGS_ITEM_ID = 18596 I4 s* g2 ?$ U% Y, ^
- DROP_RATE = 500000, u! R# v1 E% L5 M: l
- * W" E2 q6 F) h6 ~# c8 p6 y
- WORLD_MAP_ITEM_ID = 16651 t3 D% S, S9 g/ K; Y
" L# M; j/ v. Z+ w9 m9 K& i- def getCount(st) :
- K/ v& s; L3 @% A2 T/ U$ Q5 w6 { - return st.getQuestItemsCount(FANGS_ITEM_ID); I# s$ N- n/ }( J
- . {7 ^5 V* N" H
- def completed(st) :
: l# [" r( h8 @4 k9 g9 P, b+ q, x( h - st.setState(COMPLETED)! ~8 n5 P# z0 r. a0 o; [
- st.clearQuestDrops()
+ f0 I7 ~+ Y" Y; G# k8 _ J' S5 a1 { - st.takeItems(FANGS_ITEM_ID,-1)' U* `# n4 l1 {3 s$ q
- st.giveItems(WORLD_MAP_ITEM_ID,1)
2 \; k1 x' t- x$ Y" Z6 \" t- n4 j - st.exitQuest(False)( B" {0 h0 v3 J) T
- return% O$ { o, N4 {8 t# B3 w& c) t
- $ l: K* E2 @6 Y. x
- def check(st) :
; q! \" m* T) R7 ` - if getCount(st) >= 4 :0 E4 M' `* A* W1 \) W( z. P( v
- completed(st)' C' I N9 k4 C J$ A& }
- return6 A2 m5 p3 ]; V |5 R' H3 R1 W
- ) g% w9 Y7 E$ K( P8 R q! D7 U% u
- class Quest (JQuest):5 [1 a" {7 Z3 B8 O/ _) a
- . e! R% L& q" G, e6 v! V0 U# g) T
- def __init__(self,id,name,descr): JQuest.__init__(self,id,name,descr)
0 p% J* Z* B8 R3 ~6 K0 l+ p3 D! v
% A; j) ^& y+ M7 I- W; T' F3 w- def onEvent (self,event,st):, y" F$ E4 p# C+ q5 l1 B
- id = st.getState()+ S8 B+ ]9 @. } t
- if id == CREATED : st.setState(STARTED). [. `7 K# C1 x$ \ G4 _6 \) p
- elif id == COMPLETED: pass
0 m0 r; ?/ `' A8 N1 u! j* Q - elif id == STARTED : check(st)0 y ?, O) e% U
- return
, C$ d8 b. j$ v1 R# T4 l2 p$ ^ - 0 R5 A6 O+ H q
- def onKill (self,npcId,st):% y) W- [+ t c1 h
- if npcId == KELTIR_NPC_ID:; {, g, J/ w S# O! Z9 q- {
- n = getCount(st)
5 c* A* K; I$ `6 Q7 U+ B8 H - if n == 0:) g; h- i/ I7 T3 a6 v% a, H5 G' w5 X
- if st.get('chat0') == None :5 j4 ~# s% e, q" C$ K0 y. j% ~: b
- st.set("chat0", "true")
- n- _. H* ~ O/ u. R: t: F- } - return "Chat0.htm"* l- L3 g- N* @$ ^/ G! _
- elif n == 1:
~0 ?3 d5 _* a3 a" L - if st.get('chat1') == None :, T9 o& |' f$ q# b# u7 P
- st.set("chat1", "true")6 k7 w& o1 r! ?+ F: X
- return "Chat1.htm"% [! ` _0 k5 i/ U
- elif n >= 4: {2 l' W5 R& i8 ]# O2 S- k' h
- return "Chat4.htm"+ Y, C( E2 }( J# K w+ ?& B- m8 Z
- return "Collect "+str(n)+" of 4 fangs"
, _. O' u- V3 L1 K" o" R+ a! s - return$ P" a' `4 d( Z( |5 }# `" {& G! a8 J: ?
) Y. h; F" C$ V: q- QUEST = Quest(201, "Tutorial", "Tutorial quest"), W: \1 S0 i* B* @5 j- l1 t
- CREATED = State('Start', QUEST)
5 u# D( M; k2 I1 G! m4 L' A5 c - STARTED = State('Started', QUEST)
5 s6 j- s% L2 @' O: A: p - COMPLETED = State('Completed', QUEST)) \( O- M6 H- U/ S2 y
- ' V* ] I: t, W7 p
- QUEST.setInitialState(CREATED)5 |$ H2 p+ n7 t
- QUEST.addStartNpc(7056)% V. f. e1 [4 \9 j
- QUEST.addStartNpc(7012)# q ~( H; E$ ^$ X# B$ l
- QUEST.addStartNpc(7009)
( l5 |9 M$ a* y) c - QUEST.addStartNpc(7011)- \5 b7 v" |2 d8 G# c
- ' m. @3 N% v: m/ R: C- l$ }
- STARTED.addQuestDrop(KELTIR_NPC_ID,FANGS_ITEM_ID,DROP_RATE)
1 T. g! Y# q6 y9 X* i- E - STARTED.addKillId(KELTIR_NPC_ID)! G! ~3 ~. O1 {' a+ k
- STARTED.addTalkId(7056)
: w+ {1 w9 l( |- } G2 b4 Q - STARTED.addTalkI d(7012)8 d* {9 e, `! B% o. Q" Z5 ~ f/ t
- STARTED.addTalkId(7009)( l) \% A- D( ]
- STARTED.addTalkId(7011)
Скопировать код
+ `' ]: F! ~3 o" _8 S% @: k0 r( l @6 R9 Z% w/ u
|