Зарегистрируйтесь сейчас чтобы найти еще больше друзей, и получить полноценный доступ ко всем функциям сайта!
Для просмотра Вам необходимо авторизоваться Если Вы еще не зарегистрированы, перейдите по ссылке:Зарегистрироваться
x
Хроники Interlude
7 x+ E9 B: ]" EСборка L2j
0 C& b/ I% e0 d; OОбратите внимание: в файле htm стартового NCP обязательно должна быть ссылка на квест:+ T8 {) r# i3 r7 X% z5 |
- STARTED.addQuestDrop(KELTIR_NPC_ID,FANGS_ITEM_ID,DROP_RATE)
Скопировать код Для этого квеста больше ничего не надо. Все необходимое для корректной работы квеста уже добавили. Вот полный текст квеста:
( i6 \( Z7 F7 e) ^, x# h3 S$ ^" D7 X! d
- if getCount(st) >= 4 :9 x" |! G8 h+ l9 r' P G1 K
- completed(st)
' c7 `, r; I/ Y' X3 d- B - return [6 F0 x: C4 P1 J K
- # B# y% y; [- U9 U7 q" f
- class Quest (JQuest):
/ S; ~9 P$ x6 m1 ?7 o - def __init__(self,id,name,descr): JQuest.__init__(self,id,name,descr)3 w( |3 a" n* K) j# I
- def onEvent (self,event,st):$ @5 n/ W) m+ y U4 _9 M
- id = st.getState()4 L. |( u& \# A& J
- if id == CREATED : st.setState(STARTED)
. J% S0 F; {( [: {$ l @6 h - elif id == COMPLETED: pass
6 i8 X) I8 a6 q& I - elif id == STARTED : check(st)1 v* T, A# A& X. F" V* Q
- return
' N4 n7 x; L& r: |/ _: | D
; ~6 p9 f% D. @5 F+ c! u- QUEST = Quest(201,"Tutorial", "Tutorial quest")
7 C3 ^; P6 J+ }5 A$ F - CREATED = State('Start', QUEST), M+ Y& O# z0 y0 }: s6 x
- STARTED = State('Started', QUEST)
# O# l) S; T4 E* R( q - COMPLETED = State('Completed', QUEST)/ Y& `! Z# y4 `. f
- : K$ ?5 S7 P6 ]0 V
- QUEST.setInitialState(CREATED)
& D. p! R/ n* Q9 t* V- ~7 R1 p - QUEST.addStartNpc(7056)' n- m( K' ]# {' r, d2 ?# C
- STARTED.addQuestDrop(KELTIR_NPC_ID,FANGS_ITEM_ID,DROP_RATE)
Скопировать код Теперь рассмотрим, как это работает.
& i: j" _0 W6 o9 _ a+ yИгрок подходит к начальному NCP (в данном случае 7056), нажимает на «Quest». Квест будет создан и состояние квеста перейдет к CREATED и игроку будет показана страничка Start.htm с описанием квеста. Тогда метод onEvent, поле открытия странички Start.htm переведет состояние квеста в STARTED и игроку будет показана страничка Started.htm, где будет опсание того, как найти keltirs и .т.д.: b; |& s2 R* c9 y' x9 T
+ L# c3 [. W( g2 o0 P" N
, ]4 J( J3 P- { L$ K% d; J1 W* J
При состоянии STARTED будет зарегистрирован дроп «fangs» при убийстве keltirs. Игрок может вернуться к стартовому NCP и спросить о квесте – метод onEvent будет вызван снова. Если у игрока не хватает необходимого количества предметов, то метод check() не переведет квест в следующее состояние и Started.htm будет показана снова. Но если игрок собрал необходимее количество предметов (в данном случае 4 клыка), то метод check() вызовет метод completed() который переведет квест в новое состояние COMPLETED, заберет все клыки, даст карту мира, т.к. это награда за квест, покажет Completed.htm и завершит квест.
: A) z- R( R5 i# E
* ~9 h, I* B$ \, a3 C* b
+ ?8 X4 p5 A* f4 I1 m3 k9 O. qТеперь давайте сделаем наш квест более похожим на то, что он должен из себя представлять.
6 x4 B; O; |$ C' B" f( l$ w0 G# s( DПрежде всего у нас есть 3 метода для объявления их в Яве – onTalk, onKill и onEvent. Если методы onTalk и onKill не объявлены, то за них все будет делать метод onEvent, т.е. определять квестовых монстров и вызывать диалоги NCP. Есть примечание, методы onTalk и onKill будут вызывать только диалоги с NCP в зависимости от текущего состояния квеста. Метод onKill будет вызываться только тогда, когда мы убиваем квестового монстра.; D/ m: |1 U0 J+ _
: q/ X' [9 B% y+ W' ^) {+ M0 M5 S1 F3 u
6 d% G @7 C, h G5 d
Давайте рассмотрим как вызывается метод onKill при убийстве keltir в состоянии квеста STARTED:' K0 G H# x$ Y" C+ i
- STARTED.addKillId(KELTIR_NPC_ID)
Скопировать код и метод onKill в классе Quest:/ Y w9 y( @' t7 E' A
5 C2 a @ B, v7 P- class Quest (JQuest):
% d' y1 F) W7 j& l% M - ...
. C. Y; r8 {5 i( e - def onKill (self,npcId,st):
0 o _1 \% z) V6 F0 n/ a - if npcId == KELTIR_NPC_ID:$ F8 }4 w7 S! y) t" Q$ d
- n = getCount(st)* b0 V) n4 X# ^
- if n == 0:
% i$ Y& _* I& v; R - return "Chat0.htm"1 }. S$ f2 A$ n* V' d
- elif n == 1:
$ v$ F6 a* h a4 t* U. M - return "Chat1.htm"+ X+ w! s, b! ~' |) W5 a% B8 [; _
- elif n >= 4:
: ?& W0 T' K8 v; C8 S- U3 }/ x - return "Chat4.htm"% X2 [6 G7 r. \' e0 K# ^3 o# a
- return "Collected "+str(n)+" of 4 fangs"( Q+ L, D; w9 Q+ E
- return
Скопировать код Метод onKill (а так же метод onTalk) имеет следующие параметры:6 t: R6 ~) ~7 \! l1 m9 D2 s* L
7 d) @! r6 j" w( x
% }- e) H$ N# C+ \2 B7 s
• self – квест
6 [! b, G% W1 z- {/ l/ U* R• npcId – ID NCP, которого мы должны убивать (если это метод onTalk, то ID того NCP, с которым мы должны поговорить).; R: w+ p% `. @" r1 ]5 k
• st – текущее состояние игрока.; Z9 f4 q" n& O* i6 B* A8 d
7 G8 r$ T0 z8 G5 ^/ Y
* H; g$ P7 c9 D/ q; A! oВ этом методе мы проверяем и отмечаем, является ли убитый NCP keltir’ом. В основном эта проверка не нужна, т.к. у нас только KELTIR_NPC_ID.
. L+ @2 i; V' }/ J% K; y% {8 d; o- f0 B+ K' i/ P
& e: S# z$ `9 B7 c3 m: Y( k# s: DЗатем проверяем количество предметов (в данном случае количество клыков), и если их вообще нет, то возвращаем строку "Chat0.htm", если только один предмет, то возвращаем строку "Chat1.htm", если же предметов 4 или больше, то "Chat4.htm". Если строка возвращена из методов onEvent, onKill или onTalk, то сервер покажет соответствующие htm. В Chat0.htm может иметь следующий текст: «Вы не имеете ни одного клыка, возвращайтесь позже, когда соберете 4 штуки и бла, бла, бла…», в Chat1.htm может быть следующий текст: «У Вас всего 1 клык, по этому соберите еще…». В Chat4.htm – «Вы собрали необходимое количество предметов, возвращайтесь к вашему тренеру, что бы завершить квест…»* p b2 V2 B! H) }/ [
' ~4 _% M! A! ?/ z
# [: S/ n' M' OПримечание: если в строка return начинается с "<html>", то будет показана страничка html с текстом, который стоит далее. Так вместо:
0 F" ^8 {* h. i2 d) N8 Vreturn "Chat4.htm") |2 q4 K q- A! I# S
9 i' P# ]1 g! o
& n4 C+ c3 w& M2 E
можно поставить:
4 H$ ~# }( b7 q- ] w- return "<html><body>Return to your trainer to complete the quest</body></html>"
Скопировать код Так же если строка заканчивается без .htm или в начале нет <html>, то текст будет выведен, как системное сообщение в окне чата. В нашем случае мы сделаем так, что бы при каждом убийстве keltik выводилось системное сообщение: «Собрано N из 4-х клыков».
$ p$ Z9 y5 ]: E- w* |9 S! j5 K/ h9 `7 i$ e0 e8 t5 h8 ]
b5 O# w y* {, I" ?" J: U
Наш код для onKill имеет один недостаток. Он будет постоянно показывать Chat0.htm, Chat1.htm и Chat4.htm, нам же необходимо, что бы Chat0.htm и Chat1.htm показывались только один раз. Как нам это сделать? С помощью переменных.
9 i' U1 I0 ?- t# k0 P* c! e& G1 b. ?* x
g% {+ ] p) [- {
В каждом квесте строки могут храниться с помощью переменных. Эти переменные сохраняются в Вашей БД. В каждом методе мы можем назначить, прочитать и удалить переменные. Давайте изменим метод onKill, так что бы каждый диалог вызывался только один раз.: Q" U% C: k- u$ X* n
- def onKill (self,npcId,st):
9 U% M# n4 J$ q1 } - if npcId == KELTIR_NPC_ID:- F! ]- F* z* C
- n = getCount(st)7 [6 Y' {9 u' g8 ?% \5 a
- if n == 0:$ g9 o6 V5 d) v, `2 W: L0 N0 s3 {
- if st.get('chat0') == None :) b3 l$ p P2 F! r( S2 D8 O; O1 y
- st.set("chat0", "true")
4 F! x* e& O# J4 b$ |' s - return "Chat0.htm"5 Q' s' g! D9 [: s- U& n; Q/ U
- elif n == 1:) {9 n" A2 B7 M% [$ M
- if st.get('chat1') == None :' u$ T2 E; J' y4 A
- st.set("chat1", "true")& l: w o; z- }9 E( A8 O- e0 e8 U
- return "Chat1.htm"
/ I. U K: J' H( z K7 B - elif n >= 4:; \) S: F8 [$ o' S& T# o) s$ j& D
- return "Chat4.htm"0 l, t8 K e( B# G0 {2 Q
- return "Collected "+str(n)+" of 4 fangs", J b2 X; }8 D( }9 p, l4 }
- return
Скопировать код Если у игрока нет клыков (n=0), то мы получаем занчение переменной 'chat0'. Когда метод onKill вызван в первый раз, то пока ни каких переменных не имеется и python возвращает значение None. В этом случае объявляется переменная и показывается диалог Chat0.htm. Когда мы убиваем keltir, но не получаем с него клык, функция st.get('chat0') возвращает строку true, а не None. И во второй раз окно с Chat0.htm не появится, но в окне чата появится строчка «Collected 0 of 4 fangs». По тому же принципу сделано и с Chat1.htm.
( C& | l2 b' C$ K
, q- ]4 O" E8 d9 }/ O p) x
G7 j: I" n; a9 J5 S2 {* v3 XВот конечный рабочий вариант квеста:
: C7 E( J4 t+ F$ R- import sys8 T. O5 a! a! s
- from net.sf.l2j.gameserver.model.quest import State
1 E# T- J1 @, Y0 j' G4 P - from net.sf.l2j.gameserver.model.quest import QuestState
" n. h3 R: x. m0 x( c, }3 J - from net.sf.l2j.gameserver.model.quest.jython import QuestJython as JQuest
6 K+ U+ M2 R% B1 T7 @
: X$ H' z' l# j' r, k5 ]* H0 l& \- KELTIR_NPC_ID = 12082) E. }2 |: z; J) K/ h6 N& n6 H
- FANGS_ITEM_ID = 1859. m2 z% B) U: a0 C" E
- DROP_RATE = 5000001 [/ }: A5 \8 O
- H9 f$ A2 M. s- WORLD_MAP_ITEM_ID = 1665
/ T) T3 N/ z$ V3 `9 O$ [
# L7 S( T+ J, B- def getCount(st) :
2 x( w W5 |0 D+ Z* g2 D - return st.getQuestItemsCount(FANGS_ITEM_ID)
% Q8 Q# @0 G+ m9 c5 y3 x
+ X; I2 N: Q- Z- \# x p; Z- def completed(st) :) B h. A" p# n9 F1 r
- st.setState(COMPLETED)
h3 ^7 h) B2 m1 l+ a- Z& X' Z* Q$ l2 [ - st.clearQuestDrops()' \! ~6 q( V% S; f9 J! w" h
- st.takeItems(FANGS_ITEM_ID,-1)6 g) f& v9 y0 _- T, z+ s
- st.giveItems(WORLD_MAP_ITEM_ID,1)+ d. {: ~" L: Y; ^% @
- st.exitQuest(False)
% o# ~/ u) D. a8 |8 P0 ^' _ - return% l; |/ ^: A: l9 @) P$ N
" Y" e: U3 e f6 q' D8 o2 ^5 _9 q- def check(st) :
3 g+ |% B- y* Y7 c - if getCount(st) >= 4 :2 x6 Z" C% ~5 S# f' x
- completed(st)
. F' R6 u. V; B5 z# P2 B! ] - return
* F J( S8 Z& y j0 ?3 ] - , T3 D4 q/ @. ]# F
- class Quest (JQuest):+ A Q( X- t% e+ C5 q7 y
- k- O# h, B+ v& o* B# T- def __init__(self,id,name,descr): JQuest.__init__(self,id,name,descr)# n/ o5 E2 D% k; z$ u* A7 O
- 3 h/ D+ |; e: n* r! y
- def onEvent (self,event,st):
1 M, ?" P" a F8 m6 f - id = st.getState()2 @# [' o: s$ g- T4 j8 u
- if id == CREATED : st.setState(STARTED)
1 b; K- ~0 t2 B$ z7 }* O+ W. d6 V - elif id == COMPLETED: pass- o8 @: a- U% J @
- elif id == STARTED : check(st)' L% X# l- l$ n& M% R& U
- return
i/ J' J7 z8 [9 o# j1 i! i
% O& N0 M& E+ ?% P/ O: K- def onKill (self,npcId,st):- E9 |/ r9 r' P) [8 n% O# B
- if npcId == KELTIR_NPC_ID:
) [, g2 f. b) @. Y o7 _& K - n = getCount(st)) R3 d; w2 J i$ j( I) S7 G1 a
- if n == 0:7 |; k% y" R6 L, J+ Q) \0 S
- if st.get('chat0') == None :# Y6 p6 Q, k P5 i$ Z
- st.set("chat0", "true")& a1 G# \0 E5 A! X1 _9 N+ _0 P9 G
- return "Chat0.htm"" Y* H, p+ |, M0 t
- elif n == 1:4 T& b I7 y) k' N! K |
- if st.get('chat1') == None :
: F2 H# o: `- n7 H# D0 C* w - st.set("chat1", "true")
# r! u/ t" c7 S |3 {& x - return "Chat1.htm"
& {: ?$ k( \" o/ W - elif n >= 4:
/ b9 C, \7 G! h) v7 F, E+ _ - return "Chat4.htm"
8 Z, E/ P# O- |3 k9 ]$ x( l9 g" f - return "Collect "+str(n)+" of 4 fangs" n1 h0 L! I+ e. a
- return( a: F- \ Q2 U( J) m F% h; ~
7 ^* z R2 P6 @6 K0 V- QUEST = Quest(201, "Tutorial", "Tutorial quest")0 x# U4 {1 M) |% s. ^7 K
- CREATED = State('Start', QUEST)8 u* U3 r: n4 O; t5 A0 y/ G. n$ s* a
- STARTED = State('Started', QUEST). E% u: P4 q- }9 o
- COMPLETED = State('Completed', QUEST)
7 _, K2 T6 Y( n
' s, P1 p9 s j+ I' X! J, {7 B- QUEST.setInitialState(CREATED)& D+ [( y i6 z3 ^4 ]
- QUEST.addStartNpc(7056)
7 `# V9 M! e3 Q/ V0 Y - QUEST.addStartNpc(7012)
5 v8 t* c7 G4 ]- { - QUEST.addStartNpc(7009)
9 J2 }! a, x7 P3 H# \ - QUEST.addStartNpc(7011): u( u$ ~/ X" v! s# [, w
- & f# ?3 j% Z9 Q# G! x U2 ]# N* {% C
- STARTED.addQuestDrop(KELTIR_NPC_ID,FANGS_ITEM_ID,DROP_RATE)
; N' c$ h' ^) ] M - STARTED.addKillId(KELTIR_NPC_ID)
1 Z. V" ?0 b9 s% @ - STARTED.addTalkId(7056)
* K; h7 {: n$ z0 o3 c3 |/ e - STARTED.addTalkI d(7012)
' s" ^/ n3 ]" N; M) W# O( A - STARTED.addTalkId(7009): [- I# ~) C( P# M
- STARTED.addTalkId(7011)
Скопировать код
$ R1 ~/ Q; E5 {) O7 ] h+ }
7 ^7 ^. u" }0 X |