Универсальный солдат (GTA SA) — различия между версиями
Материал из GTAModding.ru
Axel218 (обсуждение | вклад) |
Axel218 (обсуждение | вклад) |
||
Строка 2: | Строка 2: | ||
Данный скрипт добавляет в игру "универсальных солдат" - это секретный военный проект правительства США :) Они появляются недалеко от игрока и ведут по нему огонь, если у того 6 звёзд розыска. | Данный скрипт добавляет в игру "универсальных солдат" - это секретный военный проект правительства США :) Они появляются недалеко от игрока и ведут по нему огонь, если у того 6 звёзд розыска. | ||
− | Но это в игре. А на деле - это небольшой пример развития исскуственного | + | Но это в игре. А на деле - это небольшой пример развития исскуственного интеллекта [[Актёр|актёров]] скриптом. Конечно, это не идеально, но может послужить хорошим примером управления поведением актёров для скриптеров. |
Особенности скрипта: | Особенности скрипта: |
Версия 06:36, 21 января 2009
Автор: Axel218
Данный скрипт добавляет в игру "универсальных солдат" - это секретный военный проект правительства США :) Они появляются недалеко от игрока и ведут по нему огонь, если у того 6 звёзд розыска. Но это в игре. А на деле - это небольшой пример развития исскуственного интеллекта актёров скриптом. Конечно, это не идеально, но может послужить хорошим примером управления поведением актёров для скриптеров.
Особенности скрипта:
- Солдат может применять в разных ситуациях различные виды оружия
- Может уворачиваться от выстрелов (стрейфиться)
- Периодически забрасывает игрока гранатами :)
Код:
...
create_thread @Universal_Soldier_Thread
...
:Universal_Soldier_Thread
// Объявляем переменные для компилятора
var
7@ : Integer // Переменная для вычисления кувырка
30@ : Integer // Переменная для контроля таймера
end
:Universal_Soldier
wait 0 ms
// Проверяем уровень розыска игрока - равен ли он 6-ти звёздам?
01C0: 6@ = player $PLAYER_CHAR wanted_level
6@ == 6
jf @Universal_Soldier // Если уровень не равен 6-ти - проверяем ещё
// Получаем Handle случайного пешехода на улице
02DD: 1@ = get_random_ped_in_zone 'SAN_AND' with_pedtype_civilian 1 gang 0 criminal/prostitute 1
// Если Handle равен -1, значит он не получен - возможно, поблизости нет пешеходов
1@ <> -1
jf @Universal_Soldier // Пробуем ещё раз сначала
// Handle получен. Сохраняем координаты пешехода в переменные
00A0: store_actor 1@ position_to 2@ 3@ 4@
// Удаляем пешехода. Он был нужен нам только для получения точных координат
009B: destroy_actor 1@
01C2: remove_references_to_actor 1@
// Загружаем необходимые модели
0247: load_model #SWAT // Модель SWAT'овца - "забугорный спецназ"
0247: load_model #M4 // Модель M4
0247: load_model #SHOTGSPA // Модель боевого дробовика
0247: load_model #KNIFECUR // Модель ножа
0247: load_model #HEATSEEK // Модель ракетницы
0247: load_model #GRENADE // Модель гранаты
038B: load_requested_models
:Universal_Soldier_Check1
wait 0 ms
// Проверяем - загрузились ли модели?
if and
0248: model #SWAT available
0248: model #M4 available
0248: model #SHOTGSPA available
0248: model #KNIFECUR available
0248: model #HEATSEEK available
0248: model #GRENADE available
jf @Universal_Soldier_Check1 // Если не загрузились - проверяем ещё
// Создаём универсального солдата на координатах, полученых ранее
009A: 1@ = create_actor_pedtype 23 model #SWAT at 2@ 3@ 4@
// Устанавливаем ему много очков здоровья
0223: set_actor 1@ health_to 1500
// Столько же много брони
035F: actor 1@ armour += 1500
// Создаёи над ним маркер, чтобы его было видно на радаре. Так же это создаёт над ним
// стрелку. По умолчанию и маркер, и стрелка имеют красный цвет
0187: 5@ = create_marker_above_actor 1@
// Устанавливаем солдату иммунитет к выстрелам в голову (чтобы её не снесло при попадании)
0446: set_actor 1@ immune_to_headshots 0
// Даём ему оружие с бесконечным боезапасом
01B2: give_actor 1@ weapon 31 ammo -1 // M4
01B2: give_actor 1@ weapon 27 ammo -1 // Боевой дробовик
01B2: give_actor 1@ weapon 36 ammo -1 // Ракетница
01B2: give_actor 1@ weapon 4 ammo -1 // Нож
// После смерти солдата всё его оружие нельзя будет поднять (оно не появится)
087E: set_actor 1@ weapon_droppable 0
// Устанавливаем точность стрельбы
02E2: set_actor 1@ weapon_accuracy_to 95
// Уровень владения оружием - Hitman. От уровня зависит скорость стрельбы и передвижение
// во время стрельбы
081A: set_actor 1@ weapon_skill_to 2
// Модель поведения актёра. Например, при прицеливании актёр поднимает руки вверх,
// отскакивает от проезжающей рядом машины и так далее.
// Мы установим нулевой параметр, так как мы сами будем контролировать поведение.
060A: create_decision_maker_type 0 store_to 8@ // decision\allowed\m_.ped files
060B: set_actor 1@ decision_maker_to 8@
// Этот опкод устанавливает отношение актёра к определённому типу пешеходов.
// В нашем случае это ненависть (4) к игроку (0)
077A: set_actor 1@ acquaintance 4 to_actors_pedtype 0 // see ped.dat
// Заставляем солдата атаковать игрока
07A5: AS_actor 1@ attack_actor $PLAYER_ACTOR -1 ms
// Выгружаем ненужные модели из памяти. Модель гранаты остаётся в памяти!
0249: release_model #SWAT
0249: release_model #M4
0249: release_model #SHOTGSPA
0249: release_model #KNIFECUR
0249: release_model #HEATSEEK
:Universal_Soldier_AI // Цикл, управляющий поведением солдата
wait 0 ms
// Проверяем, если игрока не существует (его убили или т.п.) или если солдата убили
if or
8256: not player $PLAYER_CHAR defined
0118: actor 1@ dead
then // то
// Удаляем маркер над солдатом
0164: disable_marker 5@
// Удаляем информацию солдата из памяти игры
01C2: remove_references_to_actor 1@
// Удаляем модель поведения солдата
065C: release_decision_maker 8@
// Выгружаем модель гранаты
0249: release_model #GRENADE
// Ждём 10 секунд
wait 10000 ms
// Идём в самое начало скрипта
jump @Universal_Soldier
end
// Если игрок водит наземный или воздушный транспорт
if or
00DF: actor $PLAYER_ACTOR driving
04AB: actor $PLAYER_ACTOR driving_plane
then // то
// Меняем активное оружие солдата на ракетницу и заставляем его поджарить игрока :)
01B9: set_actor 1@ armed_weapon_to 36
07A5: AS_actor 1@ attack_actor $PLAYER_ACTOR -1 ms
else // иначе
// Записываем координаты солдата в переменные
00A0: store_actor 1@ position_to 2@ 3@ 4@
// Записываем координаты игрока в переменные
00A0: store_actor $PLAYER_ACTOR position_to 6@ 7@ 8@
// Получаем расстояние между солдатом и игроком
050A: 9@ = distance_between_XYZ 2@ 3@ 4@ and_XYZ 6@ 7@ 8@
// Если игрок находится более чем в 50-ти метрах от солдата
if 9@ >= 20.0
then // то
// Меняем активное оружие солдата на M4
01B9: set_actor 1@ armed_weapon_to 31
else // иначе
// Если игрок на средней дистанции от солдата
if and
9@ < 18.0
9@ > 12.0
then
// Проверим, может гранатку бросим? ;)
gosub @Universal_Soldier_Grenade_Check
end
// Если игрок находится близко к солдату
if 9@ < 2.5
then // то
// Меняем активное оружие солдата на нож
01B9: set_actor 1@ armed_weapon_to 4
else // иначе
// На средних дистанциях
// Меняем активное оружие солдата на боевой дробовик
01B9: set_actor 1@ armed_weapon_to 27
end
end
end
if and // если
0457: player $PLAYER_CHAR aiming_at_actor 1@ // Игрок целится в солдата
874F: not actor $PLAYER_ACTOR ped_event == 12 // Игрок не перезаряжается
82D8: not actor 1@ current_weapon == 4 // У солдата нет в руках ножа
02A0: actor 1@ stopped // Солдат стоит на месте
then // то
// Смысл следующей операции в том, что если игрок целится в солдата - тот делает
// кувырок в случайную сторону, а затем бычтрый выстрел. Получается весьма эффектно.
// Генерируем случайное число (0/1)
7@ = Random(-1, 1)
// Делаем на мнгновение солдата миролюбивым существом, чтобы он не натворил глупостей
077C: clear_actor 1@ default_action 4 to_all_actor_types
// Получаем угол игрока и отнимаем от него 180, затем устанавливаем полученный угол
// солдату, чтобы тот был повёрнут лицом к игроку
0172: 9@ = actor $PLAYER_ACTOR Z_angle
000F: 9@ -= 180.0
0173: set_actor 1@ Z_angle_to 9@
// Заставляем солдата сделать кувырок в случайную сторону (7@). 0 - влево, 1 - вправо
06E3: AS_actor 1@ roll_sideways 7@
// Ждём, пока солдат кувыркнётся
wait 1200 ms
// Делаем солдата вновь агрессивно настроеным к игроку :)
077A: set_actor 1@ default_action 4 to_actors_pedtype 0
// Заставляем солдата атаковать игрока
07A5: AS_actor 1@ attack_actor $PLAYER_ACTOR -1 ms
// Ждём пол-секунды, чтобы солдат не кувыркался со стороны в сторону как угорелый
wait 500
end
// Идём в начало цикла
jump @Universal_Soldier_AI
:Universal_Soldier_Grenade_Check
// Eсли таймер достиг нужного нам значения
if 002D: 32@ >= 30@
then // то
// Даём солдату одну гранату
01B2: give_actor 1@ weapon 16 ammo 1
// Поднимаем его. Сидя он не сможет кинуть гранату
04EB: AS_actor 1@ crouch 0
// Заставляем кинуть гранату
07A5: AS_actor 1@ attack_actor $PLAYER_ACTOR -1 ms
// Ждём, пока солдат не бросит гранату
while 02D8: actor 1@ current_weapon == 16
wait 0 ms
end
// Задаём случайное значение между 20-ю и 40-а секундами, чтобы сверять таймер
30@ = Random(20000, 40000)
// Обнуляем таймер
32@ = 0
end
return