Здесь будут публиковаться уроки по скриптингу, написанные лично мной. Надеюсь, что эти уроки помогут Вам быстрее научиться делать свои скрипты. Удачи!
Уважаемые посетители! Я уже давно создал плейлист Sanny Builder: Мои примеры, где можно увидеть мои примеры скриптов с полным разбором кода.
Вот и команда для создания актера:
Actor.create(1@,4,#ARMY,X,Y,Z)
1@ - это переменная актера, с помощью которой им можно манипулировать.
4 - тип актера (коп, мужчина, бандит и т.д.)
#ARMY - имя загруженной нами модели
X, Y, Z - координаты (ТОЛЬКО ДРОБНЫЕ)
Вот мы и создали актера, теперь надо что-нибудь с ним сделать, например, увеличить здоровье.
Это делается вот этой командой
Actor.health(1@) = 350
1@ - переменная актера, которого мы создали
350 - количество здоровья (не может быть дробным числом!)
Теперь дадим ему броню
Actor.armour(1@) = 200
1@ - переменная актера
200 - количество боони (тоже не дробное!)
Теперь повернем его
Actor.angle(1@) = 90.0
1@ - переменная актера
90.0 - угол в градусах (ТОЛЬКО ДРОБНЫЙ)
И напоследок дадим ему оружие. Перед этим модель оружия необходимо загрузить.
01B2: give_actor 1@ weapon 18 ammo 250
1@ - переменная актера
18 - номер оружия (это револьвер из ВС)
250 - количество патронов к оружию.
Чтобы сделать актера простым пешеходом и убрать о нем сведения, используйте вот эту команду
actor.RemoveReferences(1@)
1@ - переменная актера
Смотрите пример и разбирайтесь. Пример для VC, но, если выбрать другую модель оружия, то и для SA подойдет.
:MyScript01 //начало
wait 0 // чтобы не вылетело ждем 0 миллисекунд
model.load(#ARMY) // объявляем модель актера
model.load(#PYTHON) // объявляем модель оружия
038B: load_requested_models // загружаем объявленные модели
:MyScript02 // вторая метка
wait 0 // чтоб не вылетало
if and // проверка нескольких условий
model.Available(#ARMY) // проверка на загруженность модели
model.Available(#PYTHON) // проверка на загруженность модели
jf @MyScript02
wait 10 //ждем 10 миллисекунд
// ну а дальше все уже понятно...
actor.create(1@,6,#ARMY,-1200.1,550.5,12.3)
actor.health(1@) = 150
actor.armour(1@) = 200
actor.angle(1@) = 270.0
01B2: give_actor 1@ weapon 18 ammo 250
wait 1500
actor.RemoveReferences(1@) //удаляем из памяти сведения об актере
model.destroy(#ARMY) // выгружаем модели
model.destroy(#PYTHON)
end_thread // завершаем скрипт
car.Create(1@,#ADMIRAL,X,Y,Z)
1@ - переменная авто. нужна для разных действий
#ADMIRAL - модель авто. перед созданием, нужно загрузить модель командой model.load(#модель)
X,Y,Z - координаты
Вот, машина создана, теперь посмотрим, что можно с ней делать.
Чтобы задать машине определенную скорость, используйте эту команду:
car.SetSpeedInstantly(1@,100.0)
1@ - переменная машины
100.0 - скорость (мили/час) (только дробное число) car.Health(1@) = 1000
Здоровье машины.
1000 - кол-во здоровья (1000 - обычное здоровье машины)
Можно переместить авто в определенное место
car.PutAt(1@,X,Y,Z)
1@ - все та же переменная машины
X,Y,Z - координаты, в которые мы перемещаем машину
Еще машине можно поставить защиту от чего-либо
car.SetImmunities(1@,1,1,1,1,1)
1@ - переменная авто
"тут первая цифра - защита от пуль, вторая - от огня, третья - от взрывов, четвертая - от оружия ближнего боя,пятая от столкновений." (цитата из справки SB)
car.ToggleHydraulics(1@,1)
Этой командой на машину ставится гидравлика (как у лоурайдеров)
1@ - переменная авто
1 - параметр. 1 - вкл. 2 - выкл.
car.destroy(1@)
уничтожает машину
car.RemoveReferences(1@)
убирает сведения о машине. машина теперь исчезнет, если игрок находится далеко от нее
Перейдем к проверкам:
car.Wrecked(1@)
Проверяет уничтожена ли машина с переменной 1@
car.HasHydraulics(1@)
Если ли у машины гидравлика
Пример создания машины:
:Car //начинаем скрипт
wait 0 //ждем 0 мс, чтобы не вылетело
model.load(#ADMIRAL) //объявляем модель
038B: load_requested_models //загружаем объявленную модель
:Car_2 //вторая часть скрипта
wait 0 //ждем, чтобы не вылетело
if //одиночное условие
model. Available(#ADMIRAL) //загружена ли модель?
jf @Car_2 //если нет, идем на начало
car.create(1@,#ADMIRAL,2488.56,-1667.84,13.38) //само создание машины
car.removereferences(1@) //удаляем сведения о машине из памяти, чтобы не нагружать игру
model.destroy(#ADMIRAL) //удаляем модель из памяти, чтобы не нагружать игру
end_thread //завершаем скрипт
:Cicl
wait 0
if and
not actor.Dead($PLAYER_ACTOR)
not actor.Driving($PLAYER_ACTOR)
0AB0: key_pressed 0xD //проверки на то, что игрок жив, не в авто, и на нажатие клавиши "Enter"
jf @Cicl
actor.StorePos($PLAYER_ACTOR,2@,3@,4@) //сохраняем текущие координаты игрока в переменные
02CE: 4@ = ground_z_at 2@ 3@ 4@ //получаем координату поверхности, чтобы действие не происходило в воздухе
//начало самого таймера, то есть простого цикла, известного многим по школьному курсу программирования (в Turbo Pascal)
for 1@ = 15 downto 0 //берем downto, чтобы счет шел от большего к меньшему
01E5: show_text_1number_highpriority GXT 'VAR' number 1@ time 1000 flag 1 //выводим значение переменной (секунды), которая в цикле изменяется с 15 до 0
if //начало условия. эта часть необязательна, она нужна для звука, который будет проигрываться, когда время будет меньше 5 секунд
1@ <= 5 //если значение времени таймера меньше или равно 5, то...
then
018C: play_sound 1084 at 0.0 0.0 0.0 //...проигрываем звук №1084
end //конец условия. else не нужно в данном случае
wait 1000 //ждем 1 секунду, иначе таймер закончится сразу же, да и таймер в секундах
end //конец цикла, это и конец таймера
020C: create_explosion_with_radius 10 at 2@ 3@ 4@ //создаем два больших взрыва
020C: create_explosion_with_radius 6 at 2@ 3@ 4@
wait 750 //ждем 750 мс, чтобы игрок не сразу мог перезапустить скрипт
jump @Cicl //идем на начало
Суть скрипта в том, что спустя 15 секунд после нажатия Enter произойдет взрыв (в той точке, в которой игрок нажал клавишу). Как видите, сам код прост и мал по размеру. К тому же есть еще плюсы:
-Не нужно проверять, что время таймера равно нулю, цикл сам завершается
-Можно легко и быстро настроить абсолютно все: время, звук таймера, и при каких значениях он будет воспроизведен, текст.
Помимо того, что можно выводить разные варианты текста (как по стилям написания, так и по цвету, например, сделать текст красным, когда значение таймера меньше 5 секунд), Вы сможете вывести текст как текст-бокс (серый прямоугольник в верхнем левом углу экрана, примером будет сообщение о том, как сменить оружие на другое). Для этого понадобится команда 0513, только не забудьте применить команду 03E6 после цикла, чтобы текст-бокс не держался на экране все время и исчез (сам он не исчезает).
Единственная проблема состоит в том, что выводятся именно секунды,а не минуты, но это, конечно, можно исправить, немного поломав голову.
В целом можно сказать, что такой таймер гораздо проще создается, его можно изменить по своему желанию, так что, если Вам понравился этот способ, дерзайте, у Вас все получится, если подключить фантазию. Можно сделать разноцветный текст, "музыкальный" таймер (звук на каждой секунде) и т.д.
1) Создайте текстовой файл (.txt) в CLEO_TEXT и поменяйте его расширение на .fxt. Имя файла должно быть английским
2) Теперь заполняйте файл текстом. Выглядит это так:
ИМЯ СТРОКИ<пробел>Текст
Имя строки должно быть написано большими английскими буквами, а также кол-во символов не должно превышать 7
Пример:
TEXT1 Take the car and drive to San Fierro!
Текст может быть и на русском, но для этого понадобится специальная программа, переводящая русские буквы в символы. Без подобной программы русский текст не будет отображаться.
Имя строки нужно писать в опкодах, чтобы игра отображала именно Ваш текст.
Пример:
03E5: show_text_box ‘TEXT1’
Мы указали имя той строки, которую мы хотим вывести. Строк может быть больше одной. Пример:
TEXT2 Now park the car near the house.
TEXT3 Exit the car and then blow it up.
Итак, мы научились правильно использовать одну из лучших возможностей CLEO!
Итак, спустя долгое время я решил опубликовать здесь ещё одну статью. На сей раз речь пойдёт о заданиях Rampage (которые ещё называются Kill Frenzy). Это задание состоит в убийстве определённых или всех подряд людей, иногда в уничтожении транспорта. При этом игроку дают определённый вид оружия, которое имеет бесконечный боезапас. По стандарту в SA отсутствует это задание, так как я, просматривая в Sanny Builder код main.scm, не нашёл тех опкодов, которые относятся к данному заданию. У меня появилась идея вернуть утерянное наследие прошлых GTA и сделать это в виде отдельной миссии. Итак, вот код:
Уважаемые посетители! Я уже давно создал плейлист Sanny Builder: Мои примеры, где можно увидеть мои примеры скриптов с полным разбором кода.
- Урок №1: Создание актеров
Вот и команда для создания актера:
Actor.create(1@,4,#ARMY,X,Y,Z)
1@ - это переменная актера, с помощью которой им можно манипулировать.
4 - тип актера (коп, мужчина, бандит и т.д.)
#ARMY - имя загруженной нами модели
X, Y, Z - координаты (ТОЛЬКО ДРОБНЫЕ)
Вот мы и создали актера, теперь надо что-нибудь с ним сделать, например, увеличить здоровье.
Это делается вот этой командой
Actor.health(1@) = 350
1@ - переменная актера, которого мы создали
350 - количество здоровья (не может быть дробным числом!)
Теперь дадим ему броню
Actor.armour(1@) = 200
1@ - переменная актера
200 - количество боони (тоже не дробное!)
Теперь повернем его
Actor.angle(1@) = 90.0
1@ - переменная актера
90.0 - угол в градусах (ТОЛЬКО ДРОБНЫЙ)
И напоследок дадим ему оружие. Перед этим модель оружия необходимо загрузить.
01B2: give_actor 1@ weapon 18 ammo 250
1@ - переменная актера
18 - номер оружия (это револьвер из ВС)
250 - количество патронов к оружию.
Чтобы сделать актера простым пешеходом и убрать о нем сведения, используйте вот эту команду
actor.RemoveReferences(1@)
1@ - переменная актера
Смотрите пример и разбирайтесь. Пример для VC, но, если выбрать другую модель оружия, то и для SA подойдет.
:MyScript01 //начало
wait 0 // чтобы не вылетело ждем 0 миллисекунд
model.load(#ARMY) // объявляем модель актера
model.load(#PYTHON) // объявляем модель оружия
038B: load_requested_models // загружаем объявленные модели
:MyScript02 // вторая метка
wait 0 // чтоб не вылетало
if and // проверка нескольких условий
model.Available(#ARMY) // проверка на загруженность модели
model.Available(#PYTHON) // проверка на загруженность модели
jf @MyScript02
wait 10 //ждем 10 миллисекунд
// ну а дальше все уже понятно...
actor.create(1@,6,#ARMY,-1200.1,550.5,12.3)
actor.health(1@) = 150
actor.armour(1@) = 200
actor.angle(1@) = 270.0
01B2: give_actor 1@ weapon 18 ammo 250
wait 1500
actor.RemoveReferences(1@) //удаляем из памяти сведения об актере
model.destroy(#ARMY) // выгружаем модели
model.destroy(#PYTHON)
end_thread // завершаем скрипт
- Урок №2: Создание транспорта
car.Create(1@,#ADMIRAL,X,Y,Z)
1@ - переменная авто. нужна для разных действий
#ADMIRAL - модель авто. перед созданием, нужно загрузить модель командой model.load(#модель)
X,Y,Z - координаты
Вот, машина создана, теперь посмотрим, что можно с ней делать.
Чтобы задать машине определенную скорость, используйте эту команду:
car.SetSpeedInstantly(1@,100.0)
1@ - переменная машины
100.0 - скорость (мили/час) (только дробное число) car.Health(1@) = 1000
Здоровье машины.
1000 - кол-во здоровья (1000 - обычное здоровье машины)
Можно переместить авто в определенное место
car.PutAt(1@,X,Y,Z)
1@ - все та же переменная машины
X,Y,Z - координаты, в которые мы перемещаем машину
Еще машине можно поставить защиту от чего-либо
car.SetImmunities(1@,1,1,1,1,1)
1@ - переменная авто
"тут первая цифра - защита от пуль, вторая - от огня, третья - от взрывов, четвертая - от оружия ближнего боя,пятая от столкновений." (цитата из справки SB)
car.ToggleHydraulics(1@,1)
Этой командой на машину ставится гидравлика (как у лоурайдеров)
1@ - переменная авто
1 - параметр. 1 - вкл. 2 - выкл.
car.destroy(1@)
уничтожает машину
car.RemoveReferences(1@)
убирает сведения о машине. машина теперь исчезнет, если игрок находится далеко от нее
Перейдем к проверкам:
car.Wrecked(1@)
Проверяет уничтожена ли машина с переменной 1@
car.HasHydraulics(1@)
Если ли у машины гидравлика
Пример создания машины:
:Car //начинаем скрипт
wait 0 //ждем 0 мс, чтобы не вылетело
model.load(#ADMIRAL) //объявляем модель
038B: load_requested_models //загружаем объявленную модель
:Car_2 //вторая часть скрипта
wait 0 //ждем, чтобы не вылетело
if //одиночное условие
model. Available(#ADMIRAL) //загружена ли модель?
jf @Car_2 //если нет, идем на начало
car.create(1@,#ADMIRAL,2488.56,-1667.84,13.38) //само создание машины
car.removereferences(1@) //удаляем сведения о машине из памяти, чтобы не нагружать игру
model.destroy(#ADMIRAL) //удаляем модель из памяти, чтобы не нагружать игру
end_thread //завершаем скрипт
- Урок №3: Самодельный таймер
:Cicl
wait 0
if and
not actor.Dead($PLAYER_ACTOR)
not actor.Driving($PLAYER_ACTOR)
0AB0: key_pressed 0xD //проверки на то, что игрок жив, не в авто, и на нажатие клавиши "Enter"
jf @Cicl
actor.StorePos($PLAYER_ACTOR,2@,3@,4@) //сохраняем текущие координаты игрока в переменные
02CE: 4@ = ground_z_at 2@ 3@ 4@ //получаем координату поверхности, чтобы действие не происходило в воздухе
//начало самого таймера, то есть простого цикла, известного многим по школьному курсу программирования (в Turbo Pascal)
for 1@ = 15 downto 0 //берем downto, чтобы счет шел от большего к меньшему
01E5: show_text_1number_highpriority GXT 'VAR' number 1@ time 1000 flag 1 //выводим значение переменной (секунды), которая в цикле изменяется с 15 до 0
if //начало условия. эта часть необязательна, она нужна для звука, который будет проигрываться, когда время будет меньше 5 секунд
1@ <= 5 //если значение времени таймера меньше или равно 5, то...
then
018C: play_sound 1084 at 0.0 0.0 0.0 //...проигрываем звук №1084
end //конец условия. else не нужно в данном случае
wait 1000 //ждем 1 секунду, иначе таймер закончится сразу же, да и таймер в секундах
end //конец цикла, это и конец таймера
020C: create_explosion_with_radius 10 at 2@ 3@ 4@ //создаем два больших взрыва
020C: create_explosion_with_radius 6 at 2@ 3@ 4@
wait 750 //ждем 750 мс, чтобы игрок не сразу мог перезапустить скрипт
jump @Cicl //идем на начало
Суть скрипта в том, что спустя 15 секунд после нажатия Enter произойдет взрыв (в той точке, в которой игрок нажал клавишу). Как видите, сам код прост и мал по размеру. К тому же есть еще плюсы:
-Не нужно проверять, что время таймера равно нулю, цикл сам завершается
-Можно легко и быстро настроить абсолютно все: время, звук таймера, и при каких значениях он будет воспроизведен, текст.
Помимо того, что можно выводить разные варианты текста (как по стилям написания, так и по цвету, например, сделать текст красным, когда значение таймера меньше 5 секунд), Вы сможете вывести текст как текст-бокс (серый прямоугольник в верхнем левом углу экрана, примером будет сообщение о том, как сменить оружие на другое). Для этого понадобится команда 0513, только не забудьте применить команду 03E6 после цикла, чтобы текст-бокс не держался на экране все время и исчез (сам он не исчезает).
Единственная проблема состоит в том, что выводятся именно секунды,а не минуты, но это, конечно, можно исправить, немного поломав голову.
В целом можно сказать, что такой таймер гораздо проще создается, его можно изменить по своему желанию, так что, если Вам понравился этот способ, дерзайте, у Вас все получится, если подключить фантазию. Можно сделать разноцветный текст, "музыкальный" таймер (звук на каждой секунде) и т.д.
- Урок №4: Создание .fxt файлов
1) Создайте текстовой файл (.txt) в CLEO_TEXT и поменяйте его расширение на .fxt. Имя файла должно быть английским
2) Теперь заполняйте файл текстом. Выглядит это так:
ИМЯ СТРОКИ<пробел>Текст
Имя строки должно быть написано большими английскими буквами, а также кол-во символов не должно превышать 7
Пример:
TEXT1 Take the car and drive to San Fierro!
Текст может быть и на русском, но для этого понадобится специальная программа, переводящая русские буквы в символы. Без подобной программы русский текст не будет отображаться.
Имя строки нужно писать в опкодах, чтобы игра отображала именно Ваш текст.
Пример:
03E5: show_text_box ‘TEXT1’
Мы указали имя той строки, которую мы хотим вывести. Строк может быть больше одной. Пример:
TEXT2 Now park the car near the house.
TEXT3 Exit the car and then blow it up.
Итак, мы научились правильно использовать одну из лучших возможностей CLEO!
- Урок №5 - Миссия "Ярость" (Rampage)
Итак, спустя долгое время я решил опубликовать здесь ещё одну статью. На сей раз речь пойдёт о заданиях Rampage (которые ещё называются Kill Frenzy). Это задание состоит в убийстве определённых или всех подряд людей, иногда в уничтожении транспорта. При этом игроку дают определённый вид оружия, которое имеет бесконечный боезапас. По стандарту в SA отсутствует это задание, так как я, просматривая в Sanny Builder код main.scm, не нашёл тех опкодов, которые относятся к данному заданию. У меня появилась идея вернуть утерянное наследие прошлых GTA и сделать это в виде отдельной миссии. Итак, вот код:
:Rampage
$ONMISSION
= 1
while true
gosub
@Rampage2
if
wasted_or_busted
then
00BA: show_text_styled GXT "RPFL"
time 1000 style 1
break
else
if
0@ == 2
then
player.Money(0) += 100000
00BA: show_text_styled GXT
"RPCP" time 1000 style 1
break
else
00BA: show_text_styled GXT
"RPFL" time 1000 style 1
break
end
end
end
0110:
clear_player 0 wanted_level
mission_cleanup
$ONMISSION
= 0
end_thread
:Rampage2
increment_mission_attempts
player.WantedLevel(0)
= 3
model.Load(#MINIGUN)
038B:
load_requested_models
01F9:
init_rampage_gxt 'RAMPAGE' weapon 38 time_limit 130000 targets 100
target_models -1 -1 -1 -1 completed_text 0
model.Destroy(#MINIGUN)
while true
wait 0
01FA: 0@ =
rampage_status
if or
0@ == 2
0@ == 3
then
break
end
end
return
Рассмотрим всё по
порядку.
Во-первых, всё это - миссия. Шаблон я немного переделал под
цикл while true, который достаточно хорошо упрощает работу и к тому же может
быть использовать для cleo миссии.
Во-вторых, игроку дают миниган и три звезды розыска, чтобы
было больше возможности пройти миссию.
В-третьих, использовано два опкода, касающихся Rampage.
В-четвёртых, игра сама создаёт таймер и счётчик убийств, Вам
остаётся лишь настроить параметры.
Что ж, давайте разберём опкоды:
01F9:
init_rampage_gxt 'RAMPAGE' weapon 38 time_limit 130000 targets 100
target_models -1 -1 -1 -1 completed_text 0
- 'RAMPGAE' - текст, который будет выведен в начале задания
- 38 - номер оружия, с которым игроку предстоит сражаться
- 130000 - количество времени в миллисекундах
- 100 - число "жертв" Вашего буйства
- -1 -1 -1 -1 - имена или номера (ID) моделей людей и машин, которые засчитываются за одно убийство (-1 - любой человек, -2 - любой транспорт)
- 0 - выводить ли текст завершения задания (1 - да, 0 - нет)
С текстом в данном опкоде есть некоторые проблемы:
неизвестно, с чем это связано, но текст здесь выводится дважды. В связи с этим
я поставил последний параметр на 0 и взял стандартный текст 'RAMPAGE', который,
к счастью, не выводится, так что можно теперь использовать свой текст.
И ещё один опкод по этой теме:
01FA: 0@ = rampage_status
Записывает в 0@ состояние задания. Экспериментально, а также
с помощью исследований на других сайтах я установил, что:
- 1 - задание в процессе выполнения
- 2 - успешное выполнение "Ярости"
- 3 - провал задания
Вот и всё! Можете экспериментировать с этими опкодами и
создавать новые миссии Rampage. Можно делать это в виде обыкновенного потока, я
же решил взять шаблон миссии, чтобы игра сама заканчивала действие
"Ярости", когда игрок мёртв или арестован.
Вот такая миссия, которая уложилась всего в 44 строки!
Удачных Вам перестрелок!