Зарегистрируйтесь сейчас чтобы найти еще больше друзей, и получить полноценный доступ ко всем функциям сайта!
Для просмотра Вам необходимо авторизоваться Если Вы еще не зарегистрированы, перейдите по ссылке:Зарегистрироваться
x
Хроники Interlude
' o3 W( P4 q; EСборка L2j' \" d) X% Q; h, L
Обратите внимание: в файле htm стартового NCP обязательно должна быть ссылка на квест:
7 d- Y e* ?) ]1 K( i }- STARTED.addQuestDrop(KELTIR_NPC_ID,FANGS_ITEM_ID,DROP_RATE)
Скопировать код Для этого квеста больше ничего не надо. Все необходимое для корректной работы квеста уже добавили. Вот полный текст квеста:
* U2 ]+ w8 x0 R% C, T' _/ z( G5 I9 m
% o6 V! N4 H c. ]3 _; g- if getCount(st) >= 4 :- e d- Y9 A6 q( ]3 Z
- completed(st)
- U# L( Z5 Q8 `: H! s. } - return6 i/ K6 K" m3 E9 ~5 q5 h# @' F( B, n
- & E+ F, x2 y( ?
- class Quest (JQuest):
, Q% |5 T* a6 [3 U; n+ L - def __init__(self,id,name,descr): JQuest.__init__(self,id,name,descr)0 [/ K4 N1 j+ X
- def onEvent (self,event,st):
+ [: W! V& Q% z/ E: v3 R: C! S - id = st.getState()
, z; D# a- j) [2 H - if id == CREATED : st.setState(STARTED)
$ I6 }# l' b( j; _/ V - elif id == COMPLETED: pass5 R% b/ T" `. g _0 V
- elif id == STARTED : check(st), B: o- Z0 I, c* ?( r$ V& i1 n
- return- H2 M) O; u2 t2 |% @& `
2 ^4 E: C+ s, |0 [7 n0 Z- QUEST = Quest(201,"Tutorial", "Tutorial quest")
1 ^4 i, h+ h$ d - CREATED = State('Start', QUEST)& z7 y- X- o2 x9 Z! D7 `
- STARTED = State('Started', QUEST)& E; {: @* V7 O- ]- B3 U+ F' r: ^( V
- COMPLETED = State('Completed', QUEST)
/ O+ N4 _: W v. [
& A* j9 M% I: d( u; g B. R" D* K- QUEST.setInitialState(CREATED): H* m5 X; {; \7 m) ^
- QUEST.addStartNpc(7056)- [/ ]/ j& P$ X9 v
- STARTED.addQuestDrop(KELTIR_NPC_ID,FANGS_ITEM_ID,DROP_RATE)
Скопировать код Теперь рассмотрим, как это работает.# @0 s2 I }, ?( h5 |) b
Игрок подходит к начальному NCP (в данном случае 7056), нажимает на «Quest». Квест будет создан и состояние квеста перейдет к CREATED и игроку будет показана страничка Start.htm с описанием квеста. Тогда метод onEvent, поле открытия странички Start.htm переведет состояние квеста в STARTED и игроку будет показана страничка Started.htm, где будет опсание того, как найти keltirs и .т.д.
4 c2 y2 M2 B) O e% N9 M
( E7 m' k M* g3 }# ?% j# e, l# ?8 F6 d( ^
При состоянии STARTED будет зарегистрирован дроп «fangs» при убийстве keltirs. Игрок может вернуться к стартовому NCP и спросить о квесте – метод onEvent будет вызван снова. Если у игрока не хватает необходимого количества предметов, то метод check() не переведет квест в следующее состояние и Started.htm будет показана снова. Но если игрок собрал необходимее количество предметов (в данном случае 4 клыка), то метод check() вызовет метод completed() который переведет квест в новое состояние COMPLETED, заберет все клыки, даст карту мира, т.к. это награда за квест, покажет Completed.htm и завершит квест.
+ L$ @' ]- v+ `& P! K
5 ~3 d. D& {% O8 X
4 Q, T3 S# M# c0 _) L7 |Теперь давайте сделаем наш квест более похожим на то, что он должен из себя представлять.& A/ b7 v. [" p' r+ j6 h
Прежде всего у нас есть 3 метода для объявления их в Яве – onTalk, onKill и onEvent. Если методы onTalk и onKill не объявлены, то за них все будет делать метод onEvent, т.е. определять квестовых монстров и вызывать диалоги NCP. Есть примечание, методы onTalk и onKill будут вызывать только диалоги с NCP в зависимости от текущего состояния квеста. Метод onKill будет вызываться только тогда, когда мы убиваем квестового монстра.
+ Z$ I" V$ g# e% Q! m6 `7 g" H. D2 K" [& h: e
2 k. e* w% A1 g8 d
Давайте рассмотрим как вызывается метод onKill при убийстве keltir в состоянии квеста STARTED:7 ?4 [# u# h/ q, ^% g- F9 G: ]
- STARTED.addKillId(KELTIR_NPC_ID)
Скопировать код и метод onKill в классе Quest:
9 {& B4 p$ d, s! h6 g; j. s; V% i/ U; M
- class Quest (JQuest):8 t7 ~8 d. h9 {/ [) v
- ...0 ?1 Z R; c" O: \
- def onKill (self,npcId,st):
) [; N" N0 B3 l% K' t- J - if npcId == KELTIR_NPC_ID: |; V! b1 `/ J8 c6 m& \8 ]
- n = getCount(st)) A4 i# ~$ M5 d$ e* H
- if n == 0:4 E/ ^" U1 d4 q) l2 e
- return "Chat0.htm"
0 s9 k+ O# a2 q: ? - elif n == 1:
" C' D, t( x- a - return "Chat1.htm"
& w) d$ V+ K# B* K+ P - elif n >= 4:0 t3 N/ A: v$ Y& t2 E% ^
- return "Chat4.htm"
n3 I2 C$ w) f* n( f, w - return "Collected "+str(n)+" of 4 fangs"0 l. [+ o" _" Z
- return
Скопировать код Метод onKill (а так же метод onTalk) имеет следующие параметры:
+ q" f# ]0 k: f* {- m: J' n$ i
3 T* |9 @, ~3 e' P! l9 e3 A
4 w1 x7 J+ x0 R- X• self – квест
" Q& P& _' W1 x6 K4 Z+ G$ N• npcId – ID NCP, которого мы должны убивать (если это метод onTalk, то ID того NCP, с которым мы должны поговорить).0 W; m* h2 |7 G) t' P) J+ z
• st – текущее состояние игрока.1 }. Y) x5 Q! [
* S+ p7 u- L# o( d# e4 Y
' A$ y/ z3 Q# g2 f; g" h
В этом методе мы проверяем и отмечаем, является ли убитый NCP keltir’ом. В основном эта проверка не нужна, т.к. у нас только KELTIR_NPC_ID.
. }; Q W8 ?2 r# `; H4 q4 f/ @6 W- [' a1 L. D- h/ l: N0 D0 V+ @
$ t9 J; U8 Q# ZЗатем проверяем количество предметов (в данном случае количество клыков), и если их вообще нет, то возвращаем строку "Chat0.htm", если только один предмет, то возвращаем строку "Chat1.htm", если же предметов 4 или больше, то "Chat4.htm". Если строка возвращена из методов onEvent, onKill или onTalk, то сервер покажет соответствующие htm. В Chat0.htm может иметь следующий текст: «Вы не имеете ни одного клыка, возвращайтесь позже, когда соберете 4 штуки и бла, бла, бла…», в Chat1.htm может быть следующий текст: «У Вас всего 1 клык, по этому соберите еще…». В Chat4.htm – «Вы собрали необходимое количество предметов, возвращайтесь к вашему тренеру, что бы завершить квест…»
% s5 k8 B) s! J6 }0 |' j! S
J, _5 `' B' y0 p3 \/ n% d" f
E2 k: n2 q5 [. ~Примечание: если в строка return начинается с "<html>", то будет показана страничка html с текстом, который стоит далее. Так вместо:* R/ o t- [% ]
return "Chat4.htm"
: l) O. a6 p2 d, G* ^1 O4 E/ a0 {% i+ \; C1 [9 r0 v
3 \+ y% q! A( V# ^9 {можно поставить:
; l' R$ ?' `. A5 z0 R/ E9 E- return "<html><body>Return to your trainer to complete the quest</body></html>"
Скопировать код Так же если строка заканчивается без .htm или в начале нет <html>, то текст будет выведен, как системное сообщение в окне чата. В нашем случае мы сделаем так, что бы при каждом убийстве keltik выводилось системное сообщение: «Собрано N из 4-х клыков»., u- i; j: |# g8 I; i/ i" A$ W
. j6 U, \1 A1 b) ~: a$ Z. o- e
& T: g! H2 k& m# J$ A' ~% Q; @9 cНаш код для onKill имеет один недостаток. Он будет постоянно показывать Chat0.htm, Chat1.htm и Chat4.htm, нам же необходимо, что бы Chat0.htm и Chat1.htm показывались только один раз. Как нам это сделать? С помощью переменных." A* P2 C5 d) b1 O, N) y6 G
6 W- x1 \+ v# @6 K" a6 G
2 {$ M) U8 K- {: f4 ~В каждом квесте строки могут храниться с помощью переменных. Эти переменные сохраняются в Вашей БД. В каждом методе мы можем назначить, прочитать и удалить переменные. Давайте изменим метод onKill, так что бы каждый диалог вызывался только один раз., `9 p9 V+ s7 l* \6 D) v: V: p2 S6 e6 [
- def onKill (self,npcId,st):8 e1 \* {% |) \" d7 i: }2 h- `4 J
- if npcId == KELTIR_NPC_ID:
! E7 ~2 \; P& w - n = getCount(st)9 O8 ^7 q: S# g- u, v; Z$ f `
- if n == 0:
; g5 C3 a3 [) s; ]3 o& v - if st.get('chat0') == None :
" i8 o* u0 Y( f* C - st.set("chat0", "true")
$ r" ^) T$ l: L. P" H - return "Chat0.htm"/ U+ q6 y7 y: t, A
- elif n == 1:# S) M! C, S% O) H
- if st.get('chat1') == None :, i: _: Y6 \$ o8 r* A
- st.set("chat1", "true")
\4 N) J: g0 b7 e# i1 i# Q' i b - return "Chat1.htm"
) b% r1 L# B2 y- C; \( M - elif n >= 4:) ^! I# [# P' Q5 D0 n% `7 [' H
- return "Chat4.htm"
9 f' b: ^: F! q1 E* @3 Z: n - return "Collected "+str(n)+" of 4 fangs"
& P- X4 E# a& z% }) x8 u# X2 i - return
Скопировать код Если у игрока нет клыков (n=0), то мы получаем занчение переменной 'chat0'. Когда метод onKill вызван в первый раз, то пока ни каких переменных не имеется и python возвращает значение None. В этом случае объявляется переменная и показывается диалог Chat0.htm. Когда мы убиваем keltir, но не получаем с него клык, функция st.get('chat0') возвращает строку true, а не None. И во второй раз окно с Chat0.htm не появится, но в окне чата появится строчка «Collected 0 of 4 fangs». По тому же принципу сделано и с Chat1.htm.
/ f% E3 _# T# n/ D8 V3 B+ @6 n0 I4 t( g- N/ V5 I% }
0 h8 F; b7 E% u- q+ NВот конечный рабочий вариант квеста:* g8 R. |* v( B7 t' w" X" k! T
- import sys1 b7 A/ q: x- T: X$ q# A
- from net.sf.l2j.gameserver.model.quest import State: r6 U6 L3 T W! h' q
- from net.sf.l2j.gameserver.model.quest import QuestState
' d, F$ {3 T$ R. V O - from net.sf.l2j.gameserver.model.quest.jython import QuestJython as JQuest
( `+ b4 B6 [+ j. A - 4 c1 A+ l$ V* ~9 z* ~$ U) h
- KELTIR_NPC_ID = 12082
) N, j' _& m4 e* M3 P - FANGS_ITEM_ID = 1859
" w; { W$ M* T& G: C4 H( w - DROP_RATE = 500000& l, C6 s6 X8 w
- . G" _! A/ ~9 l. }# ~' s
- WORLD_MAP_ITEM_ID = 1665) d& Y6 s2 Q. u1 D t
- 8 t- b m' W7 y) y, U
- def getCount(st) :
- H* m1 s& I8 V+ D- t- B - return st.getQuestItemsCount(FANGS_ITEM_ID)4 D5 n _: S7 d; n2 Y# ], H$ L8 E0 z
& T& B+ |1 x: D9 H: |+ c- def completed(st) :
7 W4 K, S% W2 z( M* O - st.setState(COMPLETED) Q) y# x( y0 v8 r1 R0 O
- st.clearQuestDrops()2 }$ O& X. N! [6 g4 `
- st.takeItems(FANGS_ITEM_ID,-1)5 ~$ x! O: h: U& ^ k1 Y
- st.giveItems(WORLD_MAP_ITEM_ID,1)
3 ~6 O, K9 Q/ r0 o) E, c+ H - st.exitQuest(False)( ^% M; g1 J2 E/ P* }
- return! S% i, |6 C2 b, ^$ i7 o0 I
6 {2 a( ]( w* v; F+ o, w, ~- def check(st) :2 w' @( ~; @4 Y3 c, i. L L" p
- if getCount(st) >= 4 :
2 a% t9 [. u# p! d) S2 W, R - completed(st)1 s8 [( i' i: T- a2 O M
- return
, o$ b" \1 h" ] - 0 N8 F. S8 V4 M. F
- class Quest (JQuest):
" H/ ^" ?+ w7 K1 g: t
7 U' S" H& ?+ U2 ^- def __init__(self,id,name,descr): JQuest.__init__(self,id,name,descr); \: M; o; M1 z* N& a* N R T
- 1 T1 W: N# x/ y# E( ]% u2 g* U" K
- def onEvent (self,event,st):
2 k/ ~$ D, [$ U) ~& m' E - id = st.getState()9 Q9 k2 t- n0 O& x: N- C
- if id == CREATED : st.setState(STARTED)' N' X. [* d7 @
- elif id == COMPLETED: pass
% S9 O4 P- T |4 V6 y* \* A - elif id == STARTED : check(st): i/ B% \5 m5 o
- return0 S; { ~8 n# O$ W
1 F6 @( k. F+ v$ Y, Q9 X- def onKill (self,npcId,st):
" w8 T' Y* B: I8 e Z& T - if npcId == KELTIR_NPC_ID:
+ E- V# f' v J8 M# v4 {0 E5 Y - n = getCount(st)2 O8 _+ |( S) H" P$ ^
- if n == 0:
. W( a1 g9 w) }9 |( v - if st.get('chat0') == None :0 s8 G7 k& b; A' y3 A @) I1 x3 b
- st.set("chat0", "true")
- q0 o& L0 ?' F) F0 l# ] - return "Chat0.htm"
1 c& I: p5 E' j4 J1 `& Y5 ^ - elif n == 1:
, u/ |- I4 L- @' M& A. z7 Q - if st.get('chat1') == None :
$ K9 P) K. d# Z' _" j) Z - st.set("chat1", "true")
4 p; Y( @9 I" H( I. O7 B1 p/ I& Q - return "Chat1.htm"; S/ h3 U+ ~) l% s$ C
- elif n >= 4:
* D( I& s: E6 j4 K6 P' `3 N& A - return "Chat4.htm"
# }/ o, @/ D, K$ k' ~4 a5 e - return "Collect "+str(n)+" of 4 fangs"' L" ]1 }& h* i% P( X
- return
$ f4 q2 A& j3 g - 3 N, i8 ~& A. x h2 U. S0 S' Z
- QUEST = Quest(201, "Tutorial", "Tutorial quest")
8 `5 G" u* A: o0 f l - CREATED = State('Start', QUEST)' d* v. g1 [ O6 ~
- STARTED = State('Started', QUEST)
$ [. \, ]1 W6 ^. c - COMPLETED = State('Completed', QUEST)
" P5 |8 p. N8 ~7 h! | - , t( T# q' U' V0 h! t
- QUEST.setInitialState(CREATED)$ m7 l$ _8 k, ]7 \+ J
- QUEST.addStartNpc(7056)2 L6 }$ F9 h# g; E; N: P* c
- QUEST.addStartNpc(7012)
! Y5 ^- ^7 {1 j% y2 v - QUEST.addStartNpc(7009)$ y8 Q7 p/ D# z5 G1 F1 L+ _, \
- QUEST.addStartNpc(7011)
2 z' `3 c& P, x" K
1 P% G4 p# X7 D* z. m9 G- STARTED.addQuestDrop(KELTIR_NPC_ID,FANGS_ITEM_ID,DROP_RATE)
2 M8 i- b0 S+ d/ K - STARTED.addKillId(KELTIR_NPC_ID)/ [ R4 {; N( K% o" y% q& @& N
- STARTED.addTalkId(7056)
5 g# N: P# Y- {1 J3 U - STARTED.addTalkI d(7012)
& ?8 S, P; w9 b. J; t - STARTED.addTalkId(7009)! |8 ^$ t0 ^ g' X' f# c! i
- STARTED.addTalkId(7011)
Скопировать код
, \- Q2 G0 `+ ]2 G! W9 r" T% g* b% w i5 P4 ^# V% b
|