00094. Пропуск видеороликов

Пропуск видеороликов|Думаю многим знаком урок скриптинга в main.scm, где рассматривалось создание примитивного видеоролика. Этот урок будет так же посвящен созданию катсцены, но тема отличается тем, что мы будем делать возможность её пропуска.|wmysterio|wmysterio||||Всем привет. Я видел много скриптов, где использовались цикли с проверкой на нажатие клавиши, однако я планирую использовать намного лучший способ. Для таких целей используется два опкода:

0707: start_scene_skip_to @INTRO
0701: end_scene_skip

Первый опкод - делает мгновенный переход к метке "@INTRO". Особенность в том, что переход будет выполнен при нажатии клавиши ( пробел, шифт и т.п. ) не используя условия в коде, расположенного ниже, вплоть, до опкода "0701", что завершает сцену. Используя эти данные, давайте напишем скрипт, который делает ролик, который легко можно пропустить:

{$CLEO}
0000:
thread 'SCENE'
03BC: 0@ = create_sphere_at 2476.0601 -1681.2487 13.3413 radius 2.0

while 80EC: not actor $PLAYER_ACTOR 0 near_point 2476.0601 -1681.2487 radius 1.0 1.0
wait 0
end

03BD: destroy_sphere 0@
player.CanMove($PLAYER_CHAR) = false
actor.SetImmunities($PLAYER_ACTOR, 1, 1, 1, 1, 1)
fade 0 1000
wait 1000
04E4: unknown_refresh_game_renderer_at 2486.915 -1673.9196
Camera.SetAtPos(2486.915, -1673.9196, 13.3359)
Camera.SetPosition(2486.915, -1673.9196, 13.3359, 0.0, 0.0, 0.0)
Camera.PointAt(2485.3206, -1676.1002, 13.3382, 2)
actor.PutAt($PLAYER_ACTOR, 2484.4446, -1678.1494, 12.3367)
actor.Angle($PLAYER_ACTOR) = 54.63
0376: 1@ = create_random_actor_at 2483.2427 -1677.151 12.3374
actor.Angle(1@) = 232.9327
0826: enable_hud 0
02A3: enable_widescreen 1
wait 1000
03E6: remove_text_box
00BE: text_clear_all
fade 1 1000
0707: start_scene_skip_to @SCENE { Вызов ролика, которого можно пропустить }
wait 1000
//сам ролик:
0AD0: show_formatted_text_lowpriority "C£pa¢a cžy¤a®¨ ak¦ep" time 5000 // Справа случайный актер
wait 5000
0AD0: show_formatted_text_lowpriority "A cže¢a - CJ" time 5000 // А слева - CJ
wait 5000
0AD0: show_formatted_text_lowpriority ""¦o ¦ec¦o¢¨ požœk" time 5000 // Это тестовый ролик
wait 5000

:SCENE { Метка окончания ролика }
wait 0
fade 0 1000
0701: end_scene_skip
wait 1000
0826: enable_hud 1
02A3: enable_widescreen 0
03E6: remove_text_box
00BE: text_clear_all
actor.RemoveReferences(1@)
actor.DestroyInstantly(1@)
actor.PutAt($PLAYER_ACTOR, 2480.1101, -1678.0629, 13.3401)
actor.Angle($PLAYER_ACTOR) = 303.6017
Camera.Restore_WithJumpCut
Camera.SetBehindPlayer
wait 1000
fade 1 1000
wait 1000
player.CanMove($PLAYER_CHAR) = true
actor.SetImmunities($PLAYER_ACTOR, 0, 0, 0, 0, 0)
0A93: end_custom_thread

Результат:

Если вы нажмёте пробел во время ролика, то вы увидите, как экран начнёт темнеть и в скорее Вы перейдёте в режим игры. То есть, всё, что находится в блоке между опкодами "0707" и "0701" можно пропускать. Здесь я могу сделать несколько советов, которые могут предотвратить вылет игры, так как новички часто забывают о проверках.

