# 000133. Делаем диалоги в миссиях

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

```
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, так как оно хорошо подходит под время выводимого текста. Как я его получил? Просто:

* Беру длительность предыдущего текста ( текста выше по коду ) - в нашем случае это 5000;
* Делю его на 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
```

Что же, это один из способов вывода текста последовательно, имитируя диалог между персонажами. Надеюсь, он поможет Вам у проектах ;)|1550|1|0||delaem\_dialogi\_v\_missijakh|1504590898


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://lessons.sannybuilder.com/00100/00600/000133.-delaem-dialogi-v-missiyakh.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
