Зарегистрируйтесь сейчас чтобы найти еще больше друзей, и получить полноценный доступ ко всем функциям сайта!
Для просмотра Вам необходимо авторизоваться Если Вы еще не зарегистрированы, перейдите по ссылке:Зарегистрироваться
x
Хроники Interlude$ O; f* G; t: U* o
Сборка L2j
; t9 i# p: A* w0 Y5 jОбратите внимание: в файле htm стартового NCP обязательно должна быть ссылка на квест:2 y. ?3 ?; H+ H) P; q6 P0 |
- STARTED.addQuestDrop(KELTIR_NPC_ID,FANGS_ITEM_ID,DROP_RATE)
Скопировать код Для этого квеста больше ничего не надо. Все необходимое для корректной работы квеста уже добавили. Вот полный текст квеста:
+ o9 k$ R3 ]% l* }/ W. X+ n
% C: C7 z- q( b( _$ {$ t+ E" L- if getCount(st) >= 4 :
3 R F. K3 u2 L9 J. i - completed(st)4 h' Q6 m4 Q, k
- return
5 |5 ]2 c$ l" O+ ^# o! U
9 D% j. m; K+ G! N z- class Quest (JQuest):
4 T6 G1 [ g/ e$ v' J" g6 C1 O - def __init__(self,id,name,descr): JQuest.__init__(self,id,name,descr)% w6 T4 D" s! N! I
- def onEvent (self,event,st):! v/ m) V/ v% M9 K! D$ D7 {
- id = st.getState()
/ ^2 x* _- O K: ?# D2 q - if id == CREATED : st.setState(STARTED)
' h* s0 a, u" W - elif id == COMPLETED: pass
5 J5 c- @3 _& P& G3 J* L. { - elif id == STARTED : check(st)
9 [) L W0 Z" t, p4 P! @# ]6 G6 F - return$ j4 d0 h/ K, z8 M8 b- D3 R
- 7 O1 ?) u* x& V. {% ^- c# F5 W( i
- QUEST = Quest(201,"Tutorial", "Tutorial quest")
4 A0 R- C* u' q2 x% ~: J - CREATED = State('Start', QUEST)
, |" I, e: K5 R* e3 `9 ?3 m - STARTED = State('Started', QUEST)) h) g" z3 y" C: G) W; l+ y
- COMPLETED = State('Completed', QUEST)
m! A0 p5 V! l, c, c! A& ` - ' A( g. _; i2 b c; k8 ^, Y
- QUEST.setInitialState(CREATED)
1 E' q0 ]7 r, a! ]2 q - QUEST.addStartNpc(7056)% H6 ^) T& ]) k5 `
- STARTED.addQuestDrop(KELTIR_NPC_ID,FANGS_ITEM_ID,DROP_RATE)
Скопировать код Теперь рассмотрим, как это работает.; v9 R: h) H' _& V5 l; U
Игрок подходит к начальному NCP (в данном случае 7056), нажимает на «Quest». Квест будет создан и состояние квеста перейдет к CREATED и игроку будет показана страничка Start.htm с описанием квеста. Тогда метод onEvent, поле открытия странички Start.htm переведет состояние квеста в STARTED и игроку будет показана страничка Started.htm, где будет опсание того, как найти keltirs и .т.д.
/ J7 H5 b! V7 R( l8 m' b2 o/ K( ]3 N8 z
: U1 d+ ?: U* {9 h6 F7 ]: f
При состоянии STARTED будет зарегистрирован дроп «fangs» при убийстве keltirs. Игрок может вернуться к стартовому NCP и спросить о квесте – метод onEvent будет вызван снова. Если у игрока не хватает необходимого количества предметов, то метод check() не переведет квест в следующее состояние и Started.htm будет показана снова. Но если игрок собрал необходимее количество предметов (в данном случае 4 клыка), то метод check() вызовет метод completed() который переведет квест в новое состояние COMPLETED, заберет все клыки, даст карту мира, т.к. это награда за квест, покажет Completed.htm и завершит квест.7 I8 |0 |! ]' O8 w$ C& ~) O) s7 a" a
! J* K1 m0 a1 r( L; I. J# d. x0 c" s% F6 g _8 L) S7 o# m1 H A
Теперь давайте сделаем наш квест более похожим на то, что он должен из себя представлять.% D* q. {$ J, N* d2 s6 v. i2 W
Прежде всего у нас есть 3 метода для объявления их в Яве – onTalk, onKill и onEvent. Если методы onTalk и onKill не объявлены, то за них все будет делать метод onEvent, т.е. определять квестовых монстров и вызывать диалоги NCP. Есть примечание, методы onTalk и onKill будут вызывать только диалоги с NCP в зависимости от текущего состояния квеста. Метод onKill будет вызываться только тогда, когда мы убиваем квестового монстра.% ]- ]. N) X; H, D6 F8 o. Q
1 [$ V& M8 d% J( N8 `3 f* u: H1 W3 L: R# r
Давайте рассмотрим как вызывается метод onKill при убийстве keltir в состоянии квеста STARTED:
/ m- q B* S. E& R- STARTED.addKillId(KELTIR_NPC_ID)
Скопировать код и метод onKill в классе Quest:
, C: o8 @1 B9 g) H: g6 h! V' M9 s$ D, ^% O* a7 A& C# E9 O
- class Quest (JQuest):* ]! p' T$ W r3 d6 u
- ...
: e; j& ?6 D0 K2 ]1 ]/ W3 z4 e - def onKill (self,npcId,st):- ]7 ?0 \3 |- C- V3 ^
- if npcId == KELTIR_NPC_ID:6 {. z1 } _5 R: k @" j- |" I
- n = getCount(st)$ j' r$ f) x1 }& B8 Q) s/ Z
- if n == 0:5 A0 x* ^6 L" }, U; o$ |6 b
- return "Chat0.htm"' K$ P6 v9 j' z ~
- elif n == 1:
) ?9 i0 l' Z2 f3 V5 \' E - return "Chat1.htm"9 c5 X7 h, D6 Y$ _1 {" s
- elif n >= 4:
0 C) [% i4 Q+ \) ~; c - return "Chat4.htm"
+ g! R: d1 c, [1 q; v- Z' y9 E' L3 v - return "Collected "+str(n)+" of 4 fangs"$ t: Z& S8 Z! u9 H7 H& w1 l+ w
- return
Скопировать код Метод onKill (а так же метод onTalk) имеет следующие параметры:( @$ C" O9 z% E% V3 ?6 Z# ~
0 j+ x. O. l, r4 R( \: |# K' B, E9 d, U! ~% x$ I4 E4 k3 v
• self – квест7 R+ V2 Z. R& Q* |7 H. c
• npcId – ID NCP, которого мы должны убивать (если это метод onTalk, то ID того NCP, с которым мы должны поговорить). J( Y+ a1 z" f3 f- ] S
• st – текущее состояние игрока.
2 t' P& _) `8 [: O# ^; ~6 u) Y1 z5 ], f! W! ~
+ J+ E, a% d4 _" y* K
В этом методе мы проверяем и отмечаем, является ли убитый NCP keltir’ом. В основном эта проверка не нужна, т.к. у нас только KELTIR_NPC_ID.6 i( X# ?, H$ S$ D% z3 F1 U
7 V4 j: z J, A
$ C6 R! d! e1 ~' {5 VЗатем проверяем количество предметов (в данном случае количество клыков), и если их вообще нет, то возвращаем строку "Chat0.htm", если только один предмет, то возвращаем строку "Chat1.htm", если же предметов 4 или больше, то "Chat4.htm". Если строка возвращена из методов onEvent, onKill или onTalk, то сервер покажет соответствующие htm. В Chat0.htm может иметь следующий текст: «Вы не имеете ни одного клыка, возвращайтесь позже, когда соберете 4 штуки и бла, бла, бла…», в Chat1.htm может быть следующий текст: «У Вас всего 1 клык, по этому соберите еще…». В Chat4.htm – «Вы собрали необходимое количество предметов, возвращайтесь к вашему тренеру, что бы завершить квест…»
( W/ Y4 U+ ?1 j& u+ P: x: u4 ?" l: o, ^1 V: b w
|# n! g- M- A ?8 {
Примечание: если в строка return начинается с "<html>", то будет показана страничка html с текстом, который стоит далее. Так вместо:
6 E# T9 T N `4 Sreturn "Chat4.htm"
2 i2 P, m. }4 d K/ S: ^0 @) E% y$ s
W; o* ^' `' J$ N
можно поставить:+ Z+ q8 _$ s7 t
- return "<html><body>Return to your trainer to complete the quest</body></html>"
Скопировать код Так же если строка заканчивается без .htm или в начале нет <html>, то текст будет выведен, как системное сообщение в окне чата. В нашем случае мы сделаем так, что бы при каждом убийстве keltik выводилось системное сообщение: «Собрано N из 4-х клыков».
* J2 U B6 e8 P( k: S9 n5 e; J8 b4 c5 D* u- V
3 C" B) }" z8 N& s" O
Наш код для onKill имеет один недостаток. Он будет постоянно показывать Chat0.htm, Chat1.htm и Chat4.htm, нам же необходимо, что бы Chat0.htm и Chat1.htm показывались только один раз. Как нам это сделать? С помощью переменных.
Z& i+ v2 B) C' j2 u# F
; E. X/ D7 \1 q
6 b7 D& y( f+ z( EВ каждом квесте строки могут храниться с помощью переменных. Эти переменные сохраняются в Вашей БД. В каждом методе мы можем назначить, прочитать и удалить переменные. Давайте изменим метод onKill, так что бы каждый диалог вызывался только один раз.& e |, N: ]: D9 Z
- def onKill (self,npcId,st):
5 _/ ]' D) ?/ s9 V' }9 J# g( R - if npcId == KELTIR_NPC_ID:
: R8 `. a; X# p7 ^1 D/ ` - n = getCount(st)7 v( q b6 i3 W/ w P* @ l$ e
- if n == 0: k' t" {0 B; p5 A! }$ `
- if st.get('chat0') == None :
* ^* y, m- h. B/ p7 o) w - st.set("chat0", "true") i. ^ b! ~' R, G6 p
- return "Chat0.htm"& c& [/ g/ q! m% S
- elif n == 1:8 t& n/ n' p) y6 U6 T3 H5 t$ B) U
- if st.get('chat1') == None :8 P5 p _: l7 z# a2 n8 q4 ]3 I
- st.set("chat1", "true")3 b' C, U( }4 L* U* a
- return "Chat1.htm"
+ i2 | e) Z! { I+ Q - elif n >= 4:, }. V2 C- ?( [8 t7 }9 J
- return "Chat4.htm"
6 L+ L5 e" J7 J- q# \# n# B5 }5 D* A* m6 \( l - return "Collected "+str(n)+" of 4 fangs": ?& Z9 B( [0 v" b3 j% B, a R
- return
Скопировать код Если у игрока нет клыков (n=0), то мы получаем занчение переменной 'chat0'. Когда метод onKill вызван в первый раз, то пока ни каких переменных не имеется и python возвращает значение None. В этом случае объявляется переменная и показывается диалог Chat0.htm. Когда мы убиваем keltir, но не получаем с него клык, функция st.get('chat0') возвращает строку true, а не None. И во второй раз окно с Chat0.htm не появится, но в окне чата появится строчка «Collected 0 of 4 fangs». По тому же принципу сделано и с Chat1.htm.
& t1 N. U6 c9 u" o7 r7 _! |% q+ {& M" k+ m1 U/ Y
" h, o: X6 Y" PВот конечный рабочий вариант квеста:7 F: {0 P' |* n4 I$ Z& d$ i
- import sys# |* r# n2 m! S8 M2 H N* v
- from net.sf.l2j.gameserver.model.quest import State
3 Q; Q- B$ _- c; r1 @7 P( N - from net.sf.l2j.gameserver.model.quest import QuestState
* Q% k" l" a/ S6 W$ C - from net.sf.l2j.gameserver.model.quest.jython import QuestJython as JQuest
2 q# V5 m: r9 e9 m4 |# o: ]
2 Q# w) e2 C( t4 b3 m- `- KELTIR_NPC_ID = 12082
6 F8 u$ [ J, i. k @( y - FANGS_ITEM_ID = 1859' U+ D. `) O" Z$ I, |+ I# C
- DROP_RATE = 5000009 @, B+ X- i- F: y6 [ t% D
4 o" d7 x$ G- m# W& k0 ^) A4 @; \, h4 G- WORLD_MAP_ITEM_ID = 1665- u( _7 Y' Q5 `+ b. u
, b0 l8 H5 w+ @. V+ e ~- def getCount(st) :3 c/ n9 D6 L* O: u6 _
- return st.getQuestItemsCount(FANGS_ITEM_ID)7 Z, D5 r: k2 o. i3 N! P
; I4 R/ `) m s) C& R- def completed(st) :5 M: m" Z/ k4 u7 ]# r f
- st.setState(COMPLETED)
' u. G2 o3 x3 O# o" r - st.clearQuestDrops()/ s- |& s' a2 ^. O
- st.takeItems(FANGS_ITEM_ID,-1)
) J" r5 [( t- X% u# C - st.giveItems(WORLD_MAP_ITEM_ID,1)
% Y: X; N* {3 w& n3 o - st.exitQuest(False), h) ^. C- _4 o! \8 p& ]
- return1 m3 y6 X9 o. @' a; J
. ~7 `6 h y7 v0 H* V$ o! q+ G- def check(st) :, P1 b7 T6 r. l5 R: y
- if getCount(st) >= 4 :9 E8 p: l# t& {- L: ~+ r& y
- completed(st)- N8 \ Z) R6 N$ F$ z9 e: ~
- return
, ^0 k* N; n8 V' H- i
3 J4 t* k' A$ Y- class Quest (JQuest):
. K( z2 q! E6 V, X6 t0 R6 V8 u( ?: E - 3 s2 K7 J' _3 v+ [4 V. Q
- def __init__(self,id,name,descr): JQuest.__init__(self,id,name,descr)
# l6 p& e8 [! n# |4 } - ' e9 X& Y2 ]2 m+ K* i1 Q
- def onEvent (self,event,st):2 ~, S/ l/ D* p; Y: F" }
- id = st.getState()0 b2 x* c" G0 D! b3 l
- if id == CREATED : st.setState(STARTED)
$ ^" P4 k0 F0 A1 { p4 r) Y& ] - elif id == COMPLETED: pass
4 z, f# L) A; r/ S9 z$ w% F - elif id == STARTED : check(st)9 E; J, j6 p6 P0 g& [
- return
; s6 @6 F! A% e+ U - 7 y+ Y, S1 r" M! h
- def onKill (self,npcId,st):. i' J( [; d6 N5 P5 y
- if npcId == KELTIR_NPC_ID:
' ~8 d$ Z# O4 T+ f& {7 \* ^: q - n = getCount(st) h3 @- P4 [, u% H, S- F- H
- if n == 0:) O1 f9 R2 _+ a! D# R- R' R) |
- if st.get('chat0') == None :
3 p9 H" }5 O4 Y8 O - st.set("chat0", "true")
$ F; H3 Y$ J/ ?4 G, ~, X/ k) g. C - return "Chat0.htm"; [- q( i: I: P8 P; ~
- elif n == 1:
) I/ G9 M" I) P6 x8 B% d* R - if st.get('chat1') == None :. d; n! O+ a% d( E" A/ G% K
- st.set("chat1", "true")5 |# G" J; J( c- e
- return "Chat1.htm"
* I! w! n. \5 k/ D1 c, h - elif n >= 4:
% }1 T8 r7 V" \, U O# R - return "Chat4.htm"6 e! [3 @( b+ ?) U( u
- return "Collect "+str(n)+" of 4 fangs"
/ t+ T+ E) }* r7 q5 M/ S ]$ C1 b - return
~6 R3 z3 O3 c! [3 w% d
8 N0 l, v/ `' L0 o% n- QUEST = Quest(201, "Tutorial", "Tutorial quest")* H9 z, F, j4 ~( ^. M$ _4 s
- CREATED = State('Start', QUEST)% b$ x4 V8 n! F3 y, ]
- STARTED = State('Started', QUEST)( d' _' c% P) y. F
- COMPLETED = State('Completed', QUEST)' D/ i' ~6 F! C8 x9 _" S. j5 y
- 3 T! k& D O( u! {2 i# M
- QUEST.setInitialState(CREATED)& y9 l% k. Y) e9 M
- QUEST.addStartNpc(7056) b: \% l$ b: V) P, ?
- QUEST.addStartNpc(7012)8 V4 P# Q3 X# y7 n$ t; j0 }
- QUEST.addStartNpc(7009)& V5 ?$ F( r/ l
- QUEST.addStartNpc(7011)2 I' Q& l9 s( m5 ~
- 3 @7 c$ J y- i7 ]4 `3 w8 C, r
- STARTED.addQuestDrop(KELTIR_NPC_ID,FANGS_ITEM_ID,DROP_RATE)
- f1 b+ ^. L c# ~ - STARTED.addKillId(KELTIR_NPC_ID)$ i9 P$ H9 e" L" C/ A7 A. f7 ?
- STARTED.addTalkId(7056)& _$ a2 @# K: i0 \6 c2 J) Z$ x. M
- STARTED.addTalkI d(7012)
3 x$ z% b& U9 K; X. e. Q: l( h - STARTED.addTalkId(7009)
( B | {$ }" m. X( e - STARTED.addTalkId(7011)
Скопировать код * n0 A& g* Y4 | U& r$ ?
6 R1 ?) r) f; m, n |