Зарегистрируйтесь сейчас чтобы найти еще больше друзей, и получить полноценный доступ ко всем функциям сайта!
Для просмотра Вам необходимо авторизоваться Если Вы еще не зарегистрированы, перейдите по ссылке:Зарегистрироваться
x
Хроники Interlude
; e7 J" `- M2 _2 _8 gСборка L2j7 A7 f- X. j* l4 n
Обратите внимание: в файле htm стартового NCP обязательно должна быть ссылка на квест:6 z) w: E! g! O- c# I: O$ U/ D
- STARTED.addQuestDrop(KELTIR_NPC_ID,FANGS_ITEM_ID,DROP_RATE)
Скопировать код Для этого квеста больше ничего не надо. Все необходимое для корректной работы квеста уже добавили. Вот полный текст квеста:
7 {4 p. i- r% U/ k
6 n# d, I: X: o, I* Q8 I* H- if getCount(st) >= 4 :
7 x4 l# X3 q u7 c* g- [% Q - completed(st)
5 z8 h7 [) `& X# z y g4 X - return
) M; D& A( s1 y/ M5 z+ c4 q
8 Z' \% U& }$ n2 a- class Quest (JQuest):5 d$ i! w) M: q+ r
- def __init__(self,id,name,descr): JQuest.__init__(self,id,name,descr)7 ? c8 E" Z- N& y# x: S
- def onEvent (self,event,st):9 ]3 s$ w& v; i2 w: y
- id = st.getState()
& s' ~) W. ]% o* T" `. n - if id == CREATED : st.setState(STARTED); j5 a. p* F+ {* v F" J$ _
- elif id == COMPLETED: pass: m( S- l) N7 q9 Y
- elif id == STARTED : check(st)
7 V8 L8 h* w1 p3 ~: T( H, a3 N - return2 l9 {& A/ ^* Y% Q
5 W6 b1 m' h" q6 `! ]- QUEST = Quest(201,"Tutorial", "Tutorial quest") w1 e& ]: }: G0 `6 R$ N
- CREATED = State('Start', QUEST)
0 f- ]; C; z) B7 y/ I% \ - STARTED = State('Started', QUEST)& [7 [# [- b7 @+ x" {- J
- COMPLETED = State('Completed', QUEST)
# `( ] i# P. b) J @7 K - 1 I. _# X7 g; L5 t: w- `1 `1 Y
- QUEST.setInitialState(CREATED)9 j! j: {2 [2 _9 z% d" |1 j
- QUEST.addStartNpc(7056)
% n' O+ n3 Z7 x" P- ~) O' a - STARTED.addQuestDrop(KELTIR_NPC_ID,FANGS_ITEM_ID,DROP_RATE)
Скопировать код Теперь рассмотрим, как это работает.
4 D' ?7 h' I: x% [! ?0 YИгрок подходит к начальному NCP (в данном случае 7056), нажимает на «Quest». Квест будет создан и состояние квеста перейдет к CREATED и игроку будет показана страничка Start.htm с описанием квеста. Тогда метод onEvent, поле открытия странички Start.htm переведет состояние квеста в STARTED и игроку будет показана страничка Started.htm, где будет опсание того, как найти keltirs и .т.д.
; Q: f* i- I7 K9 c$ ^1 b; ]4 y& u
8 S. ?3 r3 C: N2 O5 K/ k s m7 Q% i% o& @
При состоянии STARTED будет зарегистрирован дроп «fangs» при убийстве keltirs. Игрок может вернуться к стартовому NCP и спросить о квесте – метод onEvent будет вызван снова. Если у игрока не хватает необходимого количества предметов, то метод check() не переведет квест в следующее состояние и Started.htm будет показана снова. Но если игрок собрал необходимее количество предметов (в данном случае 4 клыка), то метод check() вызовет метод completed() который переведет квест в новое состояние COMPLETED, заберет все клыки, даст карту мира, т.к. это награда за квест, покажет Completed.htm и завершит квест.
5 Y* r1 R' _, S# m$ {4 t
4 v0 Z$ d( X) ^ V b4 R" t# t6 h! K) n( s
Теперь давайте сделаем наш квест более похожим на то, что он должен из себя представлять.
; H1 F. \3 n X6 f0 q/ o, FПрежде всего у нас есть 3 метода для объявления их в Яве – onTalk, onKill и onEvent. Если методы onTalk и onKill не объявлены, то за них все будет делать метод onEvent, т.е. определять квестовых монстров и вызывать диалоги NCP. Есть примечание, методы onTalk и onKill будут вызывать только диалоги с NCP в зависимости от текущего состояния квеста. Метод onKill будет вызываться только тогда, когда мы убиваем квестового монстра.
, a* _' E% B. |4 Z8 G. i+ Z7 M" s% ?0 A
2 ^" f, [9 h9 ^7 NДавайте рассмотрим как вызывается метод onKill при убийстве keltir в состоянии квеста STARTED:8 L. H9 ^0 ^ k }4 J$ l
- STARTED.addKillId(KELTIR_NPC_ID)
Скопировать код и метод onKill в классе Quest:- @8 |5 d5 S- J5 l8 R) j6 k
y) {1 k9 z( q6 P+ W! C- \- class Quest (JQuest):
" o$ a v- v5 c% l9 s - ...2 }5 H4 ]: y# s
- def onKill (self,npcId,st):
2 C3 A: \ y5 t+ t4 a - if npcId == KELTIR_NPC_ID:
" n( \6 E' n0 B3 N- l- h9 j& W5 k - n = getCount(st)1 t* {# W8 X# T8 k$ I, ?
- if n == 0:! p1 \* m; C: ~3 O& _* O) ~2 [
- return "Chat0.htm"
& f% X7 O2 i- d4 v+ `9 Z/ h - elif n == 1:% R. Y9 U* J$ W, E
- return "Chat1.htm"
" p+ l2 @4 ?" J1 S - elif n >= 4:0 @7 |- U4 t+ h3 C2 G
- return "Chat4.htm"
( l" O# z0 Z+ L# t7 X9 h - return "Collected "+str(n)+" of 4 fangs"1 [; w. s6 l: N4 g' q( ^& W4 X( Z
- return
Скопировать код Метод onKill (а так же метод onTalk) имеет следующие параметры:
) ^9 K5 O7 C1 [1 `1 _
4 X' ~. m W! ^1 d" h: B8 ~
7 E3 Y9 S3 }9 {3 [) V• self – квест
/ @/ `5 F: Y; x+ E% K• npcId – ID NCP, которого мы должны убивать (если это метод onTalk, то ID того NCP, с которым мы должны поговорить).
% q5 M& O$ s6 I• st – текущее состояние игрока.0 l( P4 H+ `+ ?6 O5 L$ T
% m6 [( C4 _% p @0 e# h% d4 K, R/ c9 A9 l1 Y
В этом методе мы проверяем и отмечаем, является ли убитый NCP keltir’ом. В основном эта проверка не нужна, т.к. у нас только KELTIR_NPC_ID.
: e! i9 a" o% u) f* k {, A7 H9 ?8 f, y8 Y
! z) {3 K% [( J) q5 R
Затем проверяем количество предметов (в данном случае количество клыков), и если их вообще нет, то возвращаем строку "Chat0.htm", если только один предмет, то возвращаем строку "Chat1.htm", если же предметов 4 или больше, то "Chat4.htm". Если строка возвращена из методов onEvent, onKill или onTalk, то сервер покажет соответствующие htm. В Chat0.htm может иметь следующий текст: «Вы не имеете ни одного клыка, возвращайтесь позже, когда соберете 4 штуки и бла, бла, бла…», в Chat1.htm может быть следующий текст: «У Вас всего 1 клык, по этому соберите еще…». В Chat4.htm – «Вы собрали необходимое количество предметов, возвращайтесь к вашему тренеру, что бы завершить квест…»
4 c z3 ~% c( z/ a* p; k7 q k B$ k
6 n3 h, F0 T* [7 {' K9 X+ I
Примечание: если в строка return начинается с "<html>", то будет показана страничка html с текстом, который стоит далее. Так вместо:$ K5 Q6 R- i* P8 f" N
return "Chat4.htm"
5 u- e5 H8 Q8 J! ?0 l
. x7 G- }" P2 F! ?4 p' {8 K
+ D% f7 I7 q+ a% q3 {+ e# c, ]можно поставить:
0 B4 g' M/ O5 A- return "<html><body>Return to your trainer to complete the quest</body></html>"
Скопировать код Так же если строка заканчивается без .htm или в начале нет <html>, то текст будет выведен, как системное сообщение в окне чата. В нашем случае мы сделаем так, что бы при каждом убийстве keltik выводилось системное сообщение: «Собрано N из 4-х клыков».
& l0 Z a) U0 w9 s- z
; i' A4 c# n7 F, ~' U( d0 z9 |% t+ j7 B/ v( Z& e
Наш код для onKill имеет один недостаток. Он будет постоянно показывать Chat0.htm, Chat1.htm и Chat4.htm, нам же необходимо, что бы Chat0.htm и Chat1.htm показывались только один раз. Как нам это сделать? С помощью переменных.7 b, r+ j0 S8 Q1 J9 j
" J6 `* R2 o. L1 r
; I3 S1 e) ]2 d( M% `- w
В каждом квесте строки могут храниться с помощью переменных. Эти переменные сохраняются в Вашей БД. В каждом методе мы можем назначить, прочитать и удалить переменные. Давайте изменим метод onKill, так что бы каждый диалог вызывался только один раз.0 U# b( q0 J6 n0 ]
- def onKill (self,npcId,st):* V3 e6 B7 G; \" |, X
- if npcId == KELTIR_NPC_ID:, s* \+ Z& L5 H* F& L' W6 q# i7 K
- n = getCount(st)
7 c3 |. R- B& }, J - if n == 0:
; x1 _- Q- [4 U& U - if st.get('chat0') == None :( y. R1 r9 R* O
- st.set("chat0", "true")
s1 E- w! e6 I( i% B4 N' a - return "Chat0.htm"
/ \4 C8 O: o/ R1 c# t( y \- v - elif n == 1:/ h. [9 \7 R* A9 _4 C" {3 G' I. i
- if st.get('chat1') == None :
% A; c1 ?( z. D5 n; U - st.set("chat1", "true")# v; f8 ]$ C0 n- `
- return "Chat1.htm"
' S$ x T! q& t* p9 g6 U - elif n >= 4:0 x$ O& r8 @2 r1 f+ c
- return "Chat4.htm"" y" t0 h% o2 W) _
- return "Collected "+str(n)+" of 4 fangs"1 R% K4 Y& g9 w5 p9 A
- return
Скопировать код Если у игрока нет клыков (n=0), то мы получаем занчение переменной 'chat0'. Когда метод onKill вызван в первый раз, то пока ни каких переменных не имеется и python возвращает значение None. В этом случае объявляется переменная и показывается диалог Chat0.htm. Когда мы убиваем keltir, но не получаем с него клык, функция st.get('chat0') возвращает строку true, а не None. И во второй раз окно с Chat0.htm не появится, но в окне чата появится строчка «Collected 0 of 4 fangs». По тому же принципу сделано и с Chat1.htm.
" V3 R( Y; m0 G7 h+ g+ T9 N) U9 ?
( n, w& \2 ^, n1 `" ?
1 a' L0 H: [( iВот конечный рабочий вариант квеста:: m) v: k5 O' K w
- import sys" m, \4 [5 w4 p# k, X; W
- from net.sf.l2j.gameserver.model.quest import State$ `" J, U. Y' c, a4 E
- from net.sf.l2j.gameserver.model.quest import QuestState& ^/ Z. V; _- c8 M
- from net.sf.l2j.gameserver.model.quest.jython import QuestJython as JQuest- A$ w3 i8 {$ p2 u
& S0 v8 C& h9 ~* A* S/ |! k0 Q- KELTIR_NPC_ID = 12082
9 e! w$ q E( Q9 R# {( a Y - FANGS_ITEM_ID = 1859 h6 s* r" n- ~: y
- DROP_RATE = 500000* s$ u4 A* x* N( P
* u' ^7 T( D0 Z% b5 d- WORLD_MAP_ITEM_ID = 1665( \6 C/ G( D) T6 b" |% Y% m
- ! P' E4 P6 Z. a' @. ]
- def getCount(st) :1 Z% D% I0 `9 m- Z$ t8 j; M1 ^
- return st.getQuestItemsCount(FANGS_ITEM_ID)
0 C! T& a" x3 c$ |
- `0 U; t0 m! S" W) W- def completed(st) :5 H4 O m5 Z8 `; f! j( |# x% a
- st.setState(COMPLETED)
. K8 J& W7 o3 O2 Z+ s4 Z - st.clearQuestDrops()5 R# J; n4 Z/ Y5 r6 W
- st.takeItems(FANGS_ITEM_ID,-1)
# x v- y3 ?! ] - st.giveItems(WORLD_MAP_ITEM_ID,1)7 x& [6 G/ [3 z5 k3 X* \2 k9 b
- st.exitQuest(False)
4 m+ c- B. \8 b3 [1 O - return
% g* a- @, S5 V5 o/ ? - " p0 }7 c% Q1 h8 C* o0 X3 g
- def check(st) :
0 G. f9 n* i' K$ h& l' N8 e* e3 X5 N - if getCount(st) >= 4 : B; Z0 ~7 U- }% W4 J0 e
- completed(st)4 T9 |$ d! x: ~. t
- return9 e7 C! s1 d" a' {; G/ \
- ' P2 c) y: G' `
- class Quest (JQuest):. N) N, K5 \4 f" ?
( b% Q/ m$ z' h: d' M" M& p& K- def __init__(self,id,name,descr): JQuest.__init__(self,id,name,descr)( B* d. s/ e% y( |; j
- + |: A3 _+ o5 U7 \# ~6 c
- def onEvent (self,event,st):0 U% Q5 d0 p; q4 T
- id = st.getState()- }& e1 ~6 z- b5 t; V
- if id == CREATED : st.setState(STARTED)
" T5 p/ G7 G6 h+ J - elif id == COMPLETED: pass3 E: g/ a! N; z+ E( v
- elif id == STARTED : check(st)3 h8 ]3 C2 L( L
- return
& r0 L( ^! X! \9 I
/ ]1 a1 B) U7 x- def onKill (self,npcId,st):
9 l$ }2 L, _! K5 c' h - if npcId == KELTIR_NPC_ID:( U3 {3 K3 v) s) V8 S' @( G; i
- n = getCount(st)
) m3 J7 o+ H; F9 u( m - if n == 0:
]* L2 ]% h( u - if st.get('chat0') == None :
, B& @6 \0 j" o - st.set("chat0", "true"), h9 Q1 ]! T; _% Z5 H% y
- return "Chat0.htm"
8 J& u0 M J8 C - elif n == 1: B4 Z" B, \/ `% W7 v3 L/ n8 x I
- if st.get('chat1') == None :
$ A6 D. ~7 m7 B7 \6 H! z - st.set("chat1", "true")
- y" z% f/ I, L) ^8 `( H - return "Chat1.htm"9 ^" i; J' i# o: e4 s: k" H* n, x- T
- elif n >= 4:: R% r/ s& E* x. S" z; o
- return "Chat4.htm"* a) }- M t- B3 v( T8 [
- return "Collect "+str(n)+" of 4 fangs"
3 j' V& w% N- s/ k5 e7 J - return
* K2 i$ @: @% }5 V - ' g6 A8 D8 C. A* Q' f7 T
- QUEST = Quest(201, "Tutorial", "Tutorial quest")
2 ~* |5 K4 P# k/ A. B O - CREATED = State('Start', QUEST)* `4 ]+ x/ C: B2 X
- STARTED = State('Started', QUEST)5 s* u- E/ s" m$ I
- COMPLETED = State('Completed', QUEST) Z6 M$ k/ k( S# h( H d
- # ?) r' F4 {9 a" e! k' k# O
- QUEST.setInitialState(CREATED)
0 `, x0 o4 Q1 L$ I& j- E' b - QUEST.addStartNpc(7056), n& v* ~' }" O, ?( ?6 }: Y; z
- QUEST.addStartNpc(7012)
9 f. O6 Z; ?/ f4 L' P& A) X - QUEST.addStartNpc(7009)2 h. B2 d3 {0 x1 N- N
- QUEST.addStartNpc(7011)) g5 j3 g" s' X A# r& G& L+ K
0 Q! d* B7 d. F- STARTED.addQuestDrop(KELTIR_NPC_ID,FANGS_ITEM_ID,DROP_RATE)
1 V# P1 i9 S' o8 ~3 }4 _) \ - STARTED.addKillId(KELTIR_NPC_ID)
' b5 b; b5 m1 U9 l; j y" u/ U ? - STARTED.addTalkId(7056)
H: c: a" j0 h+ ?6 p# N$ S - STARTED.addTalkI d(7012)
) Z$ j- m! c& L+ z - STARTED.addTalkId(7009)$ c* X5 ?2 g) W
- STARTED.addTalkId(7011)
Скопировать код
7 I. d( Q8 z& U% {8 f/ s+ D9 o5 R; ?" c/ e/ w
|