Начну с того, что рекомендовано создавать всех используемых субъектов в ролике ещё до объявления опкода "0707". Приведу пример: примерно в середине ролика вы создали актёра, который будет выполнять какие то функции в нём. Нужно учесть, что если нужно будет удалить его с игры или использовать в дальнейшем, то после пропуска ролика нужно обязательно проверить на существование, так как играющий может пропустить ролик ещё до создания актёра.

Так как актёр не создан и идёт уничтожение актёра после ролика, то естественно будет вылет. Для примера, давайте усовершенствуем наш скрипт, сделаем, что бы во время диалога приходил 2-й созданный актёр и вступал в диалог. После катсцены, делаем проверки. Вот код примера:

{$CLEO}
0000:
thread 'SCENE'
03BC: 0@ = create_sphere_at 2476.0601 -1681.2487 13.3413 radius 2.0

while 80EC: not actor $PLAYER_ACTOR 0 near_point 2476.0601 -1681.2487 radius 1.0 1.0
wait 0
end

03BD: destroy_sphere 0@
player.CanMove($PLAYER_CHAR) = false
actor.SetImmunities($PLAYER_ACTOR, 1, 1, 1, 1, 1)
fade 0 1000
wait 1000
04E4: unknown_refresh_game_renderer_at 2486.915 -1673.9196
Camera.SetAtPos(2486.915, -1673.9196, 13.3359)
Camera.SetPosition(2486.915, -1673.9196, 13.3359, 0.0, 0.0, 0.0)
Camera.PointAt(2485.3206, -1676.1002, 13.3382, 2)
actor.PutAt($PLAYER_ACTOR, 2484.4446, -1678.1494, 12.3367)
actor.Angle($PLAYER_ACTOR) = 54.63
0376: 1@ = create_random_actor_at 2483.2427 -1677.151 12.3374
actor.Angle(1@) = 232.9327
0826: enable_hud 0
02A3: enable_widescreen 1
wait 1000
03E6: remove_text_box
00BE: text_clear_all
fade 1 1000
0707: start_scene_skip_to @SCENE
wait 1000
0AD0: show_formatted_text_lowpriority "C£pa¢a cžy¤a®¨ ak¦ep" time 5000
wait 5000
0AD0: show_formatted_text_lowpriority "A cže¢a - CJ" time 5000
wait 5000
0AD0: show_formatted_text_lowpriority ""¦o ¦ec¦o¢¨ požœk" time 5000
wait 5000

0376: 2@ = create_random_actor_at 2488.4609 -1671.9213 12.3359
actor.Angle(2@) = 145.077
07CD: AS_actor 2@ walk_to 2484.9302 -1676.5956 13.3378 stop_with_angle 139.4369 within_radius 1.0
wait 250
Camera.SetPosition(2482.2092, -1680.7852, 13.3318, 0.0, 0.0, 0.0)
Camera.PointAt(2485.3206, -1676.1002, 13.3382, 2)

while 80EC: not actor 2@ 0 near_point 2484.9302 -1676.5956 radius 1.0 1.0
wait 0
end
0AD0: show_formatted_text_lowpriority "Œpœ¥ež ¦pe¦œ ak¦ep" time 5000
wait 5000 //этот блок создаёт случайного актёра и заставляет его подойти к точке

:SCENE
wait 0
fade 0 1000
0701: end_scene_skip
wait 1000
if
actor.Defined(2@)
then
marker.CreateAboveActor(3@, 2@)
end // если мы планируем поставить маркер над актёром, то обязательно нужно делать проверку!
0826: enable_hud 1
02A3: enable_widescreen 0
03E6: remove_text_box
00BE: text_clear_all
actor.RemoveReferences(1@)
actor.DestroyInstantly(1@)
actor.PutAt($PLAYER_ACTOR, 2480.1101, -1678.0629, 13.3401)
actor.Angle($PLAYER_ACTOR) = 303.6017
Camera.Restore_WithJumpCut
Camera.SetBehindPlayer
wait 1000
fade 1 1000
wait 1000
player.CanMove($PLAYER_CHAR) = true
actor.SetImmunities($PLAYER_ACTOR, 0, 0, 0, 0, 0)
0A93: end_custom_thread

