Уроки моддинга
Основной раздел
Search
K
Links

Интересное в скриптинге

Всем привет! С Вами wmysterio, и это очередной и долгожданный урок по скриптингу GTA San Andreas. Как уже говорилось на форуме, я планирую сделать глобальную модификацию мейна, и я прошел игру заново, чтобы установить сюжет. Во время прохождения я захотел узнать как делаются некоторые вещи, и заглянул в оригинальный мейн.
Что же я нашел интересненького? Очень много любопытного. Например, узнал как сделать маркер в ввиде капельки:
title
У меня спрашивали очень много людей, и я наконец нашел ответ. Как оказалось, за это отвечает опкод:
075B: zoom_radar 0
Меня это слегка удивило, так как я, по-локиге, искал опкоды, связанные с маркерами, но как оказалось за маркеры ввиде капель отвечает радар. Чтобы достичь такого эффекта, нужно установить масштаб радара в число, отличное от нуля, например:
075B: zoom_radar 1
Удивительно, но это работает!
Cледующим шагом стало исследование исскуственно интелекта, вернее как достишь хорошего уровня интелекта за минимум строк кода. Для примера, возьмём урок и этот урок. В них речь шла о том, чтобы проигрывать анимацию последовательно, однако AS-паки используются не только для анимации, но и для других действий (я об этом знал, но в уроках не упомянул чего-то).
Что-бы заставить актёра патрулировать возле дома CJ, достаточно этого кода:
{$CLEO}
0615: define_AS_pack_begin 2@
05D3: AS_actor -1 goto_point 2500.376 -1685.9846 13.472 mode 4 time -1 ms
05D3: AS_actor -1 goto_point 2485.1157 -1686.6415 13.5085 mode 4 time -1 ms
0643: set_AS_pack 2@ loop 1
0616: define_AS_pack_end 2@
model.Load(#WMYDRUG)
038B: load_requested_models
0@ = Actor.Create(Mission2, #WMYDRUG, 2485.1157, -1686.6415, 12.5085)9.4457
0618: assign_actor 0@ to_AS_pack 2@
061B: remove_references_to_AS_pack 2@
Model.Destroy(#WMYDRUG)
0A93: end_custom_thread
Обратите внимание на опкод 0643. Он заставляет проигрывать содержимое экшн-пака с начала по окончанию действия. Здесь важно то, что этот опкод должен находится между началом и кончом AS-пака. В противном случае повторения не произойдёт. Такой подход отлично подойдёт для мейна, где можно с помощью глобальных переменных устанавливать разные маршруты движения, имея всего 4 строки кода. Это очень важно для оптимизации кода, и мы заставляем игру больше рабоать на нас, а не на оборот.
Ещё важный момент: это модели поведения (урок). От него зависит как будет реагировать актёр на внешние события. Если нужно сделать актёра дружелюбным, то отлично подойдёт такой скрипт:
{$CLEO}
model.Load(#WMYDRUG)
Model.Load(#TEC9)
038B: load_requested_models
07E5: copy_decision_maker 65542 to 3@
0@ = Actor.Create(Mission2, #WMYDRUG, 2485.1157, -1686.6415, 12.5085)
Actor.GiveWeaponAndAmmo(0@, 32, 5000)
060B: set_actor 0@ decision_maker_to 3@
0631: put_actor 0@ in_group $PLAYER_GROUP
Model.Destroy(#WMYDRUG)
Model.Destroy(#TEC9)
0A93: end_custom_thread
Эта модель поведения мне очень понравилась, так как актёр никак не реагируте на внешние факторы со стороны игрока. Одним словом Ван не нужно больше зрботиться о том, что ваш спутник вдруг начнёт у Вас стрелять или убегать куда-то от Вас.
title
Ещё одна новинка для меня и, надеюсь, для Вас - это как заставить актёра стрелять чаще и точнее. Я расскопал один опкод, который устанавливает частоту стрельбы с оружия:
07DD: set_actor 0@ attack_rate 50
Число 50 как раз таки и отвечает за частоту стрельбы. Насколько я понял, это значение указывается в процентах, но если поставить -1 или 100, то достигается максимум. Следущий скрипт сделает актёра машиной для убиства:
{$CLEO}
model.Load(#WMYDRUG)
Model.Load(#TEC9)
038B: load_requested_models
0@ = Actor.Create(Mission2, #WMYDRUG, 2485.1157, -1686.6415, 12.5085)
Actor.GiveWeaponAndAmmo(0@, 32, 5000)
02E2: set_actor 0@ weapon_accuracy_to -1
07DD: set_actor 0@ attack_rate -1
05E2: AS_actor 0@ kill_actor $PLAYER_ACTOR
Model.Destroy(#WMYDRUG)
Model.Destroy(#TEC9)
0A93: end_custom_thread
Если Вы начали играть в близи от дома CJ, то думаю вы ощутите как теперь стреляет этот дружок.
Далее рассмотрим ещё некоторые поведения актёров. Опкод:
0588: disable_actor 0@ validate_position 0
Заставляет актёра атаковать врага на месте. Полезно, когда стрелка нужно разместить где-то на крыше и не нужно чтобы он пытался с неё спрыгнуть. Актёр начинает атаку, когда игрок находится в его поле видимости.
Опкод:
0816: set_actor 0@ dont_chase_victim 1
Заставляет актёра не бегать за жетрвой а стрелять только когда она находится в радиусе действия его оружия. В отличии от предыдущего опкода, актёр может передвигаться по его усмотрению. Используя эти скрипты, можем сделать скрипт охранника, который будет атаковать CJ при обнаружении. Для этого в место опкода 07E5 используем более так сказать "зловещий" опкод 060A, а также установим отношение актёра к игроку на ненависть. Вот что у меня получилось:
{$CLEO}
0615: define_AS_pack_begin 2@
05D3: AS_actor -1 goto_point 2500.376 -1685.9846 13.472 mode 4 time -1 ms
05C9: AS_actor -1 on_guard 3000 ms
05D3: AS_actor -1 goto_point 2485.1157 -1686.6415 13.5085 mode 4 time -1 ms
05C9: AS_actor -1 on_guard 3000 ms
0643: set_AS_pack 2@ loop 1
0616: define_AS_pack_end 2@
060A: create_decision_maker_type 4 store_to 3@
model.Load(#WMYDRUG)
Model.Load(#TEC9)
038B: load_requested_models
0@ = Actor.Create(Mission2, #WMYDRUG, 2485.1157, -1686.6415, 12.5085)
Actor.Health(0@) = 1000
Actor.GiveWeaponAndAmmo(0@, 32, 5000)
077A: set_actor 0@ acquaintance 4 to_actors_pedtype 0 // see ped.dat
0350: set_actor 0@ maintain_position_when_attacked 1
02E2: set_actor 0@ weapon_accuracy_to -1
07DD: set_actor 0@ attack_rate -1
0618: assign_actor 0@ to_AS_pack 2@
061B: remove_references_to_AS_pack 2@
060B: set_actor 0@ decision_maker_to 3@
Model.Destroy(#WMYDRUG)
Model.Destroy(#TEC9)
0A93: end_custom_thread
Результат оправдал себя: противник атакует только когда увидит CJ, при этом соблюдаюстя все нормы, например охранник не видит CJ, если тот спрятался за за забором в двух милиметрах от него.
Следующая "вкусняшка" - опкод 0677. Он заставляет актёра идти к другому актёру, стать напротив него и общаться. Вот этот код:
{$CLEO}
wait 2000
model.Load(#WMYDRUG)
038B: load_requested_models
0@ = Actor.Create(Mission2, #WMYDRUG, 2480.7903, -1675.9349, 12.3378)
Model.Destroy(#WMYDRUG)
0677: AS_actor 0@ chat_with_actor $PLAYER_ACTOR lead_speaker_flag 1 unknown_flag 1
0677: AS_actor $PLAYER_ACTOR chat_with_actor 0@ lead_speaker_flag 0 unknown_flag 1
0A93: end_custom_thread
Стоит расмотреть детали параметров. Значение "lead_speaker_flag" указывает кто первым будет жестикулировать руками. Если поставить эти флаги одновременно в 1, то оба персонажа начнут махать руками. Если оба параметра установлены в 0, то ничего не произойдёт. Другой параметр пока неизвестный мне. Мои тесты показали, что если числа будут разными, то актёры подойдут, но никаких действий больше не подадут. Если оба параметра установлены в 0 или 1, то всё работает.
Я буду продолжать исследовать main, и как только найду что-то новенькое и интересное - сразу сообщу Вам. С Вами был wmysterio, пока!