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