Универсальный солдат (GTA SA)

Материал из GTAModding.ru
Перейти к: навигация, поиск

Данный скрипт добавляет в игру "универсальных солдат". Это секретный военный проект правительства США. Они появляются недалеко от игрока и ведут по нему огонь, если у того 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

Автор: Axel218

п · о · р
San Andreas Grand Theft Auto: San Andreas
Форматы файлов.col.cfg.cut.dff.dat.fxp.gxt.ide.ifp.img.ipl.rep.rrr.scm.txd.set
Документацияcarcols.datCarrecPed EventsPed TypeАдреса Памяти Функций (SA)Анимация моделей в SAВизуальные эффекты в скриптинге
Загруженные звукиКатсценыНомера оружияРисование на экранеТрюки с меткамиСтатистикаСтруктура аудио в SABeta версия
ИнструментыCLEOCollision File Editor IIENBSeriesG-ToolsGXT EditorIMG ToolPS2 TXD ModPS2 TXD ViewerLimit AdjusterMap EditorPathViewer
San Andreas Audio ToolkitSan Andreas Texture PlacerSanny BuilderTXD WorkshopTXDFuckerXBOX TXD PowerTool
ТуториалыРедактирование аудио в SAИзменение cutsceneDecision MakerПропуск роликовКонвертация автомобилей в SA
Основы маппинга GTA:SAДелаем ломающиеся объектыКонвертирование персонажа в SA2dfx в SanAndreasМоддинг San Andreas v2.0
Новая анимация персонажейУниверсальный солдат (GTA SA)
МодыAlien CityDesign Your Own MissionGTA: UnitedGTA StoriesGTA Berlin
МультиплеерgtaTournamentMulti Theft AutoSan Andreas Multiplayer