Зарегистрируйтесь сейчас чтобы найти еще больше друзей, и получить полноценный доступ ко всем функциям сайта!
Для просмотра Вам необходимо авторизоваться Если Вы еще не зарегистрированы, перейдите по ссылке:Зарегистрироваться
x
Хроники Interlude
* \* `; {% t! R0 T- XСборка L2j8 o' S7 } l2 z$ @6 ~. D
Обратите внимание: в файле htm стартового NCP обязательно должна быть ссылка на квест:( @+ A* u, i& H$ f" l4 H
- STARTED.addQuestDrop(KELTIR_NPC_ID,FANGS_ITEM_ID,DROP_RATE)
Скопировать код Для этого квеста больше ничего не надо. Все необходимое для корректной работы квеста уже добавили. Вот полный текст квеста:* X/ q7 x$ }. D) D# ]* x
C! Z4 J+ W; T) r- [- if getCount(st) >= 4 :) i2 M% |! h6 q4 v/ Q
- completed(st)& U8 I' D4 M I7 z
- return
3 Z# Z E. G, K% s' @; e
0 n( k8 O7 N( j9 i; e+ B) F- class Quest (JQuest):
8 E& @- c" z) Q g% D1 ?8 ~ - def __init__(self,id,name,descr): JQuest.__init__(self,id,name,descr)
9 @( a2 `* J5 m! F3 X - def onEvent (self,event,st):' p, l/ s8 U4 j
- id = st.getState()
_! [7 @6 F- d$ [ - if id == CREATED : st.setState(STARTED)3 g, Q) G# w0 o
- elif id == COMPLETED: pass
: a! b5 n1 @0 O( Q - elif id == STARTED : check(st)1 {1 L5 @' b) v. e7 J9 m
- return9 @ |* N" E( j9 a$ ~# U" S
1 f( e6 s1 `3 `9 k- QUEST = Quest(201,"Tutorial", "Tutorial quest")$ ?, a1 |5 s9 s6 v1 l
- CREATED = State('Start', QUEST)9 h7 ?2 H* x! f+ L( H
- STARTED = State('Started', QUEST)( @" U; R3 h3 ]3 l6 Z- I
- COMPLETED = State('Completed', QUEST)( t J- J( ?1 f6 t+ e0 l1 D
0 [7 I2 O7 b% |- O- QUEST.setInitialState(CREATED)
- n6 z: R6 o8 m; x - QUEST.addStartNpc(7056)
7 z5 w, p, [ p - STARTED.addQuestDrop(KELTIR_NPC_ID,FANGS_ITEM_ID,DROP_RATE)
Скопировать код Теперь рассмотрим, как это работает.
; W) {5 J: y$ {! c8 KИгрок подходит к начальному NCP (в данном случае 7056), нажимает на «Quest». Квест будет создан и состояние квеста перейдет к CREATED и игроку будет показана страничка Start.htm с описанием квеста. Тогда метод onEvent, поле открытия странички Start.htm переведет состояние квеста в STARTED и игроку будет показана страничка Started.htm, где будет опсание того, как найти keltirs и .т.д.: x9 L- K" Q+ U$ D5 Y; I
& v3 s( {6 M) F k# A4 F! m4 n5 r+ \, l* [
При состоянии STARTED будет зарегистрирован дроп «fangs» при убийстве keltirs. Игрок может вернуться к стартовому NCP и спросить о квесте – метод onEvent будет вызван снова. Если у игрока не хватает необходимого количества предметов, то метод check() не переведет квест в следующее состояние и Started.htm будет показана снова. Но если игрок собрал необходимее количество предметов (в данном случае 4 клыка), то метод check() вызовет метод completed() который переведет квест в новое состояние COMPLETED, заберет все клыки, даст карту мира, т.к. это награда за квест, покажет Completed.htm и завершит квест.
) S& v9 k M' u0 \# G" u- v7 v& Y9 o& r* n! Q0 e
+ p9 v4 h' D3 K1 VТеперь давайте сделаем наш квест более похожим на то, что он должен из себя представлять.9 M9 b7 c/ O' e
Прежде всего у нас есть 3 метода для объявления их в Яве – onTalk, onKill и onEvent. Если методы onTalk и onKill не объявлены, то за них все будет делать метод onEvent, т.е. определять квестовых монстров и вызывать диалоги NCP. Есть примечание, методы onTalk и onKill будут вызывать только диалоги с NCP в зависимости от текущего состояния квеста. Метод onKill будет вызываться только тогда, когда мы убиваем квестового монстра.
4 p, ~6 u0 K6 q$ D6 {0 |+ f
9 w. ], J, g/ I$ V2 Z l Q3 j! _; ^' A; S! \4 y0 E- P9 P
Давайте рассмотрим как вызывается метод onKill при убийстве keltir в состоянии квеста STARTED:! y: ]4 o1 i) v$ D" o* y
- STARTED.addKillId(KELTIR_NPC_ID)
Скопировать код и метод onKill в классе Quest:
6 k2 T9 `; U8 K6 P
$ K3 l n- h# a- W a0 Z- class Quest (JQuest):
/ b# N" k. a' m0 h% i9 q! H7 x - ...
8 G* V) V! u5 M. }1 V - def onKill (self,npcId,st):2 C$ } a$ k7 m1 j
- if npcId == KELTIR_NPC_ID:
2 a. d3 I0 }+ ~ - n = getCount(st)8 h( U4 v1 C3 ?' R! m1 {' Z
- if n == 0:
/ P8 V6 h) w0 B- Z* f/ ] - return "Chat0.htm"
; g0 M6 T" }) s: s - elif n == 1:
# s/ p: w' A: H; { - return "Chat1.htm"
/ @; n- o$ f3 C# ]$ A* U& D9 Z! i - elif n >= 4:
" t/ Z X% g7 A+ V2 L; ^6 r# o) W - return "Chat4.htm"
: h( X% O# T d - return "Collected "+str(n)+" of 4 fangs"
* ~0 ?: g' I: O2 _ - return
Скопировать код Метод onKill (а так же метод onTalk) имеет следующие параметры:
& \; p9 l) w9 C
2 J8 u, F$ e+ t$ M1 r2 d9 o, h. J$ c5 l
• self – квест
1 C( ~- h9 N7 F- H• npcId – ID NCP, которого мы должны убивать (если это метод onTalk, то ID того NCP, с которым мы должны поговорить).
! h/ v! e9 ?5 d( B• st – текущее состояние игрока.
8 R/ l0 p" S1 A Q- P1 Z
6 G: E' |9 t; j* s5 b" E; ~/ t1 r/ D7 B7 j* w2 s0 C* A0 d2 B! C
В этом методе мы проверяем и отмечаем, является ли убитый NCP keltir’ом. В основном эта проверка не нужна, т.к. у нас только KELTIR_NPC_ID.! u8 w( q4 ?! W6 e2 }" D4 v: d8 h# o
& f! \3 v; P- g2 M9 x! R
$ g2 j! t1 j0 k9 M" s5 E0 v3 ]Затем проверяем количество предметов (в данном случае количество клыков), и если их вообще нет, то возвращаем строку "Chat0.htm", если только один предмет, то возвращаем строку "Chat1.htm", если же предметов 4 или больше, то "Chat4.htm". Если строка возвращена из методов onEvent, onKill или onTalk, то сервер покажет соответствующие htm. В Chat0.htm может иметь следующий текст: «Вы не имеете ни одного клыка, возвращайтесь позже, когда соберете 4 штуки и бла, бла, бла…», в Chat1.htm может быть следующий текст: «У Вас всего 1 клык, по этому соберите еще…». В Chat4.htm – «Вы собрали необходимое количество предметов, возвращайтесь к вашему тренеру, что бы завершить квест…»; O1 b9 F, m6 j O9 x
3 a5 f: q- M6 Y5 ~" d: A( ]
7 m' K$ m/ J9 y/ b p8 dПримечание: если в строка return начинается с "<html>", то будет показана страничка html с текстом, который стоит далее. Так вместо:7 ^4 J x9 W7 A- d
return "Chat4.htm"
$ z; T0 F: K" K- V% U# w3 W0 ^" L
* V# s: X `# M1 O" @можно поставить:: U! w& g9 R }; r8 S$ A' g
- return "<html><body>Return to your trainer to complete the quest</body></html>"
Скопировать код Так же если строка заканчивается без .htm или в начале нет <html>, то текст будет выведен, как системное сообщение в окне чата. В нашем случае мы сделаем так, что бы при каждом убийстве keltik выводилось системное сообщение: «Собрано N из 4-х клыков».: B$ W, d+ Q1 ^6 g; w
' n" @. g* N s2 W: F4 c5 ?
6 P* y/ l8 S1 j" _6 A7 e, {Наш код для onKill имеет один недостаток. Он будет постоянно показывать Chat0.htm, Chat1.htm и Chat4.htm, нам же необходимо, что бы Chat0.htm и Chat1.htm показывались только один раз. Как нам это сделать? С помощью переменных.! V( O# G% h) H+ X1 _
: `) s- Y; E1 k& P8 O
$ O" b9 {9 l7 oВ каждом квесте строки могут храниться с помощью переменных. Эти переменные сохраняются в Вашей БД. В каждом методе мы можем назначить, прочитать и удалить переменные. Давайте изменим метод onKill, так что бы каждый диалог вызывался только один раз.- G) b4 U6 A, \. \& m
- def onKill (self,npcId,st):
! a0 w, _5 F; h7 B - if npcId == KELTIR_NPC_ID:4 u$ k0 p2 W8 {' l* |# R, v
- n = getCount(st)( I- q# {, a( h8 q
- if n == 0:
$ d s) T, j9 K1 s; J) w2 j - if st.get('chat0') == None :
d( S! Q: `) _* ]3 { - st.set("chat0", "true")
) x/ Z; B6 N8 r6 Z3 I - return "Chat0.htm"1 b1 y3 v! c; V% o" N, t. j
- elif n == 1:
1 y+ V2 P( e) g3 } - if st.get('chat1') == None :2 i+ A, `% z2 \. U8 i/ c, m% z$ \
- st.set("chat1", "true")* i, m; J" u: ]8 n+ K
- return "Chat1.htm"( m6 `; z x+ |& t
- elif n >= 4:) ]. q% E+ M& K( n3 {6 \0 u
- return "Chat4.htm"
( C; }' c' [2 _) N: c" y - return "Collected "+str(n)+" of 4 fangs"5 e3 u$ ]! L( m1 x+ R( o$ T
- return
Скопировать код Если у игрока нет клыков (n=0), то мы получаем занчение переменной 'chat0'. Когда метод onKill вызван в первый раз, то пока ни каких переменных не имеется и python возвращает значение None. В этом случае объявляется переменная и показывается диалог Chat0.htm. Когда мы убиваем keltir, но не получаем с него клык, функция st.get('chat0') возвращает строку true, а не None. И во второй раз окно с Chat0.htm не появится, но в окне чата появится строчка «Collected 0 of 4 fangs». По тому же принципу сделано и с Chat1.htm.
. ]0 N/ z" W% v) Y
9 V, q* C- T' ^% m+ z6 e- r
; P, x7 @8 A0 ]Вот конечный рабочий вариант квеста:
; g$ @3 x0 o0 m8 b- import sys
3 a- b. R6 h3 B9 ~ - from net.sf.l2j.gameserver.model.quest import State0 x' c' \" x. c) Z
- from net.sf.l2j.gameserver.model.quest import QuestState$ r* b4 ?' U2 b7 v& ?! T
- from net.sf.l2j.gameserver.model.quest.jython import QuestJython as JQuest1 Q# B% A v7 h0 O
) [9 z0 n5 I2 l" ~- O- KELTIR_NPC_ID = 12082* n% E0 ~0 D- ]: T- z5 X
- FANGS_ITEM_ID = 1859+ N9 g7 w$ M( x) A0 ~
- DROP_RATE = 5000009 m9 Z1 c# X4 Q* E" t
) i/ E9 l- U6 `( Z" v# o6 o1 \- WORLD_MAP_ITEM_ID = 1665! R; ?/ o- f4 c! o$ A9 Q
- }8 s7 a& o/ {- def getCount(st) :
U% V8 z7 d1 w& _2 q' X - return st.getQuestItemsCount(FANGS_ITEM_ID)
0 K k: `9 y5 f% K - 8 u, {+ R' _& b9 n
- def completed(st) :
) D$ T! O* x) D+ V; U9 K - st.setState(COMPLETED)
0 J, c4 D1 }' x* H# F! X) W - st.clearQuestDrops()
2 Z7 k; C c) _, j - st.takeItems(FANGS_ITEM_ID,-1)- @5 I7 H( W8 d3 o$ C
- st.giveItems(WORLD_MAP_ITEM_ID,1)
( s6 v0 v2 m" P1 [ - st.exitQuest(False)
3 P% `# G7 l3 y - return
3 t6 T% I: Q6 C& n - 0 I8 F5 _' x5 k( P* |2 x i6 ?
- def check(st) :
: P% d8 b& D: o9 T% H0 u t - if getCount(st) >= 4 :5 {. [* T& C. G9 n; e' }1 Y
- completed(st)& B7 t3 Y- G% \0 N& R
- return
6 o2 d. u6 w8 Y: M
* o$ ] V h- C4 @- class Quest (JQuest):9 q: j5 n K! W9 g4 m$ {' c
- 6 j3 j6 r0 k4 _
- def __init__(self,id,name,descr): JQuest.__init__(self,id,name,descr)4 I3 d5 V: W( s! Y0 D9 o
- $ x5 o: K- a* H; k0 A5 {0 {
- def onEvent (self,event,st):
* ]4 o, [, j" K T! R3 F% U - id = st.getState()
* G8 u* }1 Z% k% C5 Z - if id == CREATED : st.setState(STARTED)% A% p9 h) D( T( F- K8 v8 M9 h
- elif id == COMPLETED: pass, S- N& T5 q6 G0 T* d
- elif id == STARTED : check(st)" b0 T+ U" V( e/ w) U
- return
2 _: L$ {/ _% l - 0 e( l+ {7 ^- ~! H; K) K. R; V
- def onKill (self,npcId,st):& f; r1 ^1 [2 \3 i1 v2 F7 P0 i
- if npcId == KELTIR_NPC_ID:
* n8 u7 Z$ S! _/ _, C, l5 G/ A' A( N - n = getCount(st)
% W4 c# l2 p. O& o9 \- c. ~$ G - if n == 0:
/ o9 J8 ~+ P3 ~0 ~: e1 _( W" L - if st.get('chat0') == None :) m h+ J) x& A6 i
- st.set("chat0", "true")- c/ `/ O+ S6 L
- return "Chat0.htm"" D! Y& ]* v9 B1 L1 |
- elif n == 1:
6 \4 f" T: E" `7 [7 p9 F+ [ - if st.get('chat1') == None :3 R" O# a" U' @, D5 r2 B
- st.set("chat1", "true")
0 G# h! R7 \5 A( z/ T P - return "Chat1.htm"6 {* ?& M, s3 n5 D
- elif n >= 4:9 i5 k8 }9 [* b+ ?3 o
- return "Chat4.htm"# c. M {1 l0 b# X" U1 d
- return "Collect "+str(n)+" of 4 fangs" R. E0 T8 ]7 j0 r4 B2 p; T4 L
- return
! X; M3 q, ?6 F6 t7 E+ S$ O
1 b, D1 g- m* j; a/ `- QUEST = Quest(201, "Tutorial", "Tutorial quest")
* J5 L3 E. p& o5 } - CREATED = State('Start', QUEST)
+ V8 o) x: Z5 g2 j9 r - STARTED = State('Started', QUEST)! G# m! h# J6 c' N
- COMPLETED = State('Completed', QUEST)
+ ]8 F0 t, l1 A8 N - ; l7 \4 L; H, s' _# A
- QUEST.setInitialState(CREATED)
0 x3 C# t1 Z- e - QUEST.addStartNpc(7056)6 `1 C8 Q: a% X" v8 |( n
- QUEST.addStartNpc(7012)1 g$ ~- q2 Y' L0 `5 U
- QUEST.addStartNpc(7009) ^# U1 W4 J+ K: {5 L Q
- QUEST.addStartNpc(7011)2 G# }/ @+ {) w" a) A7 R# a v0 c0 E1 w
- , V; Z& M6 v# P
- STARTED.addQuestDrop(KELTIR_NPC_ID,FANGS_ITEM_ID,DROP_RATE)
q8 m5 [% d0 N - STARTED.addKillId(KELTIR_NPC_ID)
8 }# ^ b6 f: f; O/ u" R" |) r - STARTED.addTalkId(7056)
/ V0 @$ }5 r T1 S: K5 N- ~0 B+ x - STARTED.addTalkI d(7012). `% c1 q& R7 c4 p; k ~; R& c2 G$ J
- STARTED.addTalkId(7009)
8 v' F2 Z4 Z' ^" ]- d- z2 @ - STARTED.addTalkId(7011)
Скопировать код
9 D, P& r+ y# N2 u: {# r4 ^$ q+ ~% E4 x, V2 w( A5 J
|