Зарегистрируйтесь сейчас чтобы найти еще больше друзей, и получить полноценный доступ ко всем функциям сайта!
Для просмотра Вам необходимо авторизоваться Если Вы еще не зарегистрированы, перейдите по ссылке:Зарегистрироваться
x
Хроники Interlude
# u0 }6 J" f& J; b uСборка L2j
! x# B, b; j$ \/ zОбратите внимание: в файле htm стартового NCP обязательно должна быть ссылка на квест:
0 Q" b7 o0 g; K" g8 D- STARTED.addQuestDrop(KELTIR_NPC_ID,FANGS_ITEM_ID,DROP_RATE)
Скопировать код Для этого квеста больше ничего не надо. Все необходимое для корректной работы квеста уже добавили. Вот полный текст квеста:
: j0 g7 Z' ?& t
6 R: F" g/ k( R- if getCount(st) >= 4 :
7 `9 m# D0 u/ X3 M - completed(st)
6 T' V: B( ]- [$ b" e - return
6 t: j) }1 q# |- u
, p4 b F9 t0 y2 U! @8 f. w- class Quest (JQuest):0 n) m A2 }; S* j' ^" A
- def __init__(self,id,name,descr): JQuest.__init__(self,id,name,descr)
/ S1 M2 q# k/ o% f% M - def onEvent (self,event,st):1 t& o0 t. s+ J9 `, m
- id = st.getState()
6 V; D" K" f+ H8 P O8 ? - if id == CREATED : st.setState(STARTED)
) ?3 C5 }. C3 R- x& G9 r - elif id == COMPLETED: pass
' n) y- l" z' p - elif id == STARTED : check(st)
6 R8 ] @1 A9 {- [! M4 i9 g# j" U - return
+ {4 J0 S2 }0 B0 u$ J' [; W; ] - 9 [6 {+ ]! B# {3 y0 \
- QUEST = Quest(201,"Tutorial", "Tutorial quest")7 w" s. ]' ]3 j* i: O# C
- CREATED = State('Start', QUEST)
; Q `/ w6 a: F& l! A - STARTED = State('Started', QUEST)% D- o! r1 o* G' r8 K& o' J
- COMPLETED = State('Completed', QUEST)8 I, i" @7 a( N" \& j
1 b% y6 }8 L* ~4 e( k4 X `- QUEST.setInitialState(CREATED)2 G6 u( l6 Y4 P B
- QUEST.addStartNpc(7056)+ d& T7 k( D3 z2 b
- STARTED.addQuestDrop(KELTIR_NPC_ID,FANGS_ITEM_ID,DROP_RATE)
Скопировать код Теперь рассмотрим, как это работает.
+ h& Z1 ~3 ]% gИгрок подходит к начальному NCP (в данном случае 7056), нажимает на «Quest». Квест будет создан и состояние квеста перейдет к CREATED и игроку будет показана страничка Start.htm с описанием квеста. Тогда метод onEvent, поле открытия странички Start.htm переведет состояние квеста в STARTED и игроку будет показана страничка Started.htm, где будет опсание того, как найти keltirs и .т.д.% `* ~3 q" o7 a
8 k6 X7 k$ s/ D3 [, b
) O/ G+ t& \4 y! WПри состоянии STARTED будет зарегистрирован дроп «fangs» при убийстве keltirs. Игрок может вернуться к стартовому NCP и спросить о квесте – метод onEvent будет вызван снова. Если у игрока не хватает необходимого количества предметов, то метод check() не переведет квест в следующее состояние и Started.htm будет показана снова. Но если игрок собрал необходимее количество предметов (в данном случае 4 клыка), то метод check() вызовет метод completed() который переведет квест в новое состояние COMPLETED, заберет все клыки, даст карту мира, т.к. это награда за квест, покажет Completed.htm и завершит квест.
( _( ~$ K3 s8 F: u, n) K
z* z6 f9 y9 o s/ @
3 _+ ]* y$ H- U [* X. ~- d8 Y) w e' zТеперь давайте сделаем наш квест более похожим на то, что он должен из себя представлять.5 p1 I4 C7 r+ X ~8 F5 ]
Прежде всего у нас есть 3 метода для объявления их в Яве – onTalk, onKill и onEvent. Если методы onTalk и onKill не объявлены, то за них все будет делать метод onEvent, т.е. определять квестовых монстров и вызывать диалоги NCP. Есть примечание, методы onTalk и onKill будут вызывать только диалоги с NCP в зависимости от текущего состояния квеста. Метод onKill будет вызываться только тогда, когда мы убиваем квестового монстра.
7 @/ Z; |) g6 K+ u
( H, ?7 S; @4 u8 y2 Y5 \1 F% w: o
. O7 j% [% q, n; G% B) L; E/ UДавайте рассмотрим как вызывается метод onKill при убийстве keltir в состоянии квеста STARTED:
7 t; H$ T% }( K* n: y$ w- STARTED.addKillId(KELTIR_NPC_ID)
Скопировать код и метод onKill в классе Quest:: B' t9 T1 Y9 @
6 k# g5 w1 K8 P7 u; C
- class Quest (JQuest):
9 s1 p6 s. n9 f }/ F - ...
( C9 d3 Y! U+ }4 c4 W - def onKill (self,npcId,st):
2 W! U$ S) X; w$ V - if npcId == KELTIR_NPC_ID:" X. x8 K K( E# i
- n = getCount(st)4 B6 W& I0 \( O2 y8 p9 ^
- if n == 0:
; z# ?0 F2 k% S; u - return "Chat0.htm"
$ `; w& l; \6 r" o; T4 u' ~! g% e - elif n == 1:
, _/ v: F4 j& B* V+ R - return "Chat1.htm"
8 r) f8 L8 B! u0 k2 H - elif n >= 4:: U' }' f2 F$ M$ j" W, c- L6 C
- return "Chat4.htm"
* @8 {' p1 h5 ?* e7 }- D0 R" h B - return "Collected "+str(n)+" of 4 fangs"/ {/ T2 H2 l5 |" M6 A$ }
- return
Скопировать код Метод onKill (а так же метод onTalk) имеет следующие параметры:
' C4 d* B9 b0 `3 M) v3 \- a* W7 x, R: F6 K0 a3 `9 h7 I9 x2 Q
1 u K% N+ [3 _6 Y1 Y• self – квест: x5 t/ A0 C+ a7 f% R" S1 e! b' K2 d' `
• npcId – ID NCP, которого мы должны убивать (если это метод onTalk, то ID того NCP, с которым мы должны поговорить).
9 ~6 h0 x! v" {6 O" h• st – текущее состояние игрока.# B: C1 o, F5 F/ I/ Y
. q, t5 [! [' [& X1 z K7 E; o
; O9 s5 ?2 @6 D' p5 ]( t+ m1 L/ y
В этом методе мы проверяем и отмечаем, является ли убитый NCP keltir’ом. В основном эта проверка не нужна, т.к. у нас только KELTIR_NPC_ID.
7 R% b/ k7 e" U N9 i% G
/ n1 n- n; k8 M5 ]; ^0 H z
$ y; {; W# c( k) l/ u$ a& d6 iЗатем проверяем количество предметов (в данном случае количество клыков), и если их вообще нет, то возвращаем строку "Chat0.htm", если только один предмет, то возвращаем строку "Chat1.htm", если же предметов 4 или больше, то "Chat4.htm". Если строка возвращена из методов onEvent, onKill или onTalk, то сервер покажет соответствующие htm. В Chat0.htm может иметь следующий текст: «Вы не имеете ни одного клыка, возвращайтесь позже, когда соберете 4 штуки и бла, бла, бла…», в Chat1.htm может быть следующий текст: «У Вас всего 1 клык, по этому соберите еще…». В Chat4.htm – «Вы собрали необходимое количество предметов, возвращайтесь к вашему тренеру, что бы завершить квест…»' ^% v9 J9 ]5 D0 ]) ?
7 F2 Z: `% i) T) A+ {1 u! W: |1 j) ~" U" E1 U# K
Примечание: если в строка return начинается с "<html>", то будет показана страничка html с текстом, который стоит далее. Так вместо:# W) a7 y Y6 h% h9 i5 C2 `
return "Chat4.htm"3 s. W8 F8 |' r
h+ [1 ?- Y8 l3 F+ q6 g* i1 R; T- Y
. u% v* J! F# `, D5 _6 Oможно поставить:
6 g% i% Q- m- O2 }- return "<html><body>Return to your trainer to complete the quest</body></html>"
Скопировать код Так же если строка заканчивается без .htm или в начале нет <html>, то текст будет выведен, как системное сообщение в окне чата. В нашем случае мы сделаем так, что бы при каждом убийстве keltik выводилось системное сообщение: «Собрано N из 4-х клыков».- _: ?" @" j5 T* G' k8 [
Z& _; r; w' a; m7 ]
6 z5 m0 a: R1 `$ WНаш код для onKill имеет один недостаток. Он будет постоянно показывать Chat0.htm, Chat1.htm и Chat4.htm, нам же необходимо, что бы Chat0.htm и Chat1.htm показывались только один раз. Как нам это сделать? С помощью переменных.
- b; e* U( f* N* [$ v3 [! B) u2 S+ s! b: E, Z4 D- I
' a2 E1 O' x) |/ R
В каждом квесте строки могут храниться с помощью переменных. Эти переменные сохраняются в Вашей БД. В каждом методе мы можем назначить, прочитать и удалить переменные. Давайте изменим метод onKill, так что бы каждый диалог вызывался только один раз.
6 g- q. x4 r: M f& e4 ]3 ^- def onKill (self,npcId,st):
3 L* g) v2 i0 v9 W - if npcId == KELTIR_NPC_ID:
3 Y4 {$ }4 O2 J. l" _% ?) e - n = getCount(st): z6 _+ Z% n# r2 L: @+ [# `
- if n == 0:
; w; S" N& \- A' A7 X! _/ Y8 h - if st.get('chat0') == None :
9 x# ?2 ^7 l+ r# m( X) Q - st.set("chat0", "true"), N* O9 ]4 z/ A4 J+ h* }3 `1 B
- return "Chat0.htm"
8 @ B. m- D* c6 }6 c4 e - elif n == 1:: {. K6 ^; `, p4 K
- if st.get('chat1') == None :. Q4 e r* K2 P3 T! {$ m( G4 o
- st.set("chat1", "true")
- i; q0 K) f5 H8 h+ Q. s - return "Chat1.htm"
7 F0 d5 T$ E, ]( k1 I) D$ A% p - elif n >= 4:4 [! U! l- D9 Q# v
- return "Chat4.htm"+ S9 F! @+ V: }( K; y
- return "Collected "+str(n)+" of 4 fangs"/ W5 w3 o! @. e8 _
- return
Скопировать код Если у игрока нет клыков (n=0), то мы получаем занчение переменной 'chat0'. Когда метод onKill вызван в первый раз, то пока ни каких переменных не имеется и python возвращает значение None. В этом случае объявляется переменная и показывается диалог Chat0.htm. Когда мы убиваем keltir, но не получаем с него клык, функция st.get('chat0') возвращает строку true, а не None. И во второй раз окно с Chat0.htm не появится, но в окне чата появится строчка «Collected 0 of 4 fangs». По тому же принципу сделано и с Chat1.htm.
: F6 n% D7 i' i l% h- I6 X$ R) B7 w3 ~
6 b/ X" L( I* b3 @3 s6 q; v: aВот конечный рабочий вариант квеста:2 Q* K% ^+ w# d0 |- m# {' s) }
- import sys
4 P' ^5 P7 Y7 B - from net.sf.l2j.gameserver.model.quest import State" `5 ^+ t7 n1 D0 R! T
- from net.sf.l2j.gameserver.model.quest import QuestState
9 S8 I" B; i' d& G3 O. @8 X. w - from net.sf.l2j.gameserver.model.quest.jython import QuestJython as JQuest }/ x& f) I# z3 v
( Z; _, ~" L- Z" r- KELTIR_NPC_ID = 12082
0 u' c1 D) H: n4 X: y6 D# I( z - FANGS_ITEM_ID = 1859% `, x0 |# O# p! ~! q4 l5 T' g1 v) O
- DROP_RATE = 500000
' g& O. c9 C7 w( ] |. x& y
# y& I) [5 |3 D6 g- WORLD_MAP_ITEM_ID = 16657 Y$ h4 M7 Q7 f5 N' _2 K- H* t
$ [- D9 @! |2 f( g, G# |- def getCount(st) :) I" G/ f! e# K
- return st.getQuestItemsCount(FANGS_ITEM_ID)
% b+ v- R5 S% F- [: \
- v G3 b- r( v2 c2 F g" u9 ]) Y- def completed(st) :% K0 l. e6 }# g: H, ^
- st.setState(COMPLETED)# w6 c6 N8 n6 P7 D" S3 d# W
- st.clearQuestDrops()) e& Z# m4 K, i) L' ?/ E. z
- st.takeItems(FANGS_ITEM_ID,-1)
4 C( O) L" r- ^( [8 H0 o2 O* U - st.giveItems(WORLD_MAP_ITEM_ID,1)
& Z4 w: r6 e/ }/ G - st.exitQuest(False)% p, V' ^; O5 e! Y @ x$ @
- return
9 J8 G# {% P% ?, t, {
$ G" o6 _7 K8 M! L7 b6 t7 {# V- def check(st) :
, c/ n, C: G8 G9 o X/ P - if getCount(st) >= 4 : [- E7 l9 R9 g8 J+ p! u; _8 Z
- completed(st)
1 r" I9 a! v, W( W - return2 B/ l; b5 Z& u; ]9 r6 T" h
- , z3 b; j+ @& ?0 l* E
- class Quest (JQuest):
6 r7 L% N; l2 s - 6 W- P j' a! B5 v1 O% d4 T, ^
- def __init__(self,id,name,descr): JQuest.__init__(self,id,name,descr), S4 j0 E( j4 f( u3 E
- ; E8 x( A7 z3 s1 ?0 F8 y6 ]
- def onEvent (self,event,st):
# x, j: Z: [( d& S+ z, `8 R$ o - id = st.getState()
5 A. {* S& e3 G! W# z. O - if id == CREATED : st.setState(STARTED)
M7 G3 c0 O7 i E# {- S - elif id == COMPLETED: pass* L1 B& b* m" f4 w! ^6 O
- elif id == STARTED : check(st)
( I% P, L/ X. M1 Z3 }* l - return/ P H$ b8 `1 d
( ?3 w) h& {% j- def onKill (self,npcId,st):
. y2 W) }5 p& m& V4 T$ P - if npcId == KELTIR_NPC_ID:
( M# o6 i: m$ c3 G, g - n = getCount(st)
( D& h. A8 @- S) G% J* F - if n == 0:
0 Y( C6 ^ Z6 s+ v" `( n* F - if st.get('chat0') == None :: x' o+ ?/ c+ ~& M( Y! x9 L4 U) v
- st.set("chat0", "true")" U. @( x! [8 W" m: ~ j3 Q+ R
- return "Chat0.htm"
: V( D8 E" w7 e/ K5 @ - elif n == 1:
" }5 o* i* o0 }2 | N1 w - if st.get('chat1') == None :! C, @2 ?. p2 s9 g' P* O* {; C2 y% T
- st.set("chat1", "true")8 z, p6 Y S3 z1 h
- return "Chat1.htm"
2 R) k0 C& n& Y2 B/ z; ~ - elif n >= 4:
0 z& h7 z' T. t. x# G - return "Chat4.htm"
: V% W4 o, r3 r: y% J3 d; t3 ] - return "Collect "+str(n)+" of 4 fangs"
' X6 I2 j i0 y( q |: h - return
/ D5 |: A5 J: Q6 O
& ^$ _6 G; J1 d$ n, p* B- QUEST = Quest(201, "Tutorial", "Tutorial quest")* P3 V8 N* ?% G6 J/ E& a! V
- CREATED = State('Start', QUEST)( p3 Y- W8 m* c1 R, k' h
- STARTED = State('Started', QUEST)8 q% i4 X6 v% g$ b6 f5 D
- COMPLETED = State('Completed', QUEST)
, d- _# C+ N! B* }2 P; q4 N - # i D. {* u- ^- {$ B
- QUEST.setInitialState(CREATED); l& d* G: d9 r. ~8 V6 D3 \
- QUEST.addStartNpc(7056)- b) Z, v, U/ ?* b6 E
- QUEST.addStartNpc(7012)" x' E4 v6 J4 }& |
- QUEST.addStartNpc(7009)7 X6 D) B1 n3 Q, A& R. o
- QUEST.addStartNpc(7011); Q7 T7 e+ g0 p ?7 B, {9 m
) d' v2 `+ b" H$ N- STARTED.addQuestDrop(KELTIR_NPC_ID,FANGS_ITEM_ID,DROP_RATE)+ [ D" S; x* c- v# o
- STARTED.addKillId(KELTIR_NPC_ID)
+ H, R; X& J& i( ]. Q4 }. K - STARTED.addTalkId(7056). d5 \ C4 Q. ^! ~
- STARTED.addTalkI d(7012)
# S1 @9 ]/ O' K: |9 t$ f X. K: i - STARTED.addTalkId(7009), {7 e% \6 h- K4 ?, |: S. g
- STARTED.addTalkId(7011)
Скопировать код
( b) s1 }. c! A* ~) T- L! q* { W5 G6 y( w. R
|