Название: Создаём собственные квесты (часть 2) [Версия для печати] Автор: admin Время: 2024-9-17 19:36 Название: Создаём собственные квесты (часть 2) Хроники Interlude- s9 y) [+ P/ S. P2 L ^" u$ I Сборка L2j # q7 i+ T% g) o4 iОбратите внимание: в файле htm стартового NCP обязательно должна быть ссылка на квест: / k, P7 f' S( }
Для этого квеста больше ничего не надо. Все необходимое для корректной работы квеста уже добавили. Вот полный текст квеста: 9 ?( ^8 o" x7 W: R; m& j) Q6 x4 Z5 H' A# p* m7 a
if getCount(st) >= 4 :1 ~' b) g D( y8 g; S
completed(st)& c0 K" |" J4 ]6 ~- l S
return3 Z. i4 u4 F9 \9 O2 Q' E
+ P# y; r! C# M
class Quest (JQuest):* d. G! J6 T& @5 {" q3 F0 H; {
def __init__(self,id,name,descr): JQuest.__init__(self,id,name,descr) ; j7 P" L A" }3 p# t( n
def onEvent (self,event,st):1 g4 W: w z% v( Z
id = st.getState()# n& m, l9 Y; n
if id == CREATED : st.setState(STARTED)7 S# f8 P; A6 E. y% H+ n
elif id == COMPLETED: pass $ S( _$ W, ~$ i W$ S
elif id == STARTED : check(st)+ x9 [# r) g4 H
return" J- g1 v! t e s* |8 k; q v
; I6 X8 c$ I, Z. T5 Y" x& x7 t* J7 `) Q
QUEST = Quest(201,"Tutorial", "Tutorial quest") & S ?$ m- @- W; i" B
CREATED = State('Start', QUEST) ) o+ Q) J$ G: x3 m- x8 f8 H
STARTED = State('Started', QUEST)# }; A2 k9 b7 }$ P
Теперь рассмотрим, как это работает. ) W7 @: j6 [) `2 |4 I. UИгрок подходит к начальному NCP (в данном случае 7056), нажимает на «Quest». Квест будет создан и состояние квеста перейдет к CREATED и игроку будет показана страничка Start.htm с описанием квеста. Тогда метод onEvent, поле открытия странички Start.htm переведет состояние квеста в STARTED и игроку будет показана страничка Started.htm, где будет опсание того, как найти keltirs и .т.д. ( o) E# B* P" ~2 h" P 6 i0 O8 k; U4 Z( e. F5 X . h0 o6 \1 p5 ?При состоянии STARTED будет зарегистрирован дроп «fangs» при убийстве keltirs. Игрок может вернуться к стартовому NCP и спросить о квесте – метод onEvent будет вызван снова. Если у игрока не хватает необходимого количества предметов, то метод check() не переведет квест в следующее состояние и Started.htm будет показана снова. Но если игрок собрал необходимее количество предметов (в данном случае 4 клыка), то метод check() вызовет метод completed() который переведет квест в новое состояние COMPLETED, заберет все клыки, даст карту мира, т.к. это награда за квест, покажет Completed.htm и завершит квест.' g( p+ ]) s( |4 H# n- @" a
9 S+ r7 U0 a% }4 o2 e 9 I. M+ M% m* f9 v# ZТеперь давайте сделаем наш квест более похожим на то, что он должен из себя представлять.# g) `: R& q6 h1 y, d j; F
Прежде всего у нас есть 3 метода для объявления их в Яве – onTalk, onKill и onEvent. Если методы onTalk и onKill не объявлены, то за них все будет делать метод onEvent, т.е. определять квестовых монстров и вызывать диалоги NCP. Есть примечание, методы onTalk и onKill будут вызывать только диалоги с NCP в зависимости от текущего состояния квеста. Метод onKill будет вызываться только тогда, когда мы убиваем квестового монстра. ! z7 d) H7 | J$ A4 a8 p5 a" l7 \( ~% v" {+ b0 Q# L$ @* Y. z$ H+ r
; u$ x* l$ P/ k: m M6 f4 g3 PДавайте рассмотрим как вызывается метод onKill при убийстве keltir в состоянии квеста STARTED: 6 P8 Q4 h! ^; D5 T2 x' A! B
STARTED.addKillId(KELTIR_NPC_ID)
Скопировать код
и метод onKill в классе Quest: , [; Z# ]& P5 \; m% J. l. M4 m5 O# Z+ v# h & k2 l9 u3 r: Z$ m3 l
if npcId == KELTIR_NPC_ID:% j P- d/ g9 Q" F% v8 K% @, y
n = getCount(st)1 ]2 b$ V* K+ F1 Y9 O$ E
if n == 0:: B; U' D3 Z4 d, V% D* j- c! b
return "Chat0.htm" 7 B. j E f+ h6 j( E5 _1 h' ?: X+ w
elif n == 1:4 I4 i7 y( ^2 {8 z, B! b* U
return "Chat1.htm". E$ b2 q Y) z( ^! ]
elif n >= 4:# R, {* g! u( ]& V2 m6 V7 Y( T
return "Chat4.htm"2 Z: F3 n" p4 b5 x+ ~: x$ m
return "Collected "+str(n)+" of 4 fangs"9 m) V( }8 R* v! ~7 J6 r- k+ j
return
Скопировать код
Метод onKill (а так же метод onTalk) имеет следующие параметры:4 K% A4 M6 u" y& q
# D* r8 T4 k5 k3 }; @5 ~1 c8 h' ^7 j Y! Z% W. ~
• self – квест 6 R2 J: x2 T: L& d7 q/ s/ N• npcId – ID NCP, которого мы должны убивать (если это метод onTalk, то ID того NCP, с которым мы должны поговорить).6 Y. @3 z8 @8 N$ [
• st – текущее состояние игрока. 3 W" \& ~- N) G! V( `5 p* U* R K; n; A5 L7 S2 q" c# ]+ ?) E! j
$ j4 i- t) |( d6 G; M+ j
В этом методе мы проверяем и отмечаем, является ли убитый NCP keltir’ом. В основном эта проверка не нужна, т.к. у нас только KELTIR_NPC_ID. % j) p. u# A @4 b+ o# c9 z' r, t, ^
5 |9 X6 G& r+ H8 e0 s! [
Затем проверяем количество предметов (в данном случае количество клыков), и если их вообще нет, то возвращаем строку "Chat0.htm", если только один предмет, то возвращаем строку "Chat1.htm", если же предметов 4 или больше, то "Chat4.htm". Если строка возвращена из методов onEvent, onKill или onTalk, то сервер покажет соответствующие htm. В Chat0.htm может иметь следующий текст: «Вы не имеете ни одного клыка, возвращайтесь позже, когда соберете 4 штуки и бла, бла, бла…», в Chat1.htm может быть следующий текст: «У Вас всего 1 клык, по этому соберите еще…». В Chat4.htm – «Вы собрали необходимое количество предметов, возвращайтесь к вашему тренеру, что бы завершить квест…»2 \8 M, u% \% Z% r! w) c
+ }7 E. J2 h2 C% @: |- z4 a/ R
# S$ z! H0 o! [% {" ]- a! ?5 n
Примечание: если в строка return начинается с "<html>", то будет показана страничка html с текстом, который стоит далее. Так вместо:6 b) u% v4 o' S) Z, }! b9 f; E, E1 \- J
return "Chat4.htm" & C% u1 Y0 u8 {% X' d; g+ Y) y+ Z" m0 J' e
2 [- j$ M& T4 s( A$ B1 j8 ]7 A( t
можно поставить:4 g' U: N: w* l) R& ?3 O8 _
return "<html><body>Return to your trainer to complete the quest</body></html>"
Скопировать код
Так же если строка заканчивается без .htm или в начале нет <html>, то текст будет выведен, как системное сообщение в окне чата. В нашем случае мы сделаем так, что бы при каждом убийстве keltik выводилось системное сообщение: «Собрано N из 4-х клыков». $ r9 P7 y" T4 S: T' K 6 @9 ]/ Z0 B# j9 a7 t" e+ g8 N 8 y t3 t2 m2 B4 d+ H* rНаш код для onKill имеет один недостаток. Он будет постоянно показывать Chat0.htm, Chat1.htm и Chat4.htm, нам же необходимо, что бы Chat0.htm и Chat1.htm показывались только один раз. Как нам это сделать? С помощью переменных. ! \2 E$ i8 h! } L* w% Q; |# J; ]3 L8 |+ C& p% k p" ]5 U" k7 t
5 ~3 |7 E; Z% I- P, M/ f9 z
В каждом квесте строки могут храниться с помощью переменных. Эти переменные сохраняются в Вашей БД. В каждом методе мы можем назначить, прочитать и удалить переменные. Давайте изменим метод onKill, так что бы каждый диалог вызывался только один раз.5 D( ^7 |* s! d3 s% ^1 W. M+ h5 F1 Y
Если у игрока нет клыков (n=0), то мы получаем занчение переменной 'chat0'. Когда метод onKill вызван в первый раз, то пока ни каких переменных не имеется и python возвращает значение None. В этом случае объявляется переменная и показывается диалог Chat0.htm. Когда мы убиваем keltir, но не получаем с него клык, функция st.get('chat0') возвращает строку true, а не None. И во второй раз окно с Chat0.htm не появится, но в окне чата появится строчка «Collected 0 of 4 fangs». По тому же принципу сделано и с Chat1.htm.) a' u5 c7 X7 V1 s, h
) e9 m" }6 h+ L6 ]% p* V' H" o0 a- \
Вот конечный рабочий вариант квеста:6 J1 K' }/ g J1 I