Зарегистрируйтесь сейчас чтобы найти еще больше друзей, и получить полноценный доступ ко всем функциям сайта!
Для просмотра Вам необходимо авторизоваться Если Вы еще не зарегистрированы, перейдите по ссылке:Зарегистрироваться
x
Хроники Interlude+ l; B3 W% R4 I$ ^0 l
Сборка L2j
5 A4 L+ A6 ] E7 cОбратите внимание: в файле htm стартового NCP обязательно должна быть ссылка на квест:
& _6 C/ ?& O& R3 d9 M- STARTED.addQuestDrop(KELTIR_NPC_ID,FANGS_ITEM_ID,DROP_RATE)
Скопировать код Для этого квеста больше ничего не надо. Все необходимое для корректной работы квеста уже добавили. Вот полный текст квеста:
6 `2 g: ?8 f$ T! S: g' c' W2 [; M: x
- if getCount(st) >= 4 :
/ j; B6 O4 @+ B, V2 a - completed(st)
) N% D3 L# _# t9 y' C7 ]9 b- P - return1 k7 D3 x8 \9 R; \+ P4 D6 C
( {# [ Z+ F+ `- class Quest (JQuest):% a* y) ]6 R$ L* g( |* `
- def __init__(self,id,name,descr): JQuest.__init__(self,id,name,descr)+ R q& Z, h/ R! `* E8 W
- def onEvent (self,event,st):- \' F$ N" H. r6 @3 f0 e
- id = st.getState()3 Y2 d# @" p, l7 g% t
- if id == CREATED : st.setState(STARTED)3 `" N! v% V( R. t
- elif id == COMPLETED: pass
: n1 [* f0 N! _& o$ q7 v - elif id == STARTED : check(st)0 l( ?& f( p+ k; H V& E3 n ^9 ]% g
- return% U/ e" g5 a2 P9 {) Y4 v; e
' l+ p% Y" u9 n( g: u. k+ t- QUEST = Quest(201,"Tutorial", "Tutorial quest")
2 b. n& e+ m8 n- R - CREATED = State('Start', QUEST)
4 n' f' @$ l S3 S- I3 @ - STARTED = State('Started', QUEST)$ ^- Y R1 [6 c; h! D( t+ R
- COMPLETED = State('Completed', QUEST)
$ g5 h- [0 ]) i: x! B' E! w+ d
$ j) `6 u' \( c9 G6 U* T, c* c- QUEST.setInitialState(CREATED)
4 s' j2 K* R9 H1 H8 H - QUEST.addStartNpc(7056)
. f9 R! }; ]7 H& J8 x+ R - STARTED.addQuestDrop(KELTIR_NPC_ID,FANGS_ITEM_ID,DROP_RATE)
Скопировать код Теперь рассмотрим, как это работает.* Z1 C' y/ ~; q" X9 ?0 t8 N
Игрок подходит к начальному NCP (в данном случае 7056), нажимает на «Quest». Квест будет создан и состояние квеста перейдет к CREATED и игроку будет показана страничка Start.htm с описанием квеста. Тогда метод onEvent, поле открытия странички Start.htm переведет состояние квеста в STARTED и игроку будет показана страничка Started.htm, где будет опсание того, как найти keltirs и .т.д.
+ O+ s, B( Z, s9 S, S5 `+ u
6 s# N! j8 A i* j v& ~5 Y% j1 }
- ~9 X8 O- ] n, M) S A8 A: zПри состоянии STARTED будет зарегистрирован дроп «fangs» при убийстве keltirs. Игрок может вернуться к стартовому NCP и спросить о квесте – метод onEvent будет вызван снова. Если у игрока не хватает необходимого количества предметов, то метод check() не переведет квест в следующее состояние и Started.htm будет показана снова. Но если игрок собрал необходимее количество предметов (в данном случае 4 клыка), то метод check() вызовет метод completed() который переведет квест в новое состояние COMPLETED, заберет все клыки, даст карту мира, т.к. это награда за квест, покажет Completed.htm и завершит квест.
+ |/ ^' ?9 h5 S5 X! b1 h$ z: y5 P w
& |$ c" g4 Y, i$ U/ I) IТеперь давайте сделаем наш квест более похожим на то, что он должен из себя представлять.
4 Z) @- R. @$ n9 {Прежде всего у нас есть 3 метода для объявления их в Яве – onTalk, onKill и onEvent. Если методы onTalk и onKill не объявлены, то за них все будет делать метод onEvent, т.е. определять квестовых монстров и вызывать диалоги NCP. Есть примечание, методы onTalk и onKill будут вызывать только диалоги с NCP в зависимости от текущего состояния квеста. Метод onKill будет вызываться только тогда, когда мы убиваем квестового монстра.
/ P& t: P i/ @% d, R$ T9 E; c: V" K
U2 ^8 A) k J3 u4 {- P2 TДавайте рассмотрим как вызывается метод onKill при убийстве keltir в состоянии квеста STARTED:
; W0 e. [5 G# h- STARTED.addKillId(KELTIR_NPC_ID)
Скопировать код и метод onKill в классе Quest:
! q* y5 [4 H) n9 t* R$ b
1 L2 ~6 J) q3 g, W- class Quest (JQuest):. K0 c0 x! {( s7 ~6 K0 F5 P
- ...
. \+ N# T/ N/ s) J7 }/ }+ @+ E# D9 m5 X - def onKill (self,npcId,st):3 e' o& }3 T/ B/ R0 I
- if npcId == KELTIR_NPC_ID:5 u: Z k% D7 W. Y/ i) z/ O; q8 k
- n = getCount(st)- _4 K5 j# ~: O: v3 _
- if n == 0:
% j ?/ V: k3 L - return "Chat0.htm"
1 `: n5 L$ G, u* q* a$ \3 ` - elif n == 1:
" E" q4 a5 I& b2 M - return "Chat1.htm"9 b9 n: i! `: @2 f- g& x" k4 [
- elif n >= 4:
: a) O- b( \+ E5 b7 [& a1 j - return "Chat4.htm"
' ]/ r7 c8 K* U. B/ j0 W - return "Collected "+str(n)+" of 4 fangs"" q: `1 ?; _4 x& z+ _% S* f2 J
- return
Скопировать код Метод onKill (а так же метод onTalk) имеет следующие параметры:. E" C5 T8 _/ e
6 ?4 ]: Z4 }2 C& g: M; S K' S
; Q, M$ g3 C: |' \# c* ~ [• self – квест
( O# Z6 J% u( X1 e4 g0 Y• npcId – ID NCP, которого мы должны убивать (если это метод onTalk, то ID того NCP, с которым мы должны поговорить).
# ~% \, m4 g# {2 _9 z5 t• st – текущее состояние игрока.
& n! k! A4 k. [+ _5 D1 T7 k( j% U' A0 @3 }0 U% `/ c2 o2 r! }
# K+ g" E; `. b3 ]* t, b. I
В этом методе мы проверяем и отмечаем, является ли убитый NCP keltir’ом. В основном эта проверка не нужна, т.к. у нас только KELTIR_NPC_ID.0 Z# n, j! l/ }0 a) y3 ~' |: I
7 ]. \3 @- g- c' S% _# T% [7 C
: d% t, o3 K! A) f4 @# j0 |, _Затем проверяем количество предметов (в данном случае количество клыков), и если их вообще нет, то возвращаем строку "Chat0.htm", если только один предмет, то возвращаем строку "Chat1.htm", если же предметов 4 или больше, то "Chat4.htm". Если строка возвращена из методов onEvent, onKill или onTalk, то сервер покажет соответствующие htm. В Chat0.htm может иметь следующий текст: «Вы не имеете ни одного клыка, возвращайтесь позже, когда соберете 4 штуки и бла, бла, бла…», в Chat1.htm может быть следующий текст: «У Вас всего 1 клык, по этому соберите еще…». В Chat4.htm – «Вы собрали необходимое количество предметов, возвращайтесь к вашему тренеру, что бы завершить квест…»
' n; Z; r, r% K L
* z% _5 `9 c0 d8 g* Z: _( T$ R8 q' L. A9 c* r( ]* K
Примечание: если в строка return начинается с "<html>", то будет показана страничка html с текстом, который стоит далее. Так вместо:
5 d& l( g' S( T1 j" C# z3 areturn "Chat4.htm"" f' O5 B0 }7 O& L* T
5 e8 T: ? x. q/ D, C% L
6 S8 Y" ]0 D$ k2 B( Jможно поставить:
: z- w; A' p# G9 @5 q7 T/ R) S- return "<html><body>Return to your trainer to complete the quest</body></html>"
Скопировать код Так же если строка заканчивается без .htm или в начале нет <html>, то текст будет выведен, как системное сообщение в окне чата. В нашем случае мы сделаем так, что бы при каждом убийстве keltik выводилось системное сообщение: «Собрано N из 4-х клыков».3 x* S% a$ J( \
6 \ l; W/ y; y) {1 O7 s5 B* B1 h( X; @9 h1 ~! q- @1 i% w
Наш код для onKill имеет один недостаток. Он будет постоянно показывать Chat0.htm, Chat1.htm и Chat4.htm, нам же необходимо, что бы Chat0.htm и Chat1.htm показывались только один раз. Как нам это сделать? С помощью переменных.$ `4 k" _+ ]. q" U' {. `0 T- L
3 I) o3 d/ ?% K. @9 J% ?9 Y6 B4 v2 h/ I+ z% N
В каждом квесте строки могут храниться с помощью переменных. Эти переменные сохраняются в Вашей БД. В каждом методе мы можем назначить, прочитать и удалить переменные. Давайте изменим метод onKill, так что бы каждый диалог вызывался только один раз.
# ^: w: J# W" U3 `- def onKill (self,npcId,st):
2 K6 E( c; E% M5 Z7 Y1 P% u0 X - if npcId == KELTIR_NPC_ID:6 V; g* v7 _+ {. p
- n = getCount(st)8 r: k! [" v: \- ]. P. Z8 \
- if n == 0:
9 L3 O4 k6 e, {3 P) Q - if st.get('chat0') == None :6 O# n3 E; j2 }1 `& \" t
- st.set("chat0", "true")! a2 z4 V W5 O4 l1 x
- return "Chat0.htm"
5 r0 v# ?4 {* h1 f4 P: j - elif n == 1:
6 Z% f- a& q8 f( g/ a - if st.get('chat1') == None :
g" _" ]) U: E& E - st.set("chat1", "true")
1 i3 y: L1 W t2 O6 P, F - return "Chat1.htm"/ u. [3 `3 }5 I3 O& s3 S# t A
- elif n >= 4:
7 z, Q/ g% v& g/ L& q - return "Chat4.htm"4 H% R2 {( @3 I0 u. ~' _ H
- return "Collected "+str(n)+" of 4 fangs" p& p) e! w8 h8 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.9 B4 ]' c2 u" s: X
3 y, N1 G" X6 `- `5 G; f' T% d+ e5 P0 ]( t
Вот конечный рабочий вариант квеста:/ ?, Y" j6 ?1 @ n
- import sys
% U! c) G9 ?1 V6 t0 @# o8 e - from net.sf.l2j.gameserver.model.quest import State
* c7 t' S4 I6 E5 ]4 s) A - from net.sf.l2j.gameserver.model.quest import QuestState
( n( U D: n4 S1 d/ x - from net.sf.l2j.gameserver.model.quest.jython import QuestJython as JQuest/ {1 H& t- O* X s k+ G! X2 a
- : H' y6 i! i s! {' u8 r+ P
- KELTIR_NPC_ID = 12082
4 X6 Z3 P8 _. j2 M5 d - FANGS_ITEM_ID = 1859
& h' R0 B( I" ~0 l" D+ S$ r - DROP_RATE = 500000
, M3 J, `3 Q3 E$ ]
, Z$ s; t1 Y! {3 K( @3 N& |5 C- WORLD_MAP_ITEM_ID = 1665$ W+ M" _# S, U2 ~) l
+ @ \/ ?! Y2 @8 N# Q- def getCount(st) : M H6 x+ N; ]$ n
- return st.getQuestItemsCount(FANGS_ITEM_ID)
+ N' p! k( w3 p# F - / r- N1 P+ S/ V# i! q* Z
- def completed(st) :* z$ v3 ?3 h/ G$ E' `
- st.setState(COMPLETED)
! N0 A! i( I) i: [- z& I, v! z - st.clearQuestDrops(): x/ \9 c4 [; N& \; `+ @
- st.takeItems(FANGS_ITEM_ID,-1): `; O9 o4 t9 L. z* Z& o
- st.giveItems(WORLD_MAP_ITEM_ID,1)9 j+ l: m, G+ {- H0 V4 Y
- st.exitQuest(False)6 ~( ?- e- j" A( z& e
- return" Y) X4 t0 [" ^" ?7 H
- " F: p% q, _- m1 x+ T7 _
- def check(st) :
- d) n" {; S/ ]( y1 Q - if getCount(st) >= 4 :+ w3 R5 Q- u& f4 e
- completed(st)
! O3 `2 A' I! ]# O& m - return2 j! J& q7 {0 o ? k8 \
8 y: K4 h- y/ Z& v: Y- class Quest (JQuest):4 b8 k6 B8 K- T
7 S8 {7 k/ Q2 f2 N2 r6 L- def __init__(self,id,name,descr): JQuest.__init__(self,id,name,descr)' B# `$ w# G# Q1 E3 @% b
- 4 _1 x- }3 i: J! r0 G! _
- def onEvent (self,event,st):
, O' d% L4 C* r4 L - id = st.getState()+ A! @9 O1 i- `8 T" z
- if id == CREATED : st.setState(STARTED), x- k* T1 X5 E W3 Y
- elif id == COMPLETED: pass
2 R. j1 q. V5 u$ ?+ k - elif id == STARTED : check(st), A7 a7 |* @' P: x0 ~
- return) B' y+ B& k7 | j5 z
- ; q# U/ t; ], j4 F2 e
- def onKill (self,npcId,st):
# p* b1 ]# z' m2 i! P - if npcId == KELTIR_NPC_ID:) c1 Y/ `0 ^6 k( L- t! p
- n = getCount(st)& `- e* [' A( j0 l9 y$ Y$ ^
- if n == 0:
" @, b7 X6 A; G2 u% o - if st.get('chat0') == None :! v+ _% `, U" `2 W1 d4 d( F
- st.set("chat0", "true")7 Y( Z; e; T; c5 q: v6 w
- return "Chat0.htm"
; d* E$ u- p2 u2 \* ` - elif n == 1:: Y/ V8 z% c9 Y. u x
- if st.get('chat1') == None :9 q$ D {* F3 [2 E1 p4 d9 d+ r K. k
- st.set("chat1", "true")5 ^: ~) S9 _7 F) x+ X& p
- return "Chat1.htm"9 G6 w$ s( q. X- _7 t
- elif n >= 4:" D$ g& p5 B8 t9 L
- return "Chat4.htm"9 i$ ?' x+ x V( a% B
- return "Collect "+str(n)+" of 4 fangs"
5 s; W- _6 Z1 x - return
7 R- H% G4 c5 m& n* F - + `/ |: r, d* A7 F0 B
- QUEST = Quest(201, "Tutorial", "Tutorial quest")
4 j/ t, k7 W, d* e - CREATED = State('Start', QUEST)4 V0 J8 i& V; J+ b( C* h& }
- STARTED = State('Started', QUEST). ~# u E8 d6 M& g7 A! r
- COMPLETED = State('Completed', QUEST)
+ o0 C0 e6 |& g - 1 c- s' u0 _+ Q2 j/ A$ g! ]
- QUEST.setInitialState(CREATED)
- L2 }1 A7 R4 B* X; H$ H. P. G, R - QUEST.addStartNpc(7056)" @( J }# {" b
- QUEST.addStartNpc(7012)
, L' i( [( g; E) r- B' H - QUEST.addStartNpc(7009)2 J# ?: c6 y& X% n# o5 L. K/ Q
- QUEST.addStartNpc(7011)* ^- l7 d/ M8 a. n6 O
) E# v" ]: L4 Z- STARTED.addQuestDrop(KELTIR_NPC_ID,FANGS_ITEM_ID,DROP_RATE)
) i. L) U3 @/ @0 F: v - STARTED.addKillId(KELTIR_NPC_ID)( R! p1 q" i7 a% G% k" R$ F, K
- STARTED.addTalkId(7056)$ a. L8 r% [; d; ~
- STARTED.addTalkI d(7012)
. Q9 r* ~1 @6 G* W0 L3 O" S - STARTED.addTalkId(7009)
. \& m) X& o9 m' s - STARTED.addTalkId(7011)
Скопировать код 4 T2 @3 J6 M# o% d& f5 r% y
. R& I' ^8 `, H" T |