В случае, если нам актёр нужен для дальнейшей манипуляции, то нам необходимо заново создать его ( если пропуск ролика был до самого создания ). Из этого делаем вывод, что лучше создать необходимые субъекты до ролика, что бы потом не играться со всякими проверками.

Но всё же иногда ситуация вынуждает нас делать проверки, что бы улучшить мод. Например: при завершении ролика 3 актёра садились в машину. Если пропустить ролик, то актёры естественно никуда не сядут =) Давайте нашим ещё один пример, что бы эти актёры в любом случаи сели в автомобиль. Создавать все субъекты мы будем до ролика, что уменьшает количество условий:

{$CLEO}
0000:
thread 'SCENE'
03BC: 0@ = create_sphere_at 2476.0601 -1681.2487 13.3413 radius 2.0

while 80EC: not actor $PLAYER_ACTOR 0 near_point 2476.0601 -1681.2487 radius 1.0 1.0
wait 0
end
model.Load(#ADMIRAL)
038B: load_requested_models

while not model.Available(#ADMIRAL)
wait 0
end

03BD: destroy_sphere 0@
player.CanMove($PLAYER_CHAR) = false
actor.SetImmunities($PLAYER_ACTOR, 1, 1, 1, 1, 1)
fade 0 1000
wait 1000
04E4: unknown_refresh_game_renderer_at 2486.915 -1673.9196
Camera.SetAtPos(2486.915, -1673.9196, 13.3359)
Camera.SetPosition(2486.915, -1673.9196, 13.3359, 0.0, 0.0, 0.0)
Camera.PointAt(2485.3206, -1676.1002, 13.3382, 2)
actor.PutAt($PLAYER_ACTOR, 2484.4446, -1678.1494, 12.3367)
actor.Angle($PLAYER_ACTOR) = 54.63
0376: 1@ = create_random_actor_at 2483.2427 -1677.151 12.3374
actor.Angle(1@) = 232.9327
0376: 2@ = create_random_actor_at 2488.4609 -1671.9213 12.3359
actor.Angle(2@) = 145.077
3@ = car.Create(#ADMIRAL, 2482.4629, -1670.8448, 13.3404)
car.Angle(3@) = 43.8693
0826: enable_hud 0
02A3: enable_widescreen 1
wait 1000
03E6: remove_text_box
00BE: text_clear_all
fade 1 1000
0707: start_scene_skip_to @SCENE
wait 1000
0AD0: show_formatted_text_lowpriority "C£pa¢a cžy¤a®¨ ak¦ep" time 5000
wait 5000
0AD0: show_formatted_text_lowpriority "A cže¢a - CJ" time 5000
wait 5000
0AD0: show_formatted_text_lowpriority ""¦o ¦ec¦o¢¨ požœk" time 5000
wait 5000
07CD: AS_actor 2@ walk_to 2484.9302 -1676.5956 13.3378 stop_with_angle 139.4369 within_radius 1.0
wait 250
Camera.SetPosition(2482.2092, -1680.7852, 13.3318, 0.0, 0.0, 0.0)
Camera.PointAt(2485.3206, -1676.1002, 13.3382, 2)

while 80EC: not actor 2@ 0 near_point 2484.9302 -1676.5956 radius 1.0 1.0
wait 0
end

0AD0: show_formatted_text_lowpriority "Œpœ¥ež ¦pe¦œ ak¦ep" time 5000
wait 5000
0AD0: show_formatted_text_lowpriority "Cežœ ¢ce ¢ ¯a¥œ®y" time 5000
Camera.SetPosition(2493.0073, -1684.394, 13.5095, 0.0, 0.0, 0.0)
Camera.PointAt(2486.0164, -1677.4105, 13.3372, 2)
05CB: AS_actor $PLAYER_ACTOR enter_car 3@ as_driver 20000 ms
05CA: AS_actor 1@ enter_car 3@ passenger_seat 0 20000 ms
05CA: AS_actor 2@ enter_car 3@ passenger_seat 1 20000 ms

:SCENE_A
wait 0
if AND
actor.InCar($PLAYER_ACTOR, 3@)
actor.InCar(1@, 3@)
actor.InCar(2@, 3@)
jf @SCENE_A // заставляем актёров сесть в тачку

:SCENE
wait 0
fade 0 1000
0701: end_scene_skip
wait 1000

if
not actor.InCar($PLAYER_ACTOR, 3@)
then
05CB: AS_actor $PLAYER_ACTOR enter_car 3@ as_driver 0 ms
end
if
not actor.InCar(1@, 3@)
then
05CA: AS_actor 1@ enter_car 3@ passenger_seat 0 0 ms
end
if
not actor.InCar(2@, 3@)
then
05CA: AS_actor 2@ enter_car 3@ passenger_seat 1 0 ms
end
{ блок условий, если игрок пропустил ролик, а актёры не в машине, то
при срабатывании проверки мгновенно перемещаем их в нужную тачку }

0826: enable_hud 1
02A3: enable_widescreen 0
03E6: remove_text_box
00BE: text_clear_all
Camera.Restore_WithJumpCut
Camera.SetBehindPlayer
wait 1000
fade 1 1000
wait 1000
player.CanMove($PLAYER_CHAR) = true
actor.SetImmunities($PLAYER_ACTOR, 0, 0, 0, 0, 0)
0A93: end_custom_thread

Результат:

Рассмотрим ещё один пример. Он касается перемещения камеры с помощью опкодов "0936" и "0920". Есть один глюк, когда пропустить ролик во время перемещения камеры, то при завершении ролика команды "Camera.Restore_WithJumpCut" и "Camera.SetBehindPlayer" не срабатывают и камера перемещается дальше, игнорируя их. С этой проблемой я соткнулся при разработке мода "GTA SA - Карьерист" и сейчас я расскажу как избавится от этой зависимости.

А избавился довольно просто - дублировал перемещения, изменив только вемя на "0" и тип перемещения поставил "0". Таким образом мы заставяем камеру мгновенно переместится в нужную точку и при пропуске ролика ненужный эффект перехода камеры будет анулирован. Давайте к нашему скрипту допишем ещё и перемещения камеры, что бы всё было как "нужно":

{$CLEO}
0000:
thread 'SCENE'
03BC: 0@ = create_sphere_at 2476.0601 -1681.2487 13.3413 radius 2.0

while 80EC: not actor $PLAYER_ACTOR 0 near_point 2476.0601 -1681.2487 radius 1.0 1.0
wait 0
end
model.Load(#ADMIRAL)
038B: load_requested_models

while not model.Available(#ADMIRAL)
wait 0
end

03BD: destroy_sphere 0@
player.CanMove($PLAYER_CHAR) = false
actor.SetImmunities($PLAYER_ACTOR, 1, 1, 1, 1, 1)
fade 0 1000
wait 1000
04E4: unknown_refresh_game_renderer_at 2486.915 -1673.9196
Camera.SetAtPos(2486.915, -1673.9196, 13.3359)
Camera.SetPosition(2486.915, -1673.9196, 13.3359, 0.0, 0.0, 0.0)
Camera.PointAt(2485.3206, -1676.1002, 13.3382, 2)
actor.PutAt($PLAYER_ACTOR, 2484.4446, -1678.1494, 12.3367)
actor.Angle($PLAYER_ACTOR) = 54.63
0376: 1@ = create_random_actor_at 2483.2427 -1677.151 12.3374
actor.Angle(1@) = 232.9327
0376: 2@ = create_random_actor_at 2488.4609 -1671.9213 12.3359
actor.Angle(2@) = 145.077
3@ = car.Create(#ADMIRAL, 2482.4629, -1670.8448, 13.3404)
car.Angle(3@) = 43.8693
0826: enable_hud 0
02A3: enable_widescreen 1
wait 1000
03E6: remove_text_box
00BE: text_clear_all
fade 1 1000
0707: start_scene_skip_to @SCENE
wait 1000
0AD0: show_formatted_text_lowpriority "C?pa?a c?y¤a?®?? ak¦ep" time 5000
wait 5000
0AD0: show_formatted_text_lowpriority "A c?e?a - CJ" time 5000
wait 5000
0AD0: show_formatted_text_lowpriority ""¦o ¦ec¦o??? po??k" time 5000
wait 5000
07CD: AS_actor 2@ walk_to 2484.9302 -1676.5956 13.3378 stop_with_angle 139.4369 within_radius 1.0
wait 250
Camera.SetPosition(2482.2092, -1680.7852, 13.3318, 0.0, 0.0, 0.0)
Camera.PointAt(2485.3206, -1676.1002, 13.3382, 2)

while 80EC: not actor 2@ 0 near_point 2484.9302 -1676.5956 radius 1.0 1.0
wait 0
end

0AD0: show_formatted_text_lowpriority "?p??e? ¦pe¦?? ak¦ep" time 5000
wait 5000
0AD0: show_formatted_text_lowpriority "Ce?? ?ce ? ?a??®y" time 5000
Camera.SetPosition(2493.0073, -1684.394, 13.5095, 0.0, 0.0, 0.0)
Camera.PointAt(2486.0164, -1677.4105, 13.3372, 2)
wait 200
0936: set_camera 2493.0073 -1684.394 13.5095 position_to 2478.6345 -1677.7593 13.3396 time 12000 drop_mode 1
0920: point_camera 2486.0164 -1677.4105 13.3372 transverse_to 2480.2334 -1675.2882 13.3393 time 12000 mode 1 // перемещаем камеру во время ролика
05CB: AS_actor $PLAYER_ACTOR enter_car 3@ as_driver 20000 ms
05CA: AS_actor 1@ enter_car 3@ passenger_seat 0 20000 ms
05CA: AS_actor 2@ enter_car 3@ passenger_seat 1 20000 m

:SCENE_A
wait 0
if AND
actor.InCar($PLAYER_ACTOR, 3@)
actor.InCar(1@, 3@)
actor.InCar(2@, 3@)
jf @SCENE_A

:SCENE
wait 0
fade 0 1000
0701: end_scene_skip
wait 1000
0936: set_camera 2493.0073 -1684.394 13.5095 position_to 2478.6345 -1677.7593 13.3396 time 0 drop_mode 0
0920: point_camera 2486.0164 -1677.4105 13.3372 transverse_to 2480.2334 -1675.2882 13.3393 time 0 mode 0 // перемещам камеру в окончательную точку игновенно
if
not actor.InCar($PLAYER_ACTOR, 3@)
then
05CB: AS_actor $PLAYER_ACTOR enter_car 3@ as_driver 0 ms
end
if
not actor.InCar(1@, 3@)
then
05CA: AS_actor 1@ enter_car 3@ passenger_seat 0 0 ms
end
if
not actor.InCar(2@, 3@)
then
05CA: AS_actor 2@ enter_car 3@ passenger_seat 1 0 ms
end
0826: enable_hud 1
02A3: enable_widescreen 0
wait 2000
Camera.Restore_WithJumpCut
Camera.SetBehindPlayer
03E6: remove_text_box
00BE: text_clear_all 
fade 1 1000
wait 1000
player.CanMove($PLAYER_CHAR) = true
actor.SetImmunities($PLAYER_ACTOR, 0, 0, 0, 0, 0)
0A93: end_custom_thread

Вот это и есть одна из возможностей устранения глюка перемещения камеры.

Думаю, этот урок станет полезныи при создании ваших роликов. Следующий урок будет про миссии. А точнее мы будем учится делать "нервометры". С Вами был wmysterio.|1013|1|0|88031612png500300400240``\|66771219png500300400240``||propusk_videorolikov|1504427719

Last updated