Рейтинг - 5.0 (3)

Всем привет! В этом, неожиданном для меня уроке, речь пойдёт о диалогах и о том, как можно использовать их, например, в процессе выполнения миссии, где нужно приехать в какую-то точку, и при этом персонажи разговаривали между собой.

Одним из способов является введение переменной-счётчика для цикла, и при выполнении условия с этим счётчиком мы выводим нужный нам текст. К этому же мы должны создать переменную-индекс, которая будет выводить текст по порядку. Для этого создадим в начале миссии транспорт и случайного актёра, после чего посадим их в транспорт:

Model.Load(#ADMIRAL)
038B: load_requested_models
4@ = car.Create(#ADMIRAL, 2495.6694, -1657.3169, 12.3608)
car.Angle(4@) = 89.0987
0229: set_car 4@ primary_color_to 1 secondary_color_to 1
Model.Destroy(#ADMIRAL)
0560: create_random_actor_in_car 4@ handle_as 3@
0430: put_actor 3@ into_car 4@ passenger_seat 0
072A: put_actor $PLAYER_ACTOR into_car 4@ driverseat

Дальше осветляем экран и вводим переменную-индекс и переменную-счётчик:

fade 1 1000
wait 1000
player.CanMove(0, 1)
actor.SetImmunities($PLAYER_ACTOR, 0, 0, 0, 0, 0)
0@ = 0 // index dialog
1@ = 0.0 // mini-timer dialog

Теперь нужно создать цикл, который будет увеличивать счётчик на 0.25. Это более менее хорошмй вариант. Дальше осуществим перебор условий:

:MISSION_AA_LOOP
wait 0
if
7 > 0@
then
jump @MISSION_AA_LOOP
end

if AND
0@ == 0
1@ >= 40.0
then
0AD0: show_formatted_text_lowpriority "CJ: I drive car in point!" time 5000
0@ += 1
1@ = 0.0
end

if AND
0@ == 1
1@ >= 45.0
then
0AD0: show_formatted_text_lowpriority "Friend: Ok. I sead down in this car!" time 5000
0@ += 1
1@ = 0.0
end

if AND
0@ == 2
1@ >= 45.0
then
0AD0: show_formatted_text_lowpriority "CJ: This point in location Observatory!" time 5000
0@ += 1
1@ = 0.0
end

if AND
0@ == 3
1@ >= 45.0
then
0AD0: show_formatted_text_lowpriority "Friend: I known. Is this car heavy?" time 5000
0@ += 1
1@ = 0.0
end

if AND
0@ == 4
1@ >= 45.0
then
0AD0: show_formatted_text_lowpriority "CJ: No. Light." time 3000
0@ += 1
1@ = 0.0
end

if AND
0@ == 5
1@ >= 25.0
then
0AD0: show_formatted_text_lowpriority "Friend: You drive very good!" time 5000
0@ += 1
1@ = 0.0
end

if AND
0@ == 6
1@ >= 45.0
then
0AD0: show_formatted_text_lowpriority "CJd: Thank you! I drive vehicles very time" time 5000
0@ += 1
1@ = 0.0
end

1@ += 0.25
jump @MISSION_AA_LOOP

У нас будет 7 фраз, каждая из которых имеет индекс, начинающийся с нуля. Сделаем проверку, что если индекс больше 6-ти, то прыгаем на метку начала цикла. Как показала практика, так будет более-менее оптимально для производительности. Дальше уже следуют ряд условий, в которых определяется какой текст и когда нужно выводить. К примеру, "0@ == 3" - идёт проверка на индекс. Если текущий индекс равен 3, то проверяем счётчик: "1@ >= 45.0" - если он больше, чем заданное число, то выводим текст, прибавляем индексу единицу и сбиваем счётчик на ноль.

И так текст будет по очереди выводится, пока индекс будет в заданном диапазоне. Чем меньше число для проверки 1@, тем быстрее выводится текст. В остановился на числе 45.0, так как оно хорошо подходит под время выводимого текста. Как я его получил? Просто:

  1. Беру длительность предыдущего текста ( текста выше по коду ) - в нашем случае это 5000;
  2. Делю его на 100, получаю 50. Отнимаю 5, получаю 45 и перевожу в дробное 45.0 - это примерно равно 5000 милисекундам ( ЭТО ЕСЛИ К 1@ ПРИБАВЛЯТЬ 0.25, КАК НАПИСАНО В КОДЕ ВЫШЕ. ЕСЛИ ПОМЕНЯТЬ ЭТО ЗНАЧЕНИЕ, ТО ПРОВЕРКУ НУЖНО БУДЕТ ПОДСТРАИВАТЬ )

Хорошо, фразы выводится по очереди. Теперь напишем условия, когда миссия считается проваленной:

if OR
car.Wrecked(4@)
02BF: car 4@ sunk
then
jump @MISSION_29_144_END_CAR
end
if
actor.Dead(3@)
then
jump @MISSION_29_144_END_ACT
end

И создадим соответствующие метки:

:MISSION_29_144_END_CAR
wait 0
gosub @MISSION_END
00BA: show_text_styled GXT 'M_FAIL' time 5000 style 1 // MISSION FAILED
0AD0: show_formatted_text_lowpriority "You car wrecked!" time 4000
return

:MISSION_29_144_END_ACT
wait 0
gosub @MISSION_END
00BA: show_text_styled GXT 'M_FAIL' time 5000 style 1 // MISSION FAILED
0AD0: show_formatted_text_lowpriority "You Friend dai!" time 4000
return

Теперь перед циклом добавим код, который будет говорить о том, куда ехать и создавать сферу и чекпоинт в нужном месте:

:MISSION_AA
wait 0
marker.Disable(5@)
marker.Disable(7@)
018A: 5@ = create_checkpoint_at 1695.4817 -2107.7493 13.5469
03BC: 6@ = create_sphere_at 1695.4817 -2107.7493 13.5469 radius 2.0
0AD0: show_formatted_text_lowpriority "Drive to point!" time 4000

Добавим проверку, что когда игрок с актёром в этой точке, то завершить миссию и сообщить о успешном её выполнении:

:MISSION_AA_LOOP
wait 0

// ...

if AND
actor.InCar($PLAYER_ACTOR, 4@)
actor.InCar(3@, 4@)
00EC: actor $PLAYER_ACTOR sphere 0 near_point 1695.4817 -2107.7493 radius 2.0 2.0
then
jump @MISSION_CC
end

// ...

jump @MISSION_AA_LOOP

:MISSION_CC
marker.Disable(5@)
03BD: destroy_sphere 6@
00BE: text_clear_all
player.CanMove(0, 0)
actor.SetImmunities($PLAYER_ACTOR, 1, 1, 1, 1, 1)
fade 0 1000
wait 1000
0633: AS_actor $PLAYER_ACTOR exit_car

while actor.InCar($PLAYER_ACTOR, 4@)
wait 0
end

gosub @MISSION_END
actor.PutAt($PLAYER_ACTOR, 1698.6144, -2096.208, 12.5469)
actor.Angle($PLAYER_ACTOR) = 181.9148
camera.Restore_WithJumpCut
Camera.SetBehindPlayer
wait 500
fade 1 1000
wait 1000
player.CanMove(0, 1)
actor.SetImmunities($PLAYER_ACTOR, 0, 0, 0, 0, 0)
0394: play_music 1
00BA: show_text_styled GXT 'M_PASSR' time 5000 style 1 // MISSION PASSED
return

Осталось добавить ещё одну вещь: организовать проверку на то, что актёр или игрок покинули транспорт. Я сделал это следующим образом:

:MISSION_AA_LOOP
wait 0

// ...

if OR
not actor.InCar($PLAYER_ACTOR, 4@)
not actor.InCar(3@, 4@)
then
jump @MISSION_BB
end

// ...

jump @MISSION_AA_LOOP

:MISSION_BB
wait 0
marker.Disable(5@)
03BD: destroy_sphere 6@
00BE: text_clear_all
5@ = marker.CreateAboveActor(3@)
07E0: set_marker 5@ type_to 1
7@ = marker.CreateAboveCar(4@)
07E0: set_marker 7@ type_to 1
0AD0: show_formatted_text_lowpriority "Hey, run in car!" time 4000

:MISSION_BB_LOOP
wait 0
if OR
car.Wrecked(4@)
02BF: car 4@ sunk
then
jump @MISSION_29_144_END_CAR
end
if
actor.Dead(3@)
then
jump @MISSION_29_144_END_ACT
end
if AND
actor.InCar($PLAYER_ACTOR, 4@)
actor.InCar(3@, 4@)
then
jump @MISSION_AA
end
jump @MISSION_BB_LOOP

Таким образом, диалог будет происходить только тогда, когда СЖ и этот случайный актёр будут в машине 4@. Если соединить всё вместе, то получится следующий код:

{$CLEO .cm}

//------------- Mission ---------------

:MISSION
thread 'MISSION'
gosub @MISSION_29_57 
if 
wasted_or_busted 
jf @MISSION_29_46 
gosub @MISSION_29_144 

:MISSION_29_46
$ONMISSION = 0 
mission_cleanup 
end_thread 

:MISSION_29_57
increment_mission_attempts 
$ONMISSION = 1 
Model.Load(#ADMIRAL)
038B: load_requested_models
4@ = car.Create(#ADMIRAL, 2495.6694, -1657.3169, 12.3608)
car.Angle(4@) = 89.0987
0229: set_car 4@ primary_color_to 1 secondary_color_to 1
Model.Destroy(#ADMIRAL)
0560: create_random_actor_in_car 4@ handle_as 3@
0430: put_actor 3@ into_car 4@ passenger_seat 0
072A: put_actor $PLAYER_ACTOR into_car 4@ driverseat
wait 1000
camera.Restore_WithJumpCut
Camera.SetBehindPlayer
fade 1 1000
wait 1000
player.CanMove(0, 1)
actor.SetImmunities($PLAYER_ACTOR, 0, 0, 0, 0, 0)
0@ = 0 // index dialog
1@ = 0.0 // mini-timer dialog

:MISSION_AA
wait 0
marker.Disable(5@)
marker.Disable(7@)
018A: 5@ = create_checkpoint_at 1695.4817 -2107.7493 13.5469
03BC: 6@ = create_sphere_at 1695.4817 -2107.7493 13.5469 radius 2.0
0AD0: show_formatted_text_lowpriority "Drive to point!" time 4000

:MISSION_AA_LOOP
wait 0
if OR
car.Wrecked(4@)
02BF: car 4@ sunk
then
jump @MISSION_29_144_END_CAR
end
if
actor.Dead(3@)
then
jump @MISSION_29_144_END_ACT
end
if OR
not actor.InCar($PLAYER_ACTOR, 4@)
not actor.InCar(3@, 4@)
then
jump @MISSION_BB
end
if AND
actor.InCar($PLAYER_ACTOR, 4@)
actor.InCar(3@, 4@)
00EC: actor $PLAYER_ACTOR sphere 0 near_point 1695.4817 -2107.7493 radius 2.0 2.0
then
jump @MISSION_CC
end

if
0@ > 6
then
jump @MISSION_AA_LOOP
end
if AND
0@ == 0
1@ >= 40.0
then
0AD0: show_formatted_text_lowpriority "CJ: I drive car in point!" time 5000
0@ += 1
1@ = 0.0
end
if AND
0@ == 1
1@ >= 45.0
then
0AD0: show_formatted_text_lowpriority "Friend: Ok. I sead down in this car!" time 5000
0@ += 1
1@ = 0.0
end
if AND
0@ == 2
1@ >= 45.0
then
0AD0: show_formatted_text_lowpriority "CJ: This point in location Observatory!" time 5000
0@ += 1
1@ = 0.0
end
if AND
0@ == 3
1@ >= 45.0
then
0AD0: show_formatted_text_lowpriority "Friend: I known. Is this car heavy?" time 5000
0@ += 1
1@ = 0.0
end
if AND
0@ == 4
1@ >= 45.0
then
0AD0: show_formatted_text_lowpriority "CJ: No. Light." time 3000
0@ += 1
1@ = 0.0
end
if AND
0@ == 5
1@ >= 25.0
then
0AD0: show_formatted_text_lowpriority "Friend: You drive very good!" time 5000
0@ += 1
1@ = 0.0
end
if AND
0@ == 6
1@ >= 45.0
then
0AD0: show_formatted_text_lowpriority "CJd: Thank you! I drive vehicles very time" time 5000
0@ += 1
1@ = 0.0
end
1@ += 0.25
jump @MISSION_AA_LOOP

:MISSION_BB
wait 0
marker.Disable(5@)
03BD: destroy_sphere 6@
00BE: text_clear_all
5@ = marker.CreateAboveActor(3@)
07E0: set_marker 5@ type_to 1
7@ = marker.CreateAboveCar(4@)
07E0: set_marker 7@ type_to 1
0AD0: show_formatted_text_lowpriority "Hey, run in car!" time 4000

:MISSION_BB_LOOP
wait 0
if OR
car.Wrecked(4@)
02BF: car 4@ sunk
then
jump @MISSION_29_144_END_CAR
end
if
actor.Dead(3@)
then
jump @MISSION_29_144_END_ACT
end
if AND
actor.InCar($PLAYER_ACTOR, 4@)
actor.InCar(3@, 4@)
then
jump @MISSION_AA
end
jump @MISSION_BB_LOOP

:MISSION_CC
marker.Disable(5@)
03BD: destroy_sphere 6@
00BE: text_clear_all
player.CanMove(0, 0)
actor.SetImmunities($PLAYER_ACTOR, 1, 1, 1, 1, 1)
fade 0 1000
wait 1000
0633: AS_actor $PLAYER_ACTOR exit_car

while actor.InCar($PLAYER_ACTOR, 4@)
wait 0
end

gosub @MISSION_END
actor.PutAt($PLAYER_ACTOR, 1698.6144, -2096.208, 12.5469)
actor.Angle($PLAYER_ACTOR) = 181.9148
camera.Restore_WithJumpCut
Camera.SetBehindPlayer
wait 500
fade 1 1000
wait 1000
player.CanMove(0, 1)
actor.SetImmunities($PLAYER_ACTOR, 0, 0, 0, 0, 0)
0394: play_music 1
00BA: show_text_styled GXT 'M_PASSR' time 5000 style 1 // MISSION PASSED
return 

:MISSION_29_144
wait 0 
gosub @MISSION_END
00BA: show_text_styled GXT 'M_FAIL' time 5000 style 1 // MISSION FAILED
return

:MISSION_29_144_END_CAR
wait 0 
gosub @MISSION_END
00BA: show_text_styled GXT 'M_FAIL' time 5000 style 1 // MISSION FAILED
0AD0: show_formatted_text_lowpriority "You car wrecked!" time 4000
return

:MISSION_29_144_END_ACT
wait 0 
gosub @MISSION_END
00BA: show_text_styled GXT 'M_FAIL' time 5000 style 1 // MISSION FAILED
0AD0: show_formatted_text_lowpriority "You Friend dai!" time 4000
return

:MISSION_END
wait 0
if
056D: actor 3@ defined
then
actor.RemoveReferences(3@)
actor.DestroyInstantly(3@)
end
if
056E: car 4@ defined
then
car.RemoveReferences(4@)
 if
 not actor.InCar($PLAYER_ACTOR, 4@)
 then
 car.Destroy(4@)
 end
end
marker.Disable(5@)
marker.Disable(7@)
03BD: destroy_sphere 6@
return

Что же, это один из способов вывода текста последовательно, имитируя диалог между персонажами. Надеюсь, он поможет Вам у проектах ;)


Теги: Диалоги в миссиях
1 2 »

Slivkin-Sergey   (07.08.13 18:11)
Вау, целый урок! Спасибо... Только я не очень понял, ведь переменным 0@ и 1@ присаивались значения 0 и 0.0, почему проверка дала положительный результат?

wmysterio   (07.08.13 18:23)
Это потому, что в цикле мы прибавляли к 1@ число 0.25
Код
1@ += 0.25
Счётчик всегда менялся. Дальше уже дело за проверками.

Slivkin-Sergey   (07.08.13 18:38)
А-а-а... я почти понял... но по идее тексты должны проноситься с неимоверной скорости, ведь после показа текстов нет задержки...

wmysterio   (07.08.13 18:47)
Slivkin-Sergey, Считай, что 1@ - это и есть задержка, только не потока, а именно текста.

Slivkin-Sergey   (07.08.13 19:08)
wmysterio, но как скрипт понимает, что это - задержка?

wmysterio   (07.08.13 19:21)
Slivkin-Sergey, это всё делает цикл, с которыми ты не любишь дружить smile Но слово "задержка" - это уже громко сказано. Это имитация задержки, путём математических операций.

Slivkin-Sergey   (07.08.13 19:27)
wmysterio, это типа скрипт очень долго их производит?.. Или как... *derpy idiot face*

Slivkin-Sergey   (07.08.13 19:37)
Кстати, как понимать вот это:
Код
1@ = 0.0
end
if AND
0@ == 6
1@ >= 45.0
then
0AD0: show_formatted_text_lowpriority "CJd: Thank you! I drive vehicles very time" time 5000

Сначала ты присваиваешь переменной 1@ значение 0, а потом пытаешься проверить, больше ли она 45...

wmysterio   (07.08.13 19:40)
Slivkin-Sergey, в какой-то мере да. Проходит примерно 180 итераций(шагов) цикла, когда 1@ станет равно 45.0 и это время очень примерно равно 5000 мили-секунд. Это тоже самое, что написать wait 27 180 раз подряд smile

Slivkin-Sergey   (07.08.13 19:52)
wmysterio, можешь рассказать, какие нужны числа для одной фразы-диаложинки, и, опираясь от этого, можно сделать цикл на любое количество фраз...

wmysterio   (07.08.13 20:02)
Slivkin-Sergey, Вот для одной фразы из диалога:
Код
// .. .. ..
0@ = 0
1@ = 0.0

:MISSION_AA_LOOP
wait 0

//
// Условия выхода с цикла
//

if
0@ > 0 // количество ФРАЗ - 1
then
jump @MISSION_AA_LOOP
end

if AND
0@ == 0
1@ >= 45.0 // сколько нужно ждать перед тем как текст появится, в данном случаи, спустя ~5 секунд появится текст, если нужно сразу вывести текст, то просто пишем условие 1@ >= 0.0
then
0AD0: show_formatted_text_lowpriority "CJ: I drive car in point!" time 5000
0@ += 1
1@ = 0.0
end

1@ += 0.25 // будет постоянно прибавлять к 1@ число 0.25
jump @MISSION_AA_LOOP
Я же написал в уроке, как я получал нужную задержку

blackful   (08.08.13 02:42)
почему у меня иногда пишет "Неверный символ в идентификаторе MISSION_3 " вот:
Код
:MISSION_2
thread 'MISSION'_2
gosub @MISSION_2
if
wasted_or_busted
jf @MISSION_3
gosub @MISSION_4

:MISSION_3
$ONMISSION = 0
mission_cleanup
end_thread

wmysterio   (08.08.13 05:10)
blackful, Во-первых:  это не относится к теме урока, в подобных случаях обращайтесь на форум. Во-вторых: предоставленный вами код полностью не правильный:
1) имя потока
Код
thread 'MISSION'_2 // нужно thread 'MISSION_2'
2) префикс всех меток не соответствует имени потока
Код
@MISSION_3 // нужно @MISSION_2_3
@MISSION_4 // нужно @MISSION_2_4
:MISSION_3 // нужно :MISSION_2_3

blackful   (08.08.13 08:59)
wmysterio, спасибо, а вот вы исходник вставили, там почти такая же ошибка как у меня "Неверный символ в идентификаторе MISSION_29_57 ." я тупо скопировал и вставил ,просто для интереса,  в чём проблема может быть? объясните пожалуйста.

wmysterio   (08.08.13 12:30)
blackful, есть глюк подсветки синтаксиса: при добавлении кода иногда расставляются лишние пробелы. Возможно у вас этот пробел где-то подставился и из-за этого появляется ошибка
1-15 16-18
Вход на сайт

Поиск
Категории раздела
Мини-чат
Пожалуйста, все вопросы по скриптингу задавать на форуме!
Наш опрос
Как Вы узнали о сайте?
Всего ответов: 9
Активность на сайте
Пожертвования
Кошельки WebMoney:
U859420971000
R407741810602
Z331072372430
E314272616890
Друзья сайта
Полезные ресурсы
Статистика

Онлайн всего: 1
Гостей: 1
Пользователей: 0

Сегодня нас посетили:
Рекомендую
Реклама