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

Всем привет! Давно не было уроков по скриптингу Санни Билдер, так как все известные моменты мы рассмотрели, я решил писать уже не уроки, а примеры полноценных миссий. Сегодня мы будем "хардкорить" в написании миссии, которую я назвал "Взрывчатка". Суть миссии в том, что к CJ обращается Свит и сообщает что его машину заминировали. Допустим, что Свит насколько привязан к этой тачки, что решает разминировать её. Нам необходимо привести сапёра, чтобы тот взялся за это нелёгкое дело. Как оказалось, что для этого дела понадобится неординарное решение - чтобы успешно разминировать её, нужно держать скорость автомобиля примерно на скорости 100 км/час. В противном случаи машину не разминировать. Думаю идея понятна.

Хочу добавить, что данная статья не для новичков, а для тех, что более-менее уже понимает чужой код и может дополнить его.

Давайте приступим к написанию кода. Миссию мы будем делать, используя CLEO. Я сочинил простейший стартер, который запустит нашу миссию.
Код
{$CLEO .cm}
thread 'BOMB'

gosub @BOMB_RUN
if
wasted_or_busted
jf @BOMB_FINISH
gosub @BOMB_FAILED

:BOMB_FINISH
$ONMISSION = 0
mission_cleanup
end_thread

:BOMB_RUN
increment_mission_attempts
$ONMISSION = 1
wait 1000
fade 1 1000

// Код миссии

gosub @BOMB_END
0394: play_music 1
01E3: show_text_1number_styled GXT 'M_PASS' number 5000 time 5000 style 1
Player.Money(0) += 5000
return

:BOMB_FAILED
gosub @BOMB_END
00BA: show_text_styled GXT 'M_FAIL' time 5000 style 1  
return

:BOMB_END
return

А необходимую конструкцию миссии я привёл к такому виду:
Код
{$CLEO .cm}
thread 'BOMB'

gosub @BOMB_RUN
if
wasted_or_busted
jf @BOMB_FINISH
gosub @BOMB_FAILED

:BOMB_FINISH
$ONMISSION = 0
mission_cleanup
end_thread

:BOMB_RUN
increment_mission_attempts
$ONMISSION = 1
wait 1000
fade 1 1000

// Код миссии

gosub @BOMB_END
0394: play_music 1
01E3: show_text_1number_styled GXT 'M_PASS' number 5000 time 5000 style 1
Player.Money(0) += 5000
return

:BOMB_FAILED
gosub @BOMB_END
00BA: show_text_styled GXT 'M_FAIL' time 5000 style 1  
return

:BOMB_END
return
Приступаем к написанию последовательности скрипта. Прежде всего очищаем местность от хлама сего и рендерим местность для камеры, убрав трафик пешеходов и автомобилей. Создаём неподалёку тачку Свита и садовим его в транспорт. Перемещаем СЖ к нему:
Код
03DE: set_pedestrians_density_multiplier_to 0.0
01EB: set_traffic_density_multiplier_to 0.0
00C0: set_current_time 4 0
0395: clear_area 0 at 2514.7581 -1670.5378 12.5749 radius 3.0
04E4: refresh_game_renderer_at 2514.7581 -1670.5378
023C: load_special_actor 'SWEET' as 1
model.Load(#GREENWOO)
038B: load_requested_models

repeat
wait 0
until 023D: special_actor 1 loaded

0@ = Car.Create(#GREENWOO, 2517.1985, -1665.6057, 12.7179)
Car.Angle(0@) = 96.3102
0229: set_car 0@ primary_color_to 0 secondary_color_to 1
01C8: 1@ = create_actor_pedtype 23 model #SPECIAL01 in_car 0@ passenger_seat 0
077A: set_actor 1@ acquaintance 0 to_actors_pedtype 0
0296: unload_special_actor 1
Model.Destroy(#GREENWOO)
Actor.PutAt($PLAYER_ACTOR, 2516.5964, -1663.8156, 12.8959)
Actor.Angle($PLAYER_ACTOR) = 203.1531
Ставим нашим героям иммунитеты и устанавливаем камеру для видеоролика. Дальше пишем код пропуска этого видеоролика:
Код
Car.SetImmunities(0@, 1, 1, 1, 1, 1)
Actor.SetImmunities(1@, 1, 1, 1, 1, 1)
015F: set_camera_position 2513.7539 -1666.6892 14.5696 rotation 0.0 0.0 0.0
0160: set_camera_point_at 2516.5203 -1664.2532 13.8745 switchstyle 2
wait 1000
00BE: text_clear_all
03E6: remove_text_box
0826: enable_hud 0
0581: enable_radar 0
02A3: enable_widescreen 1
05BF: AS_actor 1@ look_at_actor $PLAYER_ACTOR 20000 ms
05BF: AS_actor $PLAYER_ACTOR look_at_actor 1@ 20000 ms
fade 1 1000
0707: start_scene_skip_to @BOMB_END_SCENE_1
wait 1000
// Диалог

:BOMB_END_SCENE_1
fade 0 1000
0701: end_scene_skip
wait 1000
Используется анимация PED, актёры смотрят друг на друга и шевелят губами. По окончанию диалога, как и при нажатии клавиши "Пробел" идёт затемнение экрана, СЖ перемещается в транспорт, за руль. Камера сбрасывается в обычный режим.

Далее, по-сюжету, мы должны приехать к сапёру, и подобрать его. Организуем простой цикл, в котором нельзя ехать больше 100 км/час. В нём же не допустим смерти тачки и Свита:
Код
Player.CanMove(0, 1)
Actor.SetImmunities($PLAYER_ACTOR, 0, 0, 0, 0, 0)
Car.SetImmunities(0@, 0, 0, 0, 0, 0)
Actor.SetImmunities(1@, 0, 0, 0, 0, 0)
2@ = 99
5@ = 0

while 5@ == 0
wait 0
  if or
  0741: actor $PLAYER_ACTOR busted
  Actor.Dead($PLAYER_ACTOR)
  then
  5@ = -3
  continue
  end  
  if or
  02BF: car 0@ sunk
  car.Wrecked(0@)
  then
  5@ = -1
  continue
  end  
  if
  Actor.Dead(1@)
  then
  5@ = -2
  continue
  end  
  02E3: 10@ = car 0@ speed
  10@ *= 4.2
  if
  10@ > 99.0
  then
  then
  5@ = -4
  continue
  end
  if and
  not 2@ == 1
  Actor.InCar($PLAYER_ACTOR, 0@)
  Actor.InCar(1@, 0@)
  then
  Marker.Disable(6@)
  Marker.Disable(7@)
  018A: 3@ = create_checkpoint_at 2336.2732 -1679.54 12.2143
  03BC: 4@ = create_sphere_at 2336.2732 -1679.54 12.2143 radius 2.0
  0AD1: show_formatted_text_highpriority "O¦£pa¢ž¬¦ec© k ~y~ca£epy~w~!" time 3000
  2@ = 1
  continue
  end  
  if or
  not Actor.InCar($PLAYER_ACTOR, 0@)
  not Actor.InCar(1@, 0@)
  then
  if
  2@ == 1
  then
  Marker.Disable(3@)
  03BD: destroy_sphere 4@
  6@ = Marker.CreateAboveActor(1@)
  7@ = Marker.CreateAboveCar(0@)
  0AD1: show_formatted_text_highpriority "Cašœ¦ec© ¢ ~b~¯a¥œ®y~w~!" time 3000
  2@ = 2
  continue
  end
  end  
  if AND
  2@ == 1
  00EC: actor $PLAYER_ACTOR sphere 0 near_point 2336.2732 -1679.54 radius 2.0 2.0
  then
  5@ = 1
  end
end

Marker.Disable(3@)
03BD: destroy_sphere 4@
Marker.Disable(6@)
Marker.Disable(7@)
if
5@ == -1
then
jump @BOMB_FINISH_SWEET_DEAD
end
if
5@ == -2
then
jump @BOMB_FINISH_CAR_DEAD
end
if
5@ == -3
then
jump @BOMB_FAILED
end
if
5@ == -4
then
jump @BOMB_SPEED
end

Player.CanMove(0, 0)
Actor.SetImmunities($PLAYER_ACTOR, 1, 1, 1, 1, 1)
Car.SetImmunities(0@, 1, 1, 1, 1, 1)
Actor.SetImmunities(1@, 1, 1, 1, 1, 1)
fade 0 1000
wait 1000
// Следующая мини-сцена

{ блоки провала }

:BOMB_FINISH_SWEET_DEAD
gosub @BOMB_END
00BA: show_text_styled GXT 'M_FAIL' time 5000 style 1
0AD1: show_formatted_text_highpriority "Cўњ¦ yЇep!" time 3000
return

:BOMB_FINISH_CAR_DEAD
gosub @BOMB_END
00BA: show_text_styled GXT 'M_FAIL' time 5000 style 1
0AD1: show_formatted_text_highpriority "–aҐњ®a y®њ¤¦o›e®a!" time 3000
return

:BOMB_SPEED
gosub @BOMB_END
00BA: show_text_styled GXT 'M_FAIL' time 5000 style 1
0AD1: show_formatted_text_highpriority "‹Ё ЈpeўЁcњћњ ckopoc¦©!" time 3000
return
Дальше нужно организовать цикл, в котором будут условия обезвреживания бомбы. Как сказал в диалогах сапёр, нужно проверить на открытия двери, чтобы взорвать транспорт. Это можно осуществить путём проверки к-ва занятых мест. Если такое число превышает 0, то это значит, что кто-то покинул траспорт, тем самым открыв дверь. Цикл будел разделён на три этапа:
1) Когда игрок не набрал 100 км/час
2) Когда уже набрал такую скорость, включается таймер
3) Ожидание времени. Для полного хардкора включим трафик, чтобы игрок попотел :)
Код
5@ = 0
3@ = 1 // etap
02E3: $CAR_SPEED = car 0@ speed
008C: $CAR_SPEED = float $CAR_SPEED to_integer
04F7: status_text $CAR_SPEED type 0 line 1 GXT 'DEF0' // global_variable // Score
$TIMER = 60000

while 5@ == 0
wait 0
  if or
  02BF: car 0@ sunk
  car.Wrecked(0@)
  then
  5@ = -1
  continue
  end
  if
  Actor.Dead(1@)
  then
  5@ = -2
  continue
  end  
  if
  Actor.Dead(11@)
  then
  5@ = -3
  continue
  end  
   
  01E9: 10@ = car 0@ num_passengers
  046C: 12@ = car 0@ driver

  if OR
  87D6: not 12@ == $PLAYER_ACTOR // @ == $ (int)
  not 10@ == 2
  then
  020B: explode_car 0@
  continue
  end
   
  02E3: $CAR_SPEED = car 0@ speed
  $CAR_SPEED *= 3.2  
  008C: $CAR_SPEED = float $CAR_SPEED to_integer
   
  if AND
  3@ == 1
  $CAR_SPEED > 100
  then
  3@ = 2
  continue
  end
   
  if
  3@ == 2
  then  
  03C3: set_timer_to $TIMER type 1 GXT 'DEF1' // global_variable // Time
  3@ = 3
  end
   
  if AND
  3@ == 3
  Actor.InCar($PLAYER_ACTOR, 0@)
  100 > $CAR_SPEED
  then
  020B: explode_car 0@
  continue
  end
   
  if AND
  3@ == 3
  Actor.InCar($PLAYER_ACTOR, 0@)
  $TIMER == 0
  then
  5@ = 1
  end  
end

014F: stop_timer $TIMER
0151: remove_status_text $CAR_SPEED
if
5@ == -1
then
jump @BOMB_FINISH_CAR_DEAD
end
if
5@ == -2
then
jump @BOMB_FINISH_SWEET_DEAD
end
if
5@ == -3
then
jump @BOMB_FINISH_SAP_DEAD
end
Нам осталось только написать код, который выгружает из памяти все ненужные объекты:
Код
:BOMB_END
if
056D: actor 1@ defined
then
Actor.RemoveReferences(1@)
Actor.DestroyInstantly(1@)
end
if
056D: actor 11@ defined
then
Actor.RemoveReferences(11@)
Actor.DestroyInstantly(11@)
end
if
056E: car 0@ defined
then
Car.RemoveReferences(0@)
  if
  not Actor.InCar($PLAYER_ACTOR, 0@)
  then
  Car.Destroy(0@)
  end
end
return
Результат нашей миссии:




Вам задание: Дописать миссию до логического завершения - нужно приехать к дому Свита. На этом урок окончен. С Вами был wmysterio, всего доброго!

P.S Исходники вы можете скачать здесь. Улучшайте миссию на свой вкус.

SanKing   (26.02.14 21:41)
Мощненько...

Yurko_UA   (27.02.14 00:40)
Був би дуже вдячний за уроки з прикладами по використанню: scm функцій та циклу repeat, бо я якось не дуже засвоїв цей матеріал.

wmysterio   (27.02.14 01:50)
По scm-фунціям вже 2 урока додано. Не бачу сенсу ще 3-й кидати. В наступних уроках попробую ще затронути цю тему більш обширно, на прикладі місії.

Про repeat мало що можна додати. Якщо ти розібрався з while, то repeat діє так же само. Різниця тільки в умові циклу. В ріпіті цикл буде завершено, якщо умова виконається, а вайл навпаки, якщо не виконається.
Вход на сайт

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

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

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