Зарегистрируйтесь сейчас чтобы найти еще больше друзей, и получить полноценный доступ ко всем функциям сайта!
Для просмотра Вам необходимо авторизоваться Если Вы еще не зарегистрированы, перейдите по ссылке:Зарегистрироваться
x
Хроники Interlude
, { L, r2 t4 M8 a- l- iСборка L2j) {6 P) C8 t/ y. m
Обратите внимание: в файле htm стартового NCP обязательно должна быть ссылка на квест:: d, B7 b/ H. p; s. j8 J4 q
- STARTED.addQuestDrop(KELTIR_NPC_ID,FANGS_ITEM_ID,DROP_RATE)
Скопировать код Для этого квеста больше ничего не надо. Все необходимое для корректной работы квеста уже добавили. Вот полный текст квеста:
P; d) k, h! r% [$ u) F& O: X# |: A) n& p
- if getCount(st) >= 4 :9 p: l: x: W& m% l
- completed(st)/ c' y( {% Q5 Q5 j0 ?
- return
* N2 T& i2 q: ~. V
8 |1 Q5 o, f) Q4 P$ Y- class Quest (JQuest):0 f5 Y. w! L: D' G4 X
- def __init__(self,id,name,descr): JQuest.__init__(self,id,name,descr)
4 ^3 a8 b* `: K0 v, b' d, e1 R+ E - def onEvent (self,event,st):2 q2 X2 L" ]) \ F# j" J8 t
- id = st.getState()
+ Y" B/ _) o$ K* Q; ? - if id == CREATED : st.setState(STARTED)) B# E6 C, O8 @: {; G2 E
- elif id == COMPLETED: pass
1 |% H: o# Q4 r - elif id == STARTED : check(st)) D+ O3 ^& n$ Z( \- D2 w
- return4 K' u# h, |1 S+ k& I
- ) n7 ?9 P! F. @" i( I- {4 I, B4 k; V
- QUEST = Quest(201,"Tutorial", "Tutorial quest")3 j* R0 ~6 b ?1 [7 J
- CREATED = State('Start', QUEST)
' N% u- h& r7 X9 @3 T - STARTED = State('Started', QUEST)! g) i" h/ J# m7 c; x
- COMPLETED = State('Completed', QUEST)! V' H, u! j+ L0 v2 o9 H
- 2 O5 i% | H0 y# e" T% K7 Z* d
- QUEST.setInitialState(CREATED)
; N* J' ?/ B( O4 Y - QUEST.addStartNpc(7056)
" v' h! v1 J1 x. \. y - STARTED.addQuestDrop(KELTIR_NPC_ID,FANGS_ITEM_ID,DROP_RATE)
Скопировать код Теперь рассмотрим, как это работает.
. P6 k3 E+ ~, }1 c/ z- G5 o! a9 k% \* bИгрок подходит к начальному NCP (в данном случае 7056), нажимает на «Quest». Квест будет создан и состояние квеста перейдет к CREATED и игроку будет показана страничка Start.htm с описанием квеста. Тогда метод onEvent, поле открытия странички Start.htm переведет состояние квеста в STARTED и игроку будет показана страничка Started.htm, где будет опсание того, как найти keltirs и .т.д.0 O0 [8 A; b" i+ o! ] T/ o7 c7 r
, V6 Y- ~! C: E+ `4 u
/ r' w( d5 N% X3 m4 ~8 E3 jПри состоянии STARTED будет зарегистрирован дроп «fangs» при убийстве keltirs. Игрок может вернуться к стартовому NCP и спросить о квесте – метод onEvent будет вызван снова. Если у игрока не хватает необходимого количества предметов, то метод check() не переведет квест в следующее состояние и Started.htm будет показана снова. Но если игрок собрал необходимее количество предметов (в данном случае 4 клыка), то метод check() вызовет метод completed() который переведет квест в новое состояние COMPLETED, заберет все клыки, даст карту мира, т.к. это награда за квест, покажет Completed.htm и завершит квест.
2 z V7 V% `( [( w/ M# k" y) Z( A! o6 b
3 s+ U- K/ t3 a u5 Y RТеперь давайте сделаем наш квест более похожим на то, что он должен из себя представлять.; @4 U I4 M! l; O: [
Прежде всего у нас есть 3 метода для объявления их в Яве – onTalk, onKill и onEvent. Если методы onTalk и onKill не объявлены, то за них все будет делать метод onEvent, т.е. определять квестовых монстров и вызывать диалоги NCP. Есть примечание, методы onTalk и onKill будут вызывать только диалоги с NCP в зависимости от текущего состояния квеста. Метод onKill будет вызываться только тогда, когда мы убиваем квестового монстра.
& y8 ^# i, o, q/ S7 p8 d1 z W% i' l1 b
- P5 } U1 S) t5 z/ o: oДавайте рассмотрим как вызывается метод onKill при убийстве keltir в состоянии квеста STARTED:
: a0 ~# w" Z- b& G4 n9 Y- STARTED.addKillId(KELTIR_NPC_ID)
Скопировать код и метод onKill в классе Quest:
& k5 e. [4 r9 M7 |/ {7 ~3 v- l# O/ k- I/ N% B; Z
- class Quest (JQuest):
8 {; M& F/ ?% C9 r2 r - ..." U; o" s: ]3 a3 u* D5 B' M4 X
- def onKill (self,npcId,st):
) T) t' Z2 Y9 r/ w2 f - if npcId == KELTIR_NPC_ID:
5 K/ W2 R( c. P: I# W0 ? - n = getCount(st)) r& `2 E' |; d+ R' t
- if n == 0:
' `2 q3 l& e1 y6 {' w- ]% X5 t2 H - return "Chat0.htm"* e7 ]5 P, f! D$ ?
- elif n == 1:, x- N( S7 V$ s# P. s2 ]
- return "Chat1.htm"7 @7 J! k# b( }8 r
- elif n >= 4:5 X! n/ `6 b+ _# J6 H/ m* [: n
- return "Chat4.htm"+ ^# n9 L- {7 _# C N8 ?# Z4 w
- return "Collected "+str(n)+" of 4 fangs"
6 @8 D4 e! D D" E* b1 ^! \$ s - return
Скопировать код Метод onKill (а так же метод onTalk) имеет следующие параметры:. F' V, ^* T7 W* @
3 ~; m a9 R* ?) }9 G( E; J! ~* m, l
; q4 R+ k8 W: c' P, F2 y- Y+ S ^
• self – квест
' H) o5 U* ~- Q• npcId – ID NCP, которого мы должны убивать (если это метод onTalk, то ID того NCP, с которым мы должны поговорить).0 A w- ?9 s0 G+ l$ l
• st – текущее состояние игрока./ x: o$ [& Y* C8 c
" ?. i' l6 A/ X: R: }/ C
' ~6 K' t3 `2 k4 G% D6 M3 r! QВ этом методе мы проверяем и отмечаем, является ли убитый NCP keltir’ом. В основном эта проверка не нужна, т.к. у нас только KELTIR_NPC_ID. a8 k; z1 [4 N5 L8 Q( P
& E; A/ F. s4 n# g
) Y& M$ v2 M# s6 @) Z# ~5 LЗатем проверяем количество предметов (в данном случае количество клыков), и если их вообще нет, то возвращаем строку "Chat0.htm", если только один предмет, то возвращаем строку "Chat1.htm", если же предметов 4 или больше, то "Chat4.htm". Если строка возвращена из методов onEvent, onKill или onTalk, то сервер покажет соответствующие htm. В Chat0.htm может иметь следующий текст: «Вы не имеете ни одного клыка, возвращайтесь позже, когда соберете 4 штуки и бла, бла, бла…», в Chat1.htm может быть следующий текст: «У Вас всего 1 клык, по этому соберите еще…». В Chat4.htm – «Вы собрали необходимое количество предметов, возвращайтесь к вашему тренеру, что бы завершить квест…»- s4 {9 i8 h7 Y0 Y
" U% R7 K; U. b' O$ `
' \* C2 b% l. i* d% o; _+ c- {Примечание: если в строка return начинается с "<html>", то будет показана страничка html с текстом, который стоит далее. Так вместо:# i/ i& j7 N; j# \- |" F5 a9 N2 X
return "Chat4.htm"
5 z* ]0 Y: @ m* ]; Q1 Q
. Q( J9 m* o6 `8 m+ H' g. d' g/ x- Z4 J" {* ~7 S
можно поставить:
' y: y! w6 P/ T7 S, O3 a4 t& S( u- return "<html><body>Return to your trainer to complete the quest</body></html>"
Скопировать код Так же если строка заканчивается без .htm или в начале нет <html>, то текст будет выведен, как системное сообщение в окне чата. В нашем случае мы сделаем так, что бы при каждом убийстве keltik выводилось системное сообщение: «Собрано N из 4-х клыков».
5 q* x2 C8 f- V. }
+ P0 c5 A: g, V2 M% M5 t5 ^
% |1 V, o0 n) ~* gНаш код для onKill имеет один недостаток. Он будет постоянно показывать Chat0.htm, Chat1.htm и Chat4.htm, нам же необходимо, что бы Chat0.htm и Chat1.htm показывались только один раз. Как нам это сделать? С помощью переменных.8 R: Y; i8 k) |& G, q
- b1 F9 B$ A6 p) B4 \. K4 j
5 ^, t8 O# Z {% ^- c
В каждом квесте строки могут храниться с помощью переменных. Эти переменные сохраняются в Вашей БД. В каждом методе мы можем назначить, прочитать и удалить переменные. Давайте изменим метод onKill, так что бы каждый диалог вызывался только один раз.: P" ^2 G- x& O- f
- def onKill (self,npcId,st):& e% J, F6 L; ?+ z
- if npcId == KELTIR_NPC_ID:2 u7 M! p5 N; T {3 N( z w
- n = getCount(st); W8 u! C& r4 e/ _
- if n == 0:
4 R( M7 F6 M$ O! U! p: L- c* m# a - if st.get('chat0') == None :
5 V; x+ v. W$ b8 e+ Z - st.set("chat0", "true"), D- R. F- e- H5 c* u4 F
- return "Chat0.htm": s8 x/ t7 K/ A5 [. h
- elif n == 1:0 j4 D, U1 Z1 ]. m# k" G
- if st.get('chat1') == None :8 B& j% m" \# v
- st.set("chat1", "true")
/ ]+ y3 N2 S( }- g9 `: m# c - return "Chat1.htm"
& F. {2 B# t& g: C& q2 ~ - elif n >= 4:
4 z3 z2 n9 @' O0 q- H+ q$ W1 G( r - return "Chat4.htm"
/ m' L( @' M0 A5 R: s0 H* s* V+ O - return "Collected "+str(n)+" of 4 fangs"
, D+ C& a- c0 Z* U. E: Q - return
Скопировать код Если у игрока нет клыков (n=0), то мы получаем занчение переменной 'chat0'. Когда метод onKill вызван в первый раз, то пока ни каких переменных не имеется и python возвращает значение None. В этом случае объявляется переменная и показывается диалог Chat0.htm. Когда мы убиваем keltir, но не получаем с него клык, функция st.get('chat0') возвращает строку true, а не None. И во второй раз окно с Chat0.htm не появится, но в окне чата появится строчка «Collected 0 of 4 fangs». По тому же принципу сделано и с Chat1.htm.: P0 ~3 v$ C; N
* o6 G( V' w5 b1 I; t* V- [+ `& E% Z
Вот конечный рабочий вариант квеста:! a0 Q0 s- L3 I h+ Z3 |$ P3 @8 g
- import sys
$ R8 u/ t. x( I- L. v# v, B' N3 M ^. L - from net.sf.l2j.gameserver.model.quest import State
4 B( X7 z w: ]; P" \ - from net.sf.l2j.gameserver.model.quest import QuestState. S; l6 J2 _( s
- from net.sf.l2j.gameserver.model.quest.jython import QuestJython as JQuest6 x9 k1 S9 t2 V. Q [5 `
6 ~! B, p5 ]& G. A) s& B1 @- KELTIR_NPC_ID = 12082
- e+ I( s' p/ F" ^9 \9 v! `7 ~3 I/ N" m - FANGS_ITEM_ID = 1859
# i. |% G6 a1 n6 z* e" O - DROP_RATE = 500000
8 M+ ^3 [8 k ^# o
" |8 G U% k% G$ K: _/ R7 W; m- WORLD_MAP_ITEM_ID = 1665
& F8 z$ d$ v8 p1 J+ a - z1 n% d: [* Y6 p
- def getCount(st) :3 T8 Z6 N7 w N: x
- return st.getQuestItemsCount(FANGS_ITEM_ID)
/ s) e% j; h; ~6 ?$ t3 Y6 ]0 h
, }) V0 Q0 L- _4 S0 D6 i- def completed(st) :) ?- R4 h- o: e6 l
- st.setState(COMPLETED): H$ g! d7 g: g: L
- st.clearQuestDrops()! b$ Z( A* c% x% N) I
- st.takeItems(FANGS_ITEM_ID,-1). z. r2 @: G3 Y# Y( b/ a& I' x
- st.giveItems(WORLD_MAP_ITEM_ID,1)
- d E/ i8 x m8 ?, S - st.exitQuest(False)
4 m* ^; g v- U( i( N - return# z9 v4 y) m+ E% w8 N
, V3 p K1 h8 O- def check(st) : U- e% J' L+ K) I( u% U
- if getCount(st) >= 4 :/ y6 z1 Q* L1 |
- completed(st)
+ N: Z5 X' |3 Z5 C' F/ n( [ - return
# e, q0 a5 ^! ~! Q3 j0 h$ [# A# G - : v5 U, c9 B! K) p( e
- class Quest (JQuest):
1 U5 O5 n- C7 _% {0 t6 v - 2 k8 {5 U( d/ d+ ]
- def __init__(self,id,name,descr): JQuest.__init__(self,id,name,descr). ^5 K `! h/ U Z% @9 z7 k# p! Q
- I4 {6 L; l" b a- def onEvent (self,event,st):# y5 @4 o" L) O3 s! I! g
- id = st.getState()1 d9 \) C4 a+ n6 l
- if id == CREATED : st.setState(STARTED)9 f. v+ [, j6 s9 e0 O( U
- elif id == COMPLETED: pass
' C: [0 I# G! ?2 C+ w3 a - elif id == STARTED : check(st)
* U$ k$ T* L* {' B+ z, R+ D* c - return( k/ [3 V+ ?. {3 l2 }
- 6 Z q, `( N& k/ \$ p$ B
- def onKill (self,npcId,st):
; O- \9 X* k5 c7 E/ O - if npcId == KELTIR_NPC_ID:
- V! z+ p7 k( ?- o' S$ I - n = getCount(st)
6 m8 z/ g3 q) G9 a: Q - if n == 0:
! R/ [( p; Y+ [" f+ m D$ s4 m - if st.get('chat0') == None :
9 e: v6 d; B0 {2 S9 K - st.set("chat0", "true")( t, D5 t5 i& E, Q/ ~2 X7 P. J
- return "Chat0.htm"8 K- b* N1 G+ d$ W
- elif n == 1:( _; g* A' q2 `+ }/ n+ _
- if st.get('chat1') == None :( d S2 g6 Z+ T& h" W
- st.set("chat1", "true")
. @1 _" ^3 E. f. `6 n - return "Chat1.htm"
, U. Z0 n5 `+ u/ l( ]0 }3 d - elif n >= 4:
# r9 v* c; P' K+ ] - return "Chat4.htm"1 f9 f+ c9 F! v; H! c! D$ { C
- return "Collect "+str(n)+" of 4 fangs"
2 Q$ M; I( p) B2 `8 n) r1 h! H! F* Q - return
0 Q& d, V) }5 T1 B( N
# d, R+ f: @, n* @1 k/ I' t- @- QUEST = Quest(201, "Tutorial", "Tutorial quest"): N, c: ?1 K$ ^7 D @
- CREATED = State('Start', QUEST)
. Z: T4 R4 ]3 c; J - STARTED = State('Started', QUEST)$ @( d$ W* F2 E9 _
- COMPLETED = State('Completed', QUEST)
& X2 E ?3 p$ ?
( P& ^% J1 L# B7 D" ]4 K6 D# v" T- QUEST.setInitialState(CREATED)
/ }- F# u; Y) T$ _ - QUEST.addStartNpc(7056): i" z- L3 _) C3 q1 X5 V2 a
- QUEST.addStartNpc(7012)
& R0 l# f2 X/ E! z" e - QUEST.addStartNpc(7009)
+ ?" M) J) Q+ b9 B - QUEST.addStartNpc(7011) P! ]2 V) p+ P8 K& `) w3 }
6 H3 H2 o' m. x0 r7 Z0 F+ u- STARTED.addQuestDrop(KELTIR_NPC_ID,FANGS_ITEM_ID,DROP_RATE)
: n! |5 J0 K' Z5 t0 S: O - STARTED.addKillId(KELTIR_NPC_ID)
, o+ s/ Y4 u% j; Q" t - STARTED.addTalkId(7056)
1 R7 a+ l5 w7 K9 H2 k$ M! M - STARTED.addTalkI d(7012)$ ?( B! K; B3 [! D
- STARTED.addTalkId(7009)& X! D% q' s, ]! F
- STARTED.addTalkId(7011)
Скопировать код
/ `! S( {" h! p! A d
' ~: G7 H+ @. @ |