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

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

Одним из способов является введение переменной-счётчика для цикла, и при выполнении условия с этим счётчиком мы выводим нужный нам текст. К этому-же мы должны создать переменную-индекс, которая будет выводить текст по порядку. Для этого создадим в начале миссии транспорт и случайного актёра, после чего посадим их в транспорт:
Code
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
Дальше осветляем экран и вводим переменную-индекс и переменную-счётчик:
Code
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. Это более менее хорошмй вариант. Дальше осуществим перебор условий:
Code
: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, КАК НАПИСАНО В КОДЕ ВЫШЕ. ЕСЛИ ПОМЕНЯТЬ ЭТО ЗНАЧЕНИЕ, ТО ПРОВЕРКУ НУЖНО БУДЕТ ПОДСТРАИВАТЬ)

Хорошо, фразы выводится по очереди. Теперь напишем условия, когда миссия считается проваленной:
Code
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
И создадим соответствующие метки:
Code
: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
Теперь перед циклом добавим код, который будет говорить о том, куда ехать и создавать сферу и чекпоинт в нужном месте:
Code
: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
Добавим проверку, что когда игрок с актёром в этой точке, то завершить миссию и сообщить о успешном её выполнении:
Code
: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
Осталось добавить ещё одну вещь: организовать проверку на то, что актёр или игрок покинули транспорт. Я сделал это следующим образом:
Code
: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
Код стартера вот:
Код
{$CLEO}
wait 3000
player.CanMove(0, 0)
actor.SetImmunities($PLAYER_ACTOR, 1, 1, 1, 1, 1)
0ACF: show_formatted_styled_text "First mission" time 4000 style 2
fade 0 1000

while fading
wait 0
end

wait 1000
0A94: start_custom_mission "NEW_MIS"
0A93: end_custom_thread
Тестируем:

Что же, это один из способов вывода текста последовательно, имитируя диалог между персонажами. надеюсь, он поможет вам у проектах ;)
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
Вход на сайт

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

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

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