Зарегистрируйтесь сейчас чтобы найти еще больше друзей, и получить полноценный доступ ко всем функциям сайта!
Для просмотра Вам необходимо авторизоваться Если Вы еще не зарегистрированы, перейдите по ссылке:Зарегистрироваться
x
Хроники Interlude' R% ~$ d! {7 j
Сборка L2j4 o& u' }2 e9 R- h8 o6 @5 B: C
Обратите внимание: в файле htm стартового NCP обязательно должна быть ссылка на квест:7 {3 ~: w2 r4 r7 O8 _% S* F: X
- STARTED.addQuestDrop(KELTIR_NPC_ID,FANGS_ITEM_ID,DROP_RATE)
Скопировать код Для этого квеста больше ничего не надо. Все необходимое для корректной работы квеста уже добавили. Вот полный текст квеста:1 i4 E, }, C& `/ a
- H# `% A3 c. _+ s" ]
- if getCount(st) >= 4 :# x: ]7 u7 b! j y1 W* m
- completed(st)2 l' \1 T& I+ ~9 y7 p6 ?9 s/ S8 d
- return
/ ~2 o. K' j! z- L - # `$ p1 [$ c8 Z* f" M o/ p K
- class Quest (JQuest):6 K* b- |7 r; U+ U; a
- def __init__(self,id,name,descr): JQuest.__init__(self,id,name,descr)9 ~) v1 U" G- R% [6 v+ H0 D4 s
- def onEvent (self,event,st):
$ ~! R8 ~0 p4 m - id = st.getState()
1 Q6 [: ?9 U# a' N. W: O: p1 W8 M - if id == CREATED : st.setState(STARTED), L2 |0 G4 S+ O' a
- elif id == COMPLETED: pass
0 w* S: i' ?$ x0 J% n0 \$ z& f0 J8 G - elif id == STARTED : check(st)/ ~, E) d! N- I6 t+ q2 j
- return6 w" l( n! x8 c- u
- & H @0 N1 J3 i; A7 ?2 g
- QUEST = Quest(201,"Tutorial", "Tutorial quest")) O1 O4 ?8 R: {; p, k6 i7 Z/ a" b5 m
- CREATED = State('Start', QUEST)
# X e5 w0 @8 s: J5 Z - STARTED = State('Started', QUEST)) K" Z5 Z! J ~( B
- COMPLETED = State('Completed', QUEST)7 m- `7 Z f V
- / T% G6 A! a8 i( C
- QUEST.setInitialState(CREATED)9 M: I" I# d5 ]2 p* F" k3 O
- QUEST.addStartNpc(7056)4 s5 j0 B) h* ^/ _! n6 X7 k1 H
- STARTED.addQuestDrop(KELTIR_NPC_ID,FANGS_ITEM_ID,DROP_RATE)
Скопировать код Теперь рассмотрим, как это работает.5 R/ F s! G* ]$ v+ H
Игрок подходит к начальному NCP (в данном случае 7056), нажимает на «Quest». Квест будет создан и состояние квеста перейдет к CREATED и игроку будет показана страничка Start.htm с описанием квеста. Тогда метод onEvent, поле открытия странички Start.htm переведет состояние квеста в STARTED и игроку будет показана страничка Started.htm, где будет опсание того, как найти keltirs и .т.д.
3 g% H/ d- q( N6 ~% |* c! ?0 f+ F. M+ ^8 n% W# x& g
# G* u5 [' [4 ?6 @! D VПри состоянии STARTED будет зарегистрирован дроп «fangs» при убийстве keltirs. Игрок может вернуться к стартовому NCP и спросить о квесте – метод onEvent будет вызван снова. Если у игрока не хватает необходимого количества предметов, то метод check() не переведет квест в следующее состояние и Started.htm будет показана снова. Но если игрок собрал необходимее количество предметов (в данном случае 4 клыка), то метод check() вызовет метод completed() который переведет квест в новое состояние COMPLETED, заберет все клыки, даст карту мира, т.к. это награда за квест, покажет Completed.htm и завершит квест.
+ `3 c- ?/ M' N" {/ z% _8 @! @
7 e( F/ [( C" r$ r7 d& j, W$ n8 h4 q/ f! R
Теперь давайте сделаем наш квест более похожим на то, что он должен из себя представлять.0 F5 J+ X/ b$ p* I; k
Прежде всего у нас есть 3 метода для объявления их в Яве – onTalk, onKill и onEvent. Если методы onTalk и onKill не объявлены, то за них все будет делать метод onEvent, т.е. определять квестовых монстров и вызывать диалоги NCP. Есть примечание, методы onTalk и onKill будут вызывать только диалоги с NCP в зависимости от текущего состояния квеста. Метод onKill будет вызываться только тогда, когда мы убиваем квестового монстра.! a1 I5 b# V" S& y2 {5 i) ]
6 i: k% V. Q1 K' \. H
0 A3 m+ f4 M! [; K0 k& c3 IДавайте рассмотрим как вызывается метод onKill при убийстве keltir в состоянии квеста STARTED:1 ]1 d* O# F6 Q4 s* S
- STARTED.addKillId(KELTIR_NPC_ID)
Скопировать код и метод onKill в классе Quest:
P" N- i6 p' W. g( n) Q/ u1 h
3 s2 I; g9 i% S+ I- class Quest (JQuest):
1 A4 C. S5 ^$ `6 l$ w2 E8 y5 A - ...
+ J& k$ P; E' }, x - def onKill (self,npcId,st):9 R( }7 Y5 z5 q! g& b( O& w3 ]9 i
- if npcId == KELTIR_NPC_ID: f% @3 i; ^# e" f0 w
- n = getCount(st)
+ P! h* Q. Y9 ]3 s8 B# @& T& X - if n == 0:
6 v8 o W+ |% Z' J+ L - return "Chat0.htm"
6 l; q; R3 D# G, f! w - elif n == 1:
: _9 Y; Z1 e) r2 Y: E& G& J6 E/ M' ? - return "Chat1.htm"
. q- Q$ B" Q f. D3 Z1 { - elif n >= 4:: n3 \6 o' D/ w. I8 Z( ^
- return "Chat4.htm"4 i& M( t6 M/ V2 M
- return "Collected "+str(n)+" of 4 fangs"
% H0 [6 F/ G- G) l# x( j! O - return
Скопировать код Метод onKill (а так же метод onTalk) имеет следующие параметры:
3 f J' W' E# r) S
/ R: v. ?% [' s/ k7 n4 F4 a' m
( A8 s! `/ p( l9 ~9 Y; r/ d+ x" D• self – квест: Z+ f" p- ?3 C5 m7 x& P
• npcId – ID NCP, которого мы должны убивать (если это метод onTalk, то ID того NCP, с которым мы должны поговорить).
& G- K* F: ^! v" H$ c; d• st – текущее состояние игрока.
6 t4 T; h- T9 C3 j
+ p/ L0 k4 I5 k+ @2 }: j( z8 X' Y- t9 g5 Y, @6 q" b$ \
В этом методе мы проверяем и отмечаем, является ли убитый NCP keltir’ом. В основном эта проверка не нужна, т.к. у нас только KELTIR_NPC_ID.2 m7 Y, o1 s, v+ a% Y- x, _
$ f# [6 H6 d5 m6 i9 Y
# x+ V; K7 x( SЗатем проверяем количество предметов (в данном случае количество клыков), и если их вообще нет, то возвращаем строку "Chat0.htm", если только один предмет, то возвращаем строку "Chat1.htm", если же предметов 4 или больше, то "Chat4.htm". Если строка возвращена из методов onEvent, onKill или onTalk, то сервер покажет соответствующие htm. В Chat0.htm может иметь следующий текст: «Вы не имеете ни одного клыка, возвращайтесь позже, когда соберете 4 штуки и бла, бла, бла…», в Chat1.htm может быть следующий текст: «У Вас всего 1 клык, по этому соберите еще…». В Chat4.htm – «Вы собрали необходимое количество предметов, возвращайтесь к вашему тренеру, что бы завершить квест…»
t. M' v" x6 J) d5 ]$ c* n
8 A5 a, J3 p+ J8 [5 N
# } _! }3 Z2 X, VПримечание: если в строка return начинается с "<html>", то будет показана страничка html с текстом, который стоит далее. Так вместо:
2 }2 i; l3 k. M7 \) t# areturn "Chat4.htm"
6 ]5 Q7 j& e3 a7 V& N4 Q6 T3 G* b+ [* M0 H8 g- q
! Z; ]& h: c: u; ^( N+ d/ ^можно поставить:
* k3 i, q% _3 Q. r9 i" ~- return "<html><body>Return to your trainer to complete the quest</body></html>"
Скопировать код Так же если строка заканчивается без .htm или в начале нет <html>, то текст будет выведен, как системное сообщение в окне чата. В нашем случае мы сделаем так, что бы при каждом убийстве keltik выводилось системное сообщение: «Собрано N из 4-х клыков».3 `7 q0 ?6 v- t+ N( L7 y) `
7 X- g" O, z. ]* l
; l/ u& [3 D! i4 O8 ]Наш код для onKill имеет один недостаток. Он будет постоянно показывать Chat0.htm, Chat1.htm и Chat4.htm, нам же необходимо, что бы Chat0.htm и Chat1.htm показывались только один раз. Как нам это сделать? С помощью переменных.5 A+ h1 h6 e0 o) U9 L& T0 Q" A
7 T& T! n, O- |9 r# B
7 Z' X) e3 \6 w3 JВ каждом квесте строки могут храниться с помощью переменных. Эти переменные сохраняются в Вашей БД. В каждом методе мы можем назначить, прочитать и удалить переменные. Давайте изменим метод onKill, так что бы каждый диалог вызывался только один раз.
" Z; W1 K! ~# j- def onKill (self,npcId,st):
4 |* u2 c- ^4 j - if npcId == KELTIR_NPC_ID:8 m7 g) K* _4 G0 l1 U9 K z
- n = getCount(st)3 ], n: c; A) K- ]5 L; V
- if n == 0:
, E. s, ]' C) L" C2 a - if st.get('chat0') == None :
" Q, h7 z6 R i1 B# O/ c9 g+ r& I. G8 ^ - st.set("chat0", "true")7 Z! p! U( [6 a7 U) r
- return "Chat0.htm"" K6 E& |+ Z, [; O5 z# ~: M
- elif n == 1:9 n4 W3 z+ f" V9 \) L- k2 a" g
- if st.get('chat1') == None :
8 p; V. j) j8 o% @% [4 v - st.set("chat1", "true")
+ v5 [: @ a0 l& t% v; V6 ^ - return "Chat1.htm"9 n6 {- o! A& F& Q
- elif n >= 4:2 ^1 i9 H: x- X0 i5 p
- return "Chat4.htm"( x# r' w5 k- J" f
- return "Collected "+str(n)+" of 4 fangs"" l+ l1 q# ]: }: G8 c
- return
Скопировать код Если у игрока нет клыков (n=0), то мы получаем занчение переменной 'chat0'. Когда метод onKill вызван в первый раз, то пока ни каких переменных не имеется и python возвращает значение None. В этом случае объявляется переменная и показывается диалог Chat0.htm. Когда мы убиваем keltir, но не получаем с него клык, функция st.get('chat0') возвращает строку true, а не None. И во второй раз окно с Chat0.htm не появится, но в окне чата появится строчка «Collected 0 of 4 fangs». По тому же принципу сделано и с Chat1.htm.
% Y; R6 N, p5 f3 M2 U. l* z3 Y+ g: N+ q+ q( `6 n' j$ @
$ |1 i6 ^! R( N# l& G( W$ OВот конечный рабочий вариант квеста:) J# G; ?2 T8 ~7 R; }. w& {
- import sys
0 c# b. {2 S8 o! w( J5 T2 O* } - from net.sf.l2j.gameserver.model.quest import State# }$ g! H3 |/ S! ?' e* R* I! s- X
- from net.sf.l2j.gameserver.model.quest import QuestState
& ~3 u8 B. v4 q! f6 X+ q5 T$ @7 Y+ } - from net.sf.l2j.gameserver.model.quest.jython import QuestJython as JQuest& }$ Q/ S- c( ]# ], w' i
' X; p$ N# }# `0 P& q. n% e) Y! C- KELTIR_NPC_ID = 120825 M& N$ S& E$ s4 ?8 A. Q. ^
- FANGS_ITEM_ID = 1859" Y# o. h* g+ J3 {4 e# {! i3 A6 z
- DROP_RATE = 500000
% |8 ~( C5 B; w# g! H9 o u( i
$ q5 j: ?. q/ P' w- WORLD_MAP_ITEM_ID = 1665
; p" E# o- E. x1 [) c0 `1 ?& g
7 g; n" T. j6 R0 S- def getCount(st) :
$ v' }3 r! ~" q+ o! e - return st.getQuestItemsCount(FANGS_ITEM_ID)4 u' L5 H; o: h! j6 G8 @8 v/ _
- 7 C5 j, E# v9 z4 h- g
- def completed(st) :' X6 z% m, E: t! J# Y) r5 ^0 ^
- st.setState(COMPLETED)
" H( ]4 G4 q( m3 i0 u! d+ u3 c( M - st.clearQuestDrops()
8 `/ X: m, \ _+ H; @' A$ {) y - st.takeItems(FANGS_ITEM_ID,-1)/ `* O# e- D5 J" r- g$ S2 B, q; S
- st.giveItems(WORLD_MAP_ITEM_ID,1)
7 |( E L/ B; ~1 T- t$ d! }' `9 i - st.exitQuest(False)
6 {0 U ?% `" I. I% ^ - return
$ M B2 m1 w9 A" E - $ G9 s% \ T- z/ o
- def check(st) :
1 W. y Z7 j; V% Y" ]. ] - if getCount(st) >= 4 :) K9 B9 D" F' ]! ?$ A5 q0 C, K9 M
- completed(st)2 T; A' y" w0 i5 k# t
- return+ y+ ?& Z- d+ L& U* f& c3 S) M
1 S- Q2 r$ V7 I0 a- class Quest (JQuest):
2 V1 Y. T1 t5 d+ J- _3 {8 Q - - ?3 `5 l. m7 d* E
- def __init__(self,id,name,descr): JQuest.__init__(self,id,name,descr)
2 x2 X; X: ^6 \# L6 P
* E$ N$ d# x5 E, @- def onEvent (self,event,st):
/ ~6 Y, d/ b3 _; V+ f2 G0 _ - id = st.getState()
* A" C7 Y# H% M4 U, X F, ] - if id == CREATED : st.setState(STARTED) Q ~: K7 f9 M3 s
- elif id == COMPLETED: pass
: c1 l: C& c; t/ Y: N& O- \ - elif id == STARTED : check(st)
* f. O) _. g( X! S- B T5 h9 n# I - return
3 T' i' @# _$ F/ g' H
' S; Q# i* M: g- def onKill (self,npcId,st):- y2 E6 L0 s. W ^; o
- if npcId == KELTIR_NPC_ID:. s6 ~* o6 ^6 e, K$ d
- n = getCount(st)
$ _/ W" ^% q4 Q6 B9 s - if n == 0:6 g- D3 _1 S- Q$ v3 B8 p
- if st.get('chat0') == None :9 c- J* P, z0 e8 x) u' s
- st.set("chat0", "true")8 t0 i' E9 s, k" j t8 | ?& T2 E
- return "Chat0.htm"
! d- o+ x3 c& @" x+ p, x - elif n == 1:
* B3 O+ {+ e6 {$ { - if st.get('chat1') == None :
8 M( p3 m% h& y3 R9 W1 T - st.set("chat1", "true")
\1 J0 N' r8 h4 R( a5 l* f - return "Chat1.htm"
6 H2 N2 n6 ~9 {. O/ v/ Q3 y - elif n >= 4:8 k. l# I l6 r; h. T: T
- return "Chat4.htm"6 o: u4 a: i* @, B9 x4 s+ }, H
- return "Collect "+str(n)+" of 4 fangs"" M- y: _: ?8 ]. z8 t: |
- return
1 s7 z$ T2 D% ]6 m - ; {/ D$ Q: ^7 e8 }: `" T
- QUEST = Quest(201, "Tutorial", "Tutorial quest")* n8 R9 e5 S1 ^8 }' M3 q
- CREATED = State('Start', QUEST)
& G/ U# n% o) Q( u: B" l - STARTED = State('Started', QUEST)9 A8 _' Y8 L) t, y8 }0 H: b
- COMPLETED = State('Completed', QUEST)
: u7 _, t7 A- N, p0 h
/ _8 \- L7 T9 J0 X- QUEST.setInitialState(CREATED)
" i, x) {9 W! l9 u6 e - QUEST.addStartNpc(7056)7 d3 ^$ @" d8 g# R6 m7 ^9 r6 [
- QUEST.addStartNpc(7012). l1 x% x5 j5 e ^* ^( `
- QUEST.addStartNpc(7009)
6 V7 K! ^# o4 o1 c% U, | - QUEST.addStartNpc(7011)7 [4 B- y D. G+ _/ J. l
- ; H w# }# h& F
- STARTED.addQuestDrop(KELTIR_NPC_ID,FANGS_ITEM_ID,DROP_RATE)
4 S$ C+ e/ Q2 a5 i1 w& _2 r2 X - STARTED.addKillId(KELTIR_NPC_ID)" }) G5 I) b& F+ @; Z0 m
- STARTED.addTalkId(7056)! [, N: v' I% L% Z! q" U
- STARTED.addTalkI d(7012)
6 h+ B4 Q, A# Y( C! I2 P+ { - STARTED.addTalkId(7009)
; | c) d; C+ t6 A b/ y. g0 @) u, a - STARTED.addTalkId(7011)
Скопировать код
# Z% H, s5 ^6 N: \4 @9 {5 ]9 B, h+ D) E; y( `2 I% p7 m
|