Sanny Builder

Sanny Builder - мощнейшее средство для создания новых миссий и скриптов в линейке трехмерных игр GTA. В комплект входит дизассемблер, который переводит игровые скрипты в текстовый формат; компилятор, который переводит скрипт в формат, читаемый игрой, и удобный редактор со множеством вспомогательных функций, таких как подсветка синтаксиса, чтение координат игрока в игре, быстрое перемещение по участкам кода и многое другое. Добавьте к этому быструю скорость работы и настраиваемый синтаксис кода (через классы и ключевые слова) и Вы получите представление о программе.

Поддерживаемые игры

 | Декомпиляция | Компиляция
GTA III | + | +
GTA VC | + | +
GTA SA | + | +
GTA LCS | + | +
GTA VCS | + | -

Установка и обновление

Запустите файл setup.exe и следуйте инструкциям инсталлятора. Во время установки вы можете дополнительно указать папку с игрой, с которой будете работать, ассоциировать файлы с расширением .scm с Sanny Builder, установить библиотеку CLEO. Все эти опции вы можете потом изменить в самой программе.

Для полного удаления программы запустите файл unins000.exe в директории программы.

Свежие версии и обновления программы всегда можно найти на официальном сайте sannybuilder.com

Параметры командной строки:

\sa - использовать как редактор SA (по умолчанию)
\vc - использовать как редактор VC
\gta3 - использовать как редактор GTA3
\lcs - использовать как редактор LCS
\vcs - использовать как редактор VCS
\sa_mobile - использовать как редактор мобильной SA (для iOS и Android)

Вы также можете изменить режим редактирования непосредственно в редакторе.

\debug - установить отладочные опции
\compile input_file_path [output_file_path] - запустить процесс компиляции в скрытом режиме

параметры: путь к исходному файлу, путь к итоговому SCM файлу.

Например: \compile C:\myscm.txt C:\myscm.scm
output_file_path является опциональным параметром. Если он не указан, компилятор будет использовать путь на основе форматов имен.
Обратите внимание, что исходный файл должен быть без ошибок! Если в процессе компиляции возникнут ошибки, они будут записаны в файл compile.log. После завершения компиляции программа завершит работу.

\nosplash - запустить программу без стартовой заставки

Дополнительная информация

Программа написана на Delphi 7.0 Ent. © Borland Software Corp
http://www.borland.com

Был использован компонент SynEdit © SynEdit Team
http://synedit.sourceforge.net

Над справкой работали yelmi и Xieon.

Sanny Builder в Интернете:
sannybuilder.com
Sanny Builder в Twitter
Sanny Builder в Facebook
Sanny Builder на GTAForums.com

С замечаниями, советами и предложениями обращаться на mail@sannybuilder.com

Используйте программу на свой страх и риск. Делайте резервные копии всех редактируемых файлов.

С наилучшими пожеланиями, Seemann.

Copyright © 2005-2019 Seemann


История изменений

  • v. 3.3.2 - 19.10.2019
  • v. 3.3.1 - 14.09.2019
  • v. 3.3.0 - 08.09.2019
  • v. 3.2.4 - 04.08.2019
  • v. 3.2.3 - 07.07.2019
  • v. 3.2.2 - 05.07.2014
  • v. 3.2.1 - 04.05.2014
  • v. 3.2.0 - 22.03.2014
  • v. 3.1.4 - 22.02.2014
  • v. 3.1.3 - 22.12.2013
  • v. 3.1.2 - 06.10.2013
  • v. 3.1.1 - 22.09.2013
  • v. 3.1.0 - 14.09.2013
  • v. 3.09 - 28.07.2013
  • v. 3.08 - 05.07.2013
  • v. 3.06 - 17.06.2013
  • v. 3.05 - 05.06.2013
  • v. 3.04 - 04.08.2008
  • v. 3.03 - 17.11.2007
  • v. 3.02 - 16.11.2007
  • v. 3.01 - 06.08.2007
  • v. 3.00 - 04.08.2007
  • v. 2.99e - 01.01.2007
  • v. 2.99d - 03.12.2006
  • v. 2.99c - 30.11.2006
  • v. 2.99 - 27.09.2006
  • v. 2.98 - 04.08.2006
  • v. 2.97 - 11.06.2006
  • v. 2.96 - 01.04.2006
  • v. 2.9f - 18.02.2006
  • v. 2.9 - 15.12.2005
  • v. 2.6 - 05.11.2005
  • v. 2.5 - 10.10.2005
  • v. 2.0 - 18.09.2005
  • v. 1.1 - 07.09.2005
  • v. 1.0 - 04.09.2005
  • v. 0.8 - 20.08.2005
  • v. 0.7 - 10.08.2005
  • v. 0.6 - 04.08.2005

Текущая версия: 3.3.3

Список изменений:

  • исправлен баг, вызывавший неправильную компиляцию внешних скриптов

v. 3.3.2 - 19.10.2019

  • исправлены баги #0036, #0050
  • исправлен опкод 059C в режиме Vice City

v. 3.3.1 - 14.09.2019

  • исправлен баг #0048
  • добавлен файл constants.txt, который отсутствовал для режима GTA SA

v. 3.3.0 - 08.09.2019

  • добавлена поддержка для компиляции SCM Liberty City Stories
  • добавлены алиасы для переменных-таймеров: TIMERA and TIMERB
  • опция Проверка переменных теперь применяется и к глобальным переменным

v. 3.2.4 - 04.08.2019

  • исправлены баги #0031, #0032, #0033, #0040, #0044
  • исправлен дефект предыдущей версии, когда CHM справка не открывалась
  • обновлены описания опкодов для GTA 3 и Vice City
  • в IDE добавлена поддержка CLEO 2.0 для III и VC

v. 3.2.3 - 07.07.2019

  • улучшена поддержка версии GTA San Andreas для Wi﻿nStore, Xbox 360 и P﻿S3
  • исправлена ошибка с неправильной декомпиляцией опкодов 09A4 и 0A18 в режиме SA_Mobile

v. 3.2.2 - 05.07.2014

  • добавлен перевод на корейский язык (спасибо MINE)
  • улучшена работа конструкции HEX..END
  • исправлен баг #0000028

v. 3.2.1 - 04.05.2014

  • добавлен перевод на индонезийский язык (спасибо IMasterFX)
  • обновлены CLEO для GTA III и CLEO для Vice City (спасибо Silent)
  • исправлены баги #0000026, #0000027

v. 3.2.0 - 22.03.2014

  • добавление собственных режимов редактирования возможно путем изменения файла games.xml
  • новый режим редактирования - GTA SA SCR
  • переменные могут быть объявлены при помощи указания типа перед именем переменной
  • CLEO обновлена до версии 4.3.16
  • добавлен моментальный поиск в тексте (ранее эта возможность называлась "переход к метке")
  • оригинальные названия миссий могут быть изменены через файл missions.txt
  • улучшена ассоциация расширений скриптовых файлов с Sanny Builder
  • при указании директории игры Sanny Builder проверяет только существование этой директории и не проверяет наличие дополнительных файлов в ней
  • небольшие улучшения в функции проверки обновлений
  • изменена иконка Sanny Builder и иконки в меню
  • исправлен баг #0000024

v. 3.1.4 - 22.02.2014

  • CLEO обновлена до версии 4.3.14
  • исправлены некоторые ошибки в интерфейсе на высоких разрешениях экрана
  • обновлены переводы на немецкий, польский, китайский, украинский языки

v. 3.1.3 - 22.12.2013

  • добавлена поддержка iOS и Android версий GTA: San Andreas
  • значение глубины просмотра теперь используется при построении списка констант
  • обновлены переводы на китайский и немецкий языки

v. 3.1.2 - 06.10.2013

  • добавлен перевод на чешкий язык
  • добавлены опции ассоциации файлов .cs и .cm с Sanny Builder.
  • исправлены баги #0000011, #0000020

v. 3.1.1 - 22.09.2013

  • добавлена новая директива $OPCODE для регистрации нового опкода через скрипт
  • скорректировано поведение директивы $INCLUDE при поиске файла
  • исправлены баги #0000005, #0000019

v. 3.1.0 - 14.09.2013

  • в VCSCM.ini добавлены опкоды из мобильной версии GTA VC и отмечены неподдерживаемые опкоды
  • при включенной опции Добавлять доп. информацию в SCM, Sanny Builder запоминает игру, для которой был скомпилирован скрипт, чтобы включить нужный режим редактирования при декомпиляции
  • при включенной опции Добавлять доп. информацию в SCM, Sanny Builder добавляет исходный код в тело скрипта (только при наличии директивы $EXTERNAL или $CLEO)
  • добавлена новая директива $NOSOURCE, чтобы запретить добавление исходного кода в тело скрипта
  • некоторые горячие клавиши могут быть изменены в опциях
  • добавлена возможность автоматически проверять наличие обновления при запуске программы
  • директивы $VERSION и $VERSION_RESTORE устарели (компилируются, но не имеют эффекта)
  • обновлены перевод на испанский и китайский языки
  • Менеджер координат может изменять угол поворота игрока в GTA VC
  • в комплектацию Sanny Builder добавлен CLEO плагин SCRLog от LINK/2012 (можно найти в папке tools)
  • исправлены баги #0000010, #0000014, #0000015, #0000016

v. 3.09 - 28.07.2013

  • в Sanny Builder добавлено лицензионное соглашение вида Freeware/Donationware
  • добавлена возможность сообщать о найденных багах в официальный баг-трекер
  • добавлена возможность проверять наличие обновления для Sanny Builder
  • Менеджер координат теперь поддерживает все известные версии GTA3, VC и SA (спасибо Silent)
  • добавлена обновленная версия перевода на китайский язык
  • исправлены баги #0000002, #0000003, #0000004, #0000006, #0000009
  • небольшие изменения дизайна

v. 3.08 - 05.07.2013

  • добавлен Silent's ASI Loader v1.1 для CLEO 3 и CLEO 4
  • добавлен перевод на китайский язык
  • добавлены классы File и Audiostream для обратной совместимости с CLEO 4 от Alien*
  • компилятор теперь может принимать строковую константу в качестве параметра в свойстве класса**
  • компилятор больше не компилирует строки без начальной кавычки, например text1"text2" или text1'text2'
  • компилятор может компилировать символы комментария внутри строки ("{text1}text2")
  • точка с запятой (;) больше не может использоваться для закомментирования строки
  • изменен синтаксис параметра \debug
  • добавлены иконки флагов для доступных языков перевода в опциях
  • исправлены некоторые ошибки в декомпиляции для VCS

Важное замечание: File.Open, Audiostream.Load, Audiostream.Load3D были методами в CLEO 4. Теперь они свойства. Это означает, что если вы получаете ошибку при компиляции старых скриптов, где использовались эти команды, измените их синтаксис следующим образом:
переменная = File.Open(имя_файла, режим_открытия)
переменная = Audiostream.Load(имя_файла)
переменная = Audiostream.Load3D(имя_файла)

Существует ограничение на использование пробелов в таком параметре.

v. 3.06 - 17.06.2013

  • добавлены новые операторы ++ и --
  • добавлена поддержка блочных комментариев /* */
  • SASCM.INI обновлен при помощи базы GTAG
  • свойства Actor.Armour и Actor.Car заменены на корректные версии Actor.AddArmour, Actor.MissionCar
  • добавлено новое свойство Actor.CurrentCar для опкода 03C0 в скриптовых классах для игр SA и VC
  • добавлены новые комбинации клавиш Ctrl+Num+ и Ctrl+Num- для быстрого изменения размера шрифта в редакторе
  • Sanny Builder запоминает число закрытых файлов для опции Открывать все закрытые файлы
  • исправлена ошибка при компиляции скрипта с большим числом вставок hex..end
  • исправлена ошибка версии 3.05, когда программа зависала при запуске, пытаясь открыть файл, переданный в качестве параметра

v. 3.05 - 05.06.2013

  • добавлены новые языки перевода (финский, польский, венгерский, украинский, турецкий)
  • библиотека CLEO обновлена до версии 4.1.1.30f (CLEO 4 от Alien)
  • Добавлена возможность установить CLEO для GTA III и для Vice City (автор - Alien)
  • файлы опкодов (**SCM.ini, opcodes.txt) замененены на файлы из комплекта CLEO 4.
  • добавлен новый параметр запуска программы \nosplash

v. 3.04 - 04.08.2008

  • в редактор кода добавлены возможности конвертации чисел из 16-чной системы счисления в 10-чную и наоборот (Ctrl+H), а также конвертировать имя модели в ID и обратно (Ctrl+Alt+H)
  • убрано сообщение о невозможности изменить script.img при компиляции CLEO-скриптов
  • отчет о компиляции показывает размер CLEO-скрипта (пункт Largest Script)
  • исправлена ошибка при компиляции массива с числовыми индексами
  • инсталлятор не требует прав администратора

v. 3.03 - 17.11.2007

  • предыдущая версия CLEO была с ошибкой
  • мелкие исправления (положение панели инструментов теперь сохраняется)

v. 3.02 - 16.11.2007

  • новая версия CLEO
  • панель инструментов можно передвигать
  • F7 при компиляции SCM без заголовка (c директивами $E, $CLEO) не делает копию
  • при компиляции файла с директивой $CLEO нажатием F6 файл создается в той же папке, нажатием F7 дополнительно создается копия в папке CLEO (по аналогии с обычными scm-файлами)
  • новый язык перевода - итальянский, португальский

v. 3.01 - 06.08.2007

  • обновление, исправляющее некоторые ошибки

v. 3.00 - 04.08.2007

  • интегрирована библиотека CLEO 3
  • возможность декомпиляции main.scm Vice City Stories
  • поддержка констант
  • новые директивы $INCLUDE,$EXTERNAL,$CLEO
  • запись дополнительной информации в конец main.scm
  • задание собственных массивов при декомпиляции
  • возможность декомпилировать файлы main.scm без заголовка
  • можно использовать внешний скрипт с именем AAA
  • новый параметр командной строки \compile
  • в цикле FOR можно использовать дробные значения счетчика
  • команды WriteMem и ReadMem больше не поддерживаются
  • поддержка поиска по тексту с использованием регулярных выражений
  • возможность сохранять исходник в формат RTF или HTML
  • возможность пропускать заставки при запуске San Andreas
  • новая комбинация клавиш: Ctrl+Enter
  • обновленный SASCM.INI

v. 2.99e - 01.01.2007

  • справлена ошибка с пропаданием части кода при декомпиляции в режиме отладки внутри конструкции hex..end
  • конструкция hex..end может принимать тип aDMA для записи чисел
  • к цикле FOR можно использовать имена моделей в качестве значений счетчика
  • конструкция hex..end может принимать строки

v. 2.99d - 03.12.2006

  • убран Memory Hacker (он стал отдельной программой)
  • исправлена одна ошибка в декомпиляторе

v. 2.99c - 30.11.2006

  • добавлен плагин Memory Hacker
  • возможность декомпиляции main.scm Liberty City Stories
  • поддержка числовых констант в качестве индекса глобального массива
  • при декомпиляции переменные заменяются на тип ADMA, если не делятся на 4
  • при компиляции при отсутствии заголовка выставляются значения по умолчанию
  • возможность открывать файлы в редакторе методом Drag&Drop
  • новые препроцессорные директивы: {$VERSION}, {$VERSION_RESTORE}

Если при компиляции вы получаете сообщение об ошибке в заголовке ("Неизвестная команда DEFINE OBJECTS") переместите строку {$VERSION xxxx} в любое место после заголовка, например перед комментарием //-------------MAIN---------------

v. 2.99 - 27.09.2006

  • добавлены две новые команды WriteMem и ReadMem
  • поддержка чисел в шестнадцатиричном формате
  • конструкция hex..end может принимать значения меток и глобальных переменных
  • поддержка типа данных & для массивов, а также в выражениях без опкодов: &57 += &120(&231,4i)
  • возможность давать собственные имена меткам
  • возможность выбирать регистр букв для собственных имен меток и переменных, а также стринговых переменных (Настройки -> Форматирование)
  • добавлена консоль для специальных опций SB
  • поддержка GXT-файлов GTA III, GTA VC
  • поддержка символьных констант в длинных строках
  • информация об авторе и версии INI файла
  • поддержка классами INI с оригинальным порядком следования параметров (как SASCM.INI от PLPynton)
  • опция подтверждения выхода
  • возможность быстро переключать режим редактирования
  • конвертация отдельного, выделенного участка кода
  • возможность передавать во внешнее приложение в качестве параметра имя текущего открытого файла
  • исправлены некоторые ошибки в конфигурационных файлах
  • убрана автоматическая конвертация числа в тип Float, если переменная была объявлена как Float, а в нее записывалось целое число. Теперь опкод выбирается только в зависимости от типа числа
  • чтение/изменение Z_angle игрока в Coord Manager; возможность вставки значения угла в скрипт нажатием Ctrl+Shift+E (для SA)

v. 2.98 - 04.08.2006

  • Sanny Builder полностью русифицирован
  • добавлено меню внешних приложений
  • в SB встроена специальная версия Opcode Search Tool
  • проверка математических выражений при декомпиляции с выключенной опцией "Писать опкоды"
  • возможность выбирать IMG-файл самостоятельно, если таковой не найден в папке с SCM-файлом (опция "Ручной выбор IMG-файла")
  • возможность добавлять новые макросы прямо из редактора; добавлены описания макросов
  • список моделей можно сортировать по алфавиту/по значению (Alt+S, когда активен список)
  • минорные исправления и изменения

v. 2.97 - 11.06.2006

  • новый тип данных: & (direct byte address)
  • минорные изменения

v. 2.96 - 01.04.2006

  • расширена опция прохода по меткам
  • добавлена возможность вызвать список макросов
  • добавлена опция замены номеров миссий на их имена
  • исправлены некоторые ошибки

v. 2.9f - 18.02.2006

  • новые модели автоматически добавляются в список DEFINE OBJECTS (этот список можно вообще не использовать)
  • добавлены блочные комментарии: {}
  • добавлена запись макросов
  • минорные исправления и добавления

v. 2.9 - 15.12.2005

  • добавлены дополнительные команды
  • добавлен оператор IN
  • добавлена конструкция IF..THEN..ELSE..END
  • добавлены циклы WHILE, REPEAT; добавлена возможность использования вложенных циклов
  • добавлена команда ALLOC
  • новый стиль комментариев: //
  • позиции маркеров и курсора запоминаются для закрытых файлов

v. 2.6 - 05.11.2005

  • добавлена поддержка форматов Vice City и GTA3
  • добавлена возможность инициализации переменных и массивов как членов класса
  • добавлен показ списка переменных и меток
  • добавлена поддержка циклов ( оператор FOR )
  • миссии можно запускать по их имени (start_mission MYMISSION), где MYMISSION - это имя стартовой метки (DEFINE MISSION 100 at @MYMISSION )
  • доступен список импортируемых моделей (defined objects) по Ctrl+Space
  • новый оператор <>
  • если при декомпиляции не найден script.img, используется оригинальный файл
  • для массивов добавлен тип handle
  • возможность отключения предупреждения об использовании IMG игрой

v. 2.5 - 10.10.2005

  • добавлена поддержка свойств классов
  • добавлена поддержка макросов
  • добавлена конструкция VAR..END для эффективного управления переменными
  • описаны все возможные математические опкоды: 0004..008B
  • новые операторы < и <=
  • добавлена возможность автоподбора необходимого значения для оператора IF
  • добавлена поддержка текстовых названий параметров
  • добавлен показ списка моделей
  • минорные добавления и исправления

v. 2.0 - 18.09.2005

  • добавлена поддержка классов
  • добавлена поддержка ключевых слов
  • добавлена возможность писать некоторые математические команды без опкодов
  • для опкода 00D6 по умолчанию устанавливается параметр 0, если иное не установлено (if = if 0)
  • добавлена опция выбора различных видов меток (Formats->Labels Format)
  • добавлены ключевые слова True и False, которые обозначают 1 и 0 соответственно
  • добавлена конструкция HEX..END для записи шестнадцатиричных значений прямо в SCM

v. 1.1 - 07.09.2005

  • добавлен coord manager
  • исправлены некоторые ошибки

v. 1.0 - 04.09.2005

  • новый формат меток
  • добавлен конвертор из синтаксиса BW's SA Mission Builder
  • при декомпиляции в исходник добавляются названия моделей и содержимое american.gxt
  • добавлены новые опции
  • пофиксены некоторые ошибки

v. 0.8 - 20.08.2005

  • добавлена возможность ассоциировать SCM-файлы с программой
  • теперь при декомпиляции имя выходного файла изменяется, если такой файл уже существует (например, если уже существует main.scm.txt, то имя нового файла будет main.scm[0].txt)
  • сообщения об ошибках стали более информативными
  • добавлена проверка на дублирование меток
  • пофиксены некоторые ошибки

v. 0.7 - 10.08.2005

  • увеличено число опций для работы с текстом
  • добавлена возможность работать с несколькими файлами одновременно
  • добавлена функция поиска опкодов через F1 (beta)

v. 0.6 - 04.08.2005

  • полная декомпиляция *.scm файлов San Andreas
  • компиляция скриптов в SCM-файл (SA) и IMG-файл
  • доступны минимальные опции работы с текстом


Sanny Builder Help: Кодинг

  • Типы данных
  • Переменные
  • Константы
  • Массивы
  • Условия
  • Циклы
  • Классы
  • Ключевые слова (кейворды)
  • Дополнительные команды
  • HEX..END
  • Директивы


Типы данных

Код разделен на отдельные элементы, каждый из которых обозначается по-своему и выполняет конкретную функцию в скрипте.

$ - обозначение глобальных переменных. Их значения могут использоваться в любом месте кода.

Пример:

0004: $MyVar = 100

@ - в начале: метка

Пример:

0002: jump @MyLabel

@ - в конце: локальная переменная. Их значения используются только в пределах одного потока

Пример:

0006: 100@ = 10

'...' - текст (макс. 15 символов).

Допускается пустое значение: ' '

Пример:

03A4: name_thread 'MAIN'

"..." - текст (максимум определяется опкодом)

Также вы можете использовать в тексте одинарные кавычки или двойные кавычки.
Для двойных кавычек необходимо использовать специальный префикс \.

Допускается пустое значение: " "

Пример:

0662: write_debug_message "Hello, \"world\"! 'Here we go!'"

s$ - глобальная стринговая переменная

Пример:

05A9: s$MyString = 'GLOBAL'

@s - локальная стринговая переменная

Пример:

05AA: 1@s = 'LOCAL'

v$ - глобальная стринговая переменная

Пример:

06D1: v$MyString = "LONG_GLOBAL"

@v - локальная стринговая переменная

Пример:

06D2: 1@v = "LONG_LOCAL"

# - имя модели из одного из IDE - файлов игры

Пример:

0247: request_model #CELLPHONE

& - прямой байтовый адрес (ADMA). Читает и пишет значения по указанному адресу Может использоваться в тех же случаях, когда используется тип $.

Пример:

&57 += &120(&231,4i)

(примечание: число после & - локальное смещение внутри файла main.scm, относительно его начала; адрес, куда будет записано значение)

0x - число в шестнадцатиричном формате.
-0x - отрицательное значение

Пример:

0004: $var = -0xBB08

Число должно быть в интервале -80000000..7FFFFFFF

См. также: Типы данных


Переменные

Переменная - это именновая область памяти, которая хранит определенное значение. Значение переменной может быть прочитано или изменено неограниченное число раз. Существует два вида переменных:

Глобальные переменные

Глобальные переменные обозначаются знаком доллара ($) перед именем. Имя глобальной переменной - это любое сочетание букв, цифр и знака нижнего подчеркивания (_)

$variable1 $100 $____

Их значения доступны из любой миссии или потока.

Сохраняемые переменные

Сохраняемая переменная - это особый вид глобальной переменной, доступный только в режимах LCS и VCS. Она обозначается комбинацией знаков $ и _ перед именем переменной: $_var. Значение такой переменной сохраняется в сейве и восстанавливается при загрузке игры. Значение обычной глобальной переменной, обозначаемой только знаком $, не восстанавливается при загрузке игры и обнуляется.

Локальные переменные

Локальные переменные обозначаются знаком @ после имени. Имя локальной переменной может состоять только из цифр

0@ 999@ 56@

Их значения доступны только в пределах одного потока или миссии.

Каждый поток, внешний скрипт, CLEO скрипт имеет ограниченный набор локальных переменных. Смотрите документацию по лимитам, чтобы найти допустимые значения.

Переменные-таймеры

Каждый скрипт имеет доступ к двум специальным локальным переменным TIMERA и TIMERB. Значение таких переменных увеличивается одновременно с игровым временем, поэтому они обычно используются в скриптах для измерения пройденного времени.

0006: TIMERA = 0

:WAIT_2S
0001: wait 0 ms
00D6: if
0019:   TIMERA > 2000
004D: jump_if_false @WAIT_2S
0662: printstring "прошло 2 секунды"

Обратите внимание, что TIMERA и TIMERB names доступны начиная с версии Sanny Builder v3.3.0. В скриптах предыдущих версии такие таймеры выводились как обычные переменные 16@, 17@ (GTA3, VC) или 32@, 33@ (SA).

Конструкция VAR..END

Переменные используются в качестве операндов (членов) математических и логических выражений. Если правый операнд является числовой константой, Sanny Builder автоматически подбирает опкод для выражения.

$var = 0
$myarray($index, 10i) >= 150

Во многих случаях это будет даже правильнее, потому что часто в таких выражениях скриптеры используют неверные опкоды.

Однако, если в выражении в обоих сторон участвуют переменные, то компилятор не знает, какой именно опкод необходим в данном случае. Для разных типов переменных существуют свои опкоды.

Для того чтобы подсказать компилятору тип переменной, она должна быть объявлена через конструкцию VAR..END. Она позволяет объявлять переменные и их типы, для последующего манипулирования ими.

Синтаксис:
var
<имя переменной>: <новый тип>
end

Например, если обе переменные были объявлены, компилятор правильно обрабатывает выражения без опкодов:

var
$Var1 : Integer
$Var2 : Integer
end
$Var1 += $Var2 // опкод 0058

Поддерживаются следующие типы переменных:

  • Integer, Int - переменные целого типа (хранят целочисленные значения)
  • Float - переменные дробного типа (хранят дробные значения)
  • String, ShortString - переменные, содержащие строковый литерал фиксированной длины (только для массивов, используйте s$, @s для переменных)
  • LongString - переменные, содержащие строковый литерал переменной длины (только для массивов, используйте v$, @v для переменных)
  • <Имя класса> - любое доступное имя класса

Кроме глобальных переменных можно объявлять и локальные переменные.

Но нужно помнить, что в этом случае все такие переменные во всех потоках будут иметь один и тот же тип. Чтобы избежать этого, вы можете переобъявлять переменные в каждом потоке:

thread 'Food'
var
10@ : Float
$Var : Float
end
$var = 1
10@ = $Var
end_thread

thread 'Loop'
var
10@ : Int
$Var : Int
end
$var = 1
10@ = $Var
end_thread

В потоке "Food" 10@ это переменная дробного типа. В потоке "Loop" 10@ - целого типа.

Вы можете переобъявлять переменные сколько угодно раз.

Короткая форма объявления

Начиная с версии 3.2.0 можно объявить переменную используя один из встроенных типов данных (Int, Float, String, LongString).

Синтаксис:
<тип> <имя переменной>

int 0@ // 0@ объявлена как переменная целого типа.

Инициализация переменных

Также вы можете инициализировать значение переменной сразу при объявлении. Для этого после указания типа поставьте знак = и стартовое значение:

var
$fVar: float = 1.0
end
или
float $fVar = 1.0

$fVar будет объявлена как переменная дробного типа и одновременно компилятор добавит в скрипт опкод:

0005: $fVar = 1.0

Инициализация доступна только для переменных, но не массивов.


Константы

Константа представляет собой идентификатор, которому присваивается определенное значение. В отличие от переменных значение константы не может изменяться. При компиляции имя константы заменяется на то значение, которое ей было присвоено. Константы могут быть числовыми и строковыми, а также содержать в себе выражение.

Чтобы создать константу, используйте конструкцию CONST..END. Ее синтаксис выглядит следующим образом:

CONST
<имя константы> = <значение>
END

Имя константы - любой допустимый идентификатор (латинские буквы, цифры и знак подчеркивания). Не допускается использование преопределенных имен вроде Continue, True, And и т.д. Значение - число (метка, модель); строка; выражение (например, класс или переменная); другая константа.

Пример использования:

const
MoneyRequired = 30
PlayerMoney = $PLAYER_CHAR.Money
end

if
PlayerMoney > MoneyRequired
then
PlayerMoney += -1
end

При компиляции константа MoneyRequired будет заменена на число 30, а PlayerMoney на выражение $PLAYER_CHAR.Money

Компилятор также использует 2 внутренние константы True и False, значения которых равны 1 и 0 соответственно.

Вы можете использовать константы в любом месте кода, за исключением данного случая:

const
VarName = $Var
IndexName = 25
end
VarName[IndexName] = 0

Для компиляции такого выражения вы должны указать опкод, например:

0004: VarName[IndexName] = 0

Также определенные ограничения возникают при компиляции констант-выражений.

Список констант можно вызвать в любом месте кода нажатием Ctrl + [space].


Массивы

Массивы представляют собой набор индексированных элементов одного типа (тип массива). К каждому элементу массива можно обратиться напрямую, используя его индекс (номер элемента в массиве). Нумерация элементов идет, начиная с нуля.

Массивы поддерживаются играми SA и LCS, VCS.

Синтаксис:

San Andreas:
<имя массива>(<имя индексной переменной>,<размер><тип>)

Liberty City Stories, Vice City Stories:
<имя массива>(<имя индексной переменной>,<размер>)

<Имя массива>: локальная или глобальная переменная.
Имя переменной должно быть выбрано с учетом размера массива. Например, в потоке нельзя использовать в качестве имени переменную 33@, если размер массива больше 1, так как в потоках максимально допустимая локальная переменная это 33@, а элемент массива 33@ с индексом больше 0 будет за этими границами.

<Имя индексной переменной>: любая переменная.

<Размер>: любое целое число больше нуля.

<Тип>: буквы i f s v обозначающие один из типов массива:

i: integer, только целые значения, размер элемента 4 байта

f: float, дробные значения, размер элемента 4 байта

s: string, строки с фиксированной длиной 8 байтов

v: longstring, строки с фиксированной длиной 16 байтов

В LCS, VCS элементы массива могут иметь только размер 4 байта, поэтому указание типа не требуется. Массив может содержать элементы только одного типа.

Пример: чтобы обратиться к первому элементу массива, состоящего из десяти элементов, нужно использовать такую запись:

Copy to Clipboard
$index = 0
$array($index,10i) = 1

Sanny Builder позволяет упростить работу с массивами двумя способами:

1) определить его в блоке VAR..END

Используется следующая запись:

var
<array name>: array <size> of <type>
end

Например:

Copy to Clipboard
var
$FloatArray: array 10 of Float
end

После этого вы можете работать с этим массивом без указания его типа и размера. Например:

$FloatArray[$RndIndex] += 100.0

2) использовать индексированные переменные

Допустим, у вас есть массив $strings, состоящий из 10 элементов типа s. Вы можете обратиться к его элементам, напрямую через переменную $strings. Например, для записи в последную ячейку массива используйте запись:

s$strings[9] = 'str10'

Индексированные переменные очень удобно использовать для инициализации массива с разными стартовыми значениями элементов:

s$strings[0] = 'str1'
s$strings[1] = 'str2'

...

s$strings[9] = 'str10'

После этого вы можете использовать и полный вариант записи:

$index = 9
if
s$strings($index,10s) == 'str10'
then
0@ += 1
end

Такие переменные могут использоваться и в качестве имени класса, когда они объявлены как массив, например

$cars[0].Destroy

Смотри объявление массива выше.

По умолчанию при декомпиляции в режиме SA элементы массива записываются как индексированные переменные. Вы можете отключить эту возможность через консоль (команда toggle constant_indexes off). Тогда переменные будут декомпилироваться как обычно. Возможность декомпилировать с данной опцией доступна и для LCS, VCS (по умолчанию выключено).

О массивах см. также: Меняем игровую память через SCM (San Andreas)


Условия

Для проверки условия (-ий) необходимо использовать оператор IF.

Допускается использование двух видов проверки:

  1. низкоуровневое
  2. высокоуровневое

1. Используется следующий синтаксис:

00d6: if <N>
... <condition 1>
... <condition 2>
...
... <condition n+1>
004d: jump_if_false <label>

<N> - параметр, обозначающий количество условий.
0 - проверяется 1 условие
1..7 - 2 и более условий (максимум 8), связанных логическим оператором AND. Это значит что проверка выполнится, если ВСЕ условия, входящие в нее, верны.
21..27 - 2 и более условий (максимум 8), связанных логическим оператором OR. Это значит что проверка выполнится, если хотя бы ОДНО условие, входящее в нее, верно.

<label> - имя метки, на которую должен перейти скрипт, если условие ложно.

Sanny Builder допускает не использовать параметр 0 для одиночного условия. Таким образом, IF тоже самое что IF 0.

Также вы можете использовать ключевые слова AND или OR вместо числовых параметров*. Тогда компилятор сам будет высчитывать необходимое значение.
Например:

if and
$var > 0
$var2 == 10.0
jf @anywhere

Компилятор подставит цифру 1 вместо and.

* В опциях должна быть включена проверка условий.
IF AND - условия связываются логическим оператором AND (1..7)
IF OR - условия связываются логическим оператором OR (21..27)

2. Sanny Builder поддерживает конструкции IF..THEN..END и IF..THEN..ELSE..END*

Создание условия происходит по правилам, описанным выше. После слова THEN вы указываете команду (-ы), которые должны выполняться, если условие верно. После слова ELSE вы указываете команду (-ы), которые должны выполняться, если условие ложно. Условие заканчивается словом End.

if $var == 5
then
Inc($var)
else
Dec($var)
end

Допускается использование вложенных условий.

*В опциях должна быть включена проверка условий.

В качестве операторов сравнения в условиях могут использоваться следующие их виды*:

a == b a равно b
a >= b a больше либо равно b
a > b a больше b
a < b a меньше b
a <= b a меньше либо равно b
a <> b a не равно b

Поддерживаются также их вариации со словом NOT.

* При условии, что вы не используете опкод в выражении.


Циклы

Цикл - это конструкция, позволяющая выполнять последовательность команд неоднократно. Sanny Builder поддерживает три вида циклов: repeat, while, for.

Цикл FOR

Цикл FOR имеет строго ограниченное количество итераций (повторений).

Синтаксис:
FOR <переменная цикла> = <начальное значение> TO/DOWNTO <конечное значение> [step = 1]
<тело цикла>
END

<переменная цикла> - переменная, используемая в качестве счетчика итераций

<начальное значение> - начальное значение переменной цикла (любое значение, включая имя модели)

TO/DOWNTO- увеличивать или уменьшать переменную цикла

<конечное значение> - конечное значение переменной цикла, при которой он заканчивает свою работу (любое значение, включая имя модели)

<step> - шаг цикла: опциональная величина, на которую будет увеличиваться или уменьшаться переменная цикла после каждой итерации. По умолчанию равна 1

Пример:

var
$value: int = 0
$final: int = 100
end

FOR $MyCounter = 1 to $final step 2
$value += $mycounter
end

Если начальное/конечное значение или шаг цикла указаны в виде переменных, эти переменные будут автоматически объявлены с тем же типом, который есть у переменной цикла. Если переменная цикла не была объявлена с каким-то типом до использования в цикле, она получит тип Integer. Чтобы использовать дробные значения в цикле FOR, объявите переменную цикла с типом Float.

Пример:

var
$MyCounter: float
end

FOR $MyCounter = 1.0 to $final step 2.0
end

Переменные $MyCounter и $final обе будут иметь тип Float после цикла.

Цикл WHILE

Синтаксис:
WHILE <условие цикла>
<тело цикла>
END

Пример:

while not #AK47.Available
wait 0
end

Цикл WHILE работает до тех пор, пока условие цикла истинно. Условие цикла проверяется до первой итерации цикла. Поэтому если условие изначально ложно, цикл не отработает ни разу.

$var = 10

while $var > 11
inc($var)
end

Так как условие $var > 11 ложно, команда inc($var) не выполняется.

Константы true и false могут быть использованы в качестве условия цикла.

while true
<тело цикла>
end

Тело цикла будет выполняться бесконечно до тех пор, пока цикл не будет прерван командой Break.

while false
<тело цикла>
end

Этот цикл будет игнорироваться компилятором, поскольку условие никогда не выполняется.

В текущей версии компилятор принимает только одно условие в качестве условия цикла. Для проверки нескольких условий одновременно, включите их в тело цикла и используйте команды Break и Continue.

Цикл REPEAT..UNTIL

Синтаксис:
REPEAT
<тело цикла>
UNTIL <условие цикла>

Цикл repeat..until loop работает пока условие цикла не будет истинно. Условие проверяется в конце итерации цикла, поэтому данный цикл будет иметь минимум одну итерацию.

Константы true и false могут быть использованы в качестве условия цикла.

repeat..until true - цикл имеет только одну итерацию.

repeat..until false - цикл работает бесконечно пока не будет остановлен командой Break

В текущей версии компилятор принимает только одно условие в качестве условия цикла. Для проверки нескольких условий одновременно, включите их в тело цикла и используйте команды Break и Continue.

Continue и Break

Если вы хотите пропустить итерацию цикла и перейти к следующей, используйте команду Continue. Команда Break заставляет скрипт немедленно прекратить работу цикла и перейти к команде сразу после него.

Обе эти команды могут быть использованы как параметр в опкоде (например, jf continue) или как отдельная команда.

Пример:

if
    $currentactor.dead
jf Break // выход из цикла

if
    not $currentactor.dead
then
   Continue // переход к следующей итерации
end


Классы
Основные понятия

Sanny Builder допускает использование классов при написании кода. Классы - это группа опкодов, относящихся к какому-либо виду объектов в игре: игрок, актер, машина и т.д.

Все классы заранее определены в файле classes.db и изменять их в процессе кодинга невозможно. Все изменения вносятся напрямую в этот файл.

Каждый класс обладает набором команд (опкодов). Их можно разделить на несколько групп:

  • условные
  • процедуры (методы)
  • свойства
Условные команды

Условные опкоды в списке команд, вызываемом нажатием Ctrl + [space], обозначаются словом Check. Чаще всего у них один параметр - это хендл (имя) владельца класса: машины, игрока и т.д. Например:

if
Player.Defined($PLAYER_CHAR)
jf @anywhere

Процедуры

Процедурные опкоды предназначены для выполнения какого-либо конкретного действия в игре: движение объекта, уничтожение его и т.п. Отдельный вид таких опкодов - это конструкторы, которые создают объект (актера, машину) и возвращают его хендл. В SB конструкторы могут использоваться как процедура, так и как свойство.

Player.Create($PLAYER_CHAR, #NULL, 2488.5601, -1666.84, 13.38) - процедура
$PLAYER_CHAR = Player.Create(#NULL, 2488.5601, -1666.84, 13.38) - свойство-конструктор

Эффект будет одинаков.

Свойства

Свойства класса используются для чтения или записи каких-либо значений внутри класса. Например свойство Money класса Player позволяет оперировать с тремя опкодами:

0109: player $PLAYER_CHAR money += 1000000
010A: player $PLAYER_CHAR money > 461@
010B: 4@ = player $PLAYER_CHAR money

После того как это свойство описано в файле classes.db вы можете использовать следующие команды:

player($PLAYER_CHAR).Money += 1000000
player($PLAYER_CHAR).Money > 461@
4@ = player($PLAYER_CHAR).Money

В настоящий момент существует серьезное ограничение по использованию свойств в качестве операндов выражений. Sanny Builder может скомпилировать только такие выражения, которые заранее прописаны в файле classes.db. Т.е. вы не можете, например, использовать такое выражение:

player($PLAYER_CHAR).Money -= 1000000

поскольку для операции вычитания нет отдельного опкода.

В текущей версии существует ограничение на использование пробелов в строковых переменных в свойствах класса. Компилятор игнорирует все пустые символы в таком параметре. Например, такая команда

0@ = File.Open("file name","wb")

будет скомпилирована как

0@ = File.Open("filename","wb")
Члены класса

Начиная с версии 2.6 также можно инициализировать переменные как члены класса и оперировать с ними как с классом.
Например:

var
$PLAYER_CHAR: Player
end

Мы объявили переменную $PLAYER_CHAR как класс Player. Теперь для нее доступны все команды, какие есть для этого класса.
Например:

if
$PLAYER_CHAR.Defined
jf @anywhere

Обратите внимание, что такие переменные будут компилироваться как первый параметр, поэтому дублировать ее не следует.

Player.SetClothes($PLAYER_CHAR, "PLAYER_FACE", "HEAD", Head)
=
$PLAYER_CHAR.SetClothes("PLAYER_FACE", "HEAD", Head)

Такие переменные также можно переобъявлять и изменять их тип.

Класс Model

Класс Model можно использовать при помощи имен моделей, которые всегда будут являться членами этого класса. Например, вы можете использовать следующий код:

#AK47.Load

:loop
wait 0
if
#AK47.Available
jf @loop

Это будет тоже самое что

Model.Load(#AK47)

:loop
wait 0
if
Model.Available(#AK47)
jf @loop

Расширенные названия параметров

В классах вы можете использовать текстовые названия для параметров для повышения читабельности кода.
Например:

Player.SetClothes($PLAYER_CHAR, "VEST", "VEST", Torso)

Torso - это параметр типа Extended.

Для облегчения использования расширенных названий, их список для текущей команды может вызываться нажатием Ctrl + [space].
Просто установите курсор туда, где должен быть расширенный параметр,
(обозначается словом Extended во всплывающей подсказке), нажмите ctrl + [space] и в редакторе появится список возможных имен с указанием числового значения для каждого из них.


Ключевые слова (кейворды)

Заменяют собой опкоды для простых команд. Например кейворд WAIT при компиляции будет заменен на опкод 0001. Т.е. можно писать

wait 0

вместо

0001: wait 0

Список кейвордов содержится в файле keywords.txt (свой для каждой игры). В редакторе его можно вызвать нажатием Ctrl + [space]


Дополнительные команды

INC - эта команда увеличивает значение переменной, переданной как первый параметр, на значение второго параметра. Второй параметр может не использоваться, тогда вместо него будет установлена 1.

Inc($IntVariable, $Value)
=
$IntVariable += $Value

Inc(1@)
=
1@ += 1

Начиная с версии 3.06, можно использовать С++-подобный оператор ++, который увеличивает значение переменной на 1.

$var++
=
$var += 1

DEC - эта команда уменьшает значение переменной, переданной как первый параметр, на значение второго параметра. Второй параметр может не использоваться, тогда вместо него будет установлена 1.

Dec($IntVariable, $Value)
=
$IntVariable -= $Value

Dec(1@)
=
1@ -= 1

Начиная с версии 3.06, можно использовать С++-подобный оператор --, который уменьшает значение переменной на 1.

$var--
=
$var -= 1

MUL - эта команда умножает значение переменной, переданной как первый параметр, на значение второго параметра.

Mul($IntVariable, $Value)
=
$IntVariable = $IntVariable * $Value

Второй параметр может не использоваться, тогда вместо него будет установлена 2.

Mul(1@)
=
1@ = 1@ * 2

DIV - эта команда делит значение переменной, переданной как первый параметр, на значение второго параметра.

Div($IntVariable, $Value)
=
$IntVariable = $IntVariable / $Value

Второй параметр может не использоваться, тогда вместо него будет установлена 2.

Div(1@)
=
1@ = 1@ / 2

(sys) ALLOC* - эта команда устанавливает адрес памяти для переменной. Должна использоваться только для переменных с ТЕКСТОВЫМИ именами. Для остальных адрес памяти устанавливается по их имени: переменная $40 всегда будет иметь ячейку памяти #40.

Alloc($MyVar, 40) - переменная $MyVar будет иметь адрес 40.

см. также 'alloc.txt'

* команды, обозначенные словом (sys), не отражаются в коде, а являются вспомогательными для компилятора.

SQR - эта команда вычисляет квадрат значения (вторую степень) переменной, переданной в качестве параметра.

sqr($var)
=
$var *= $var

Тип переменной должен быть определен.

RANDOM - эта функция возвращает случайное число в интервале, указанном параметрами.

$rnd = random(1, $high)

Данную функцию можно использовать как для типа Integer, так и для типа Float. Выбор опкода будет зависеть от типа объявленной переменной, в которую записывается случайное значение ($rnd).


HEX..END

Sanny Builder поддерживает прямую запись данных в выходной файл. Все значения внутри этой конструкции записываются без какой-либо обработки и проверки.

Используйте эту возможность только в том случае, если вы знаете, что делаете. Любые ошибки могут повредить файл и его невозможно будет прочитать в игре или в скриптовом редакторе.

Синтаксис:
hex
<любый шестнадцатиричные значения>
end

Пример:

hex
04 00 02 0800 04 01
end

Эта последовательность байтов представляет собой скомпилированный опкод 0004: $2 = 1, поэтому игра корректно прочитает его и установит значение переменной $2 равным 1.

Вы должны использовать 2 цифры в шестнадцатиричном формате для каждого байта, который собираетесь записать в файл. Все пробелы игнорируются. Компилятор рассматривает две подряд идущих цифры с пробелом между ними как одиночный байт. К одиночной цифре (0..F) слева дописывается 0. Например, A B C будет записано как число 0xAB0C.

В конструкции HEX..END также можно использовать строки, метки, глобальные переменные, имена моделей. Они компилируются без предшествующего байта, указывающего на тип данных.

:get_offset
hex
04 00 02 $PLAYER_CHAR 01 @get_offset
end

Это точная копия опкода 0004: $PLAYER_CHAR = @get_offset

Строки компилируются как последовательность символов, заключенных между двойными кавычками.

hex
"This is a string"
end

В строках допускается использование следующих управляющих символов:

  • \0 - пустой символ - 0
  • \b - возврат на шаг - 8
  • \t - табуляция - 9
  • \n - перевод строки - 10
  • \r - возврат каретки - 13
  • \x<nn> - любой байт - nn
  • \<char> - любой символ - <char>

Пример:

hex
"\0\b\t\n\r\xDD"
end

Это даст следующую последовательность байтов: 00 08 09 0A 0D DD.

В настоящее время несколько подряд идущих пробелов в строке конвертируются в один пробел. Например, строка "This is a string" будет сконвертирована в "This is a string". Используйте символ \ чтобы добавить дополнительные пробелы в строку: "This \ \ \ is \ a \ \ \ \ string".

Также вы можете использовать тип данных aDMA, чтобы записать число в выходной файл. Число после знака & может быть как положительным, так и отрицательным, в десятичном формате или шестнадцатиричном.

hex
&1000 &-0xA33500
end

Этот пример даст следующую последовательность байтов: E8 03 00 CB 5C FF.


Директивы

Препроцессорные директивы - это специальные слова, которые указывают компилятору на необходимое поведение в процессе компиляции. Они обозначаются символом $, а также заключены в фигурные скобки {}.

Список доступных директив:

  1. $VERSION
  2. $VERSION_RESTORE
  3. $INCLUDE
  4. $EXTERNAL
  5. $CLEO
  6. $NOSOURCE
  7. $OPCODE

$VERSION

Эта директива устарела, начиная с версии 3.1.0

Данная директива указывает компилятору, какую версию опкодов необходимо использовать из INI-файла (SASCM.INI, VICESCM.INI и т.д.). В настоящий момент INI-файлы содержат только одну версию опкодов, поэтому данная директива может не использоваться. Синтаксис:

$VERSION x.y.zzzz

x - код игры.
1 - gta3;
2 - vc;
3 - sa;
4 - lcs;
5 - vcs;

y - вид порядка следования параметров в опкоде.
0 - оригинальный (параметры в INI идут последовательно 0, 1, 2 и т.д.)
1 - неоригинальный (параметры в INI идут непоследовательно 2, 0, 1, и т.д.)

zzzz - код версии файла

По умолчанию компилятор использует версию:

<текущий режим редактирования>.1.0000

$VERSION_RESTORE

Эта директива устарела, начиная с версии 3.1.0

Данная директива восстанавливает прежнюю версию, которая была до использования директивы $VERSION. В настоящий момент INI-файлы содержат только одну версию опкодов, поэтому данная директива может не использоваться.

Основная идея состоит в том, чтобы позволить одновременно компилировать куски кода, написанные на разных версиях опкодов, путем заключения их в данные директивы.

{$VERSION 3.1.0001}

... <код, написанный на версии 0001> ....

{$VERSION 3.1.0000}
... <код, написанный на версии 0000> ....
{$VERSION_RESTORE} // восстанавливаем версию 0001

... <код, написанный на версии 0001> ....

$INCLUDE

Эта директива позволяет подключать внешние текстовые файлы к исходнику. Когда компилятор находит указанную директиву, он открывает файл по адресу, переданному в качестве параметра директивы и продолжает компиляцию того кода, который записан во внешнем файле. Когда компилятор достигает конца данного файла, он возвращается обратно в предыдущий файл.

Синтаксис:

{$INCLUDE file_path}

или

{$I file_path}

Например,

{$I loadwav.txt}

или

{$I C:\dev\getarrayindex.txt}

Если в имени файла указан относительный путь, компилятор ищет файлы в следующем порядке:

1. папка, где находится файл, содержащий данную директиву*
2. Sanny Builder\data\<game>
3. корневая папка Sanny Builder
4. корневая папка игры

Если ни в одной из указанных папок не содержится такой файл, компилятор сообщит об ошибке.

Вы можете использовать данную директиву неограниченное число раз. Вкладываемые файлы могут также содержать в себе данную директиву.

*Начиная с версии v3.1.1 это стало строгим правилом. Все пути, которые указаны в директиве $INCLUDE, явлются относительными по отношению к текущему обрабатываемому файлу.

$EXTERNAL

Данная директива заставляет скомпилировать файл как внешний скрипт. Это означает, что получившийся файл будет без заголовка и с локальными метками, т.е. полным аналогом scm-файлов из файла script.img. Использование данной директивы подразумевает, что в скрипте будет только один поток (также без миссий и внешних скриптов).
Аналогом использования данной директивы является опция SKIP_SCM_HEADER. Данную опцию также можно переключить на главной панели инструментов.
Вместо $EXTERNAL можно использовать короткий вариант $E.

Синтаксис:

{$EXTERNAL}

или

{$E}

$CLEO

Данная директива является аналогом директивы $E, однако полученный файл автоматически копируется в директорию ‘игра\CLEO’, и получает расширение, указанное в директиве.

Синтаксис:

{$CLEO <расширение файла>}

Например,

{$CLEO .cm}

или

{$CLEO} // файл получит расширение по умолчанию - .cs

Таким образом, данная директива является идеальным решением для написания CLEO-скриптов

$NOSOURCE

Эта директива запрещает компилятору добавлять в тело скрипта его исходный код. По умолчанию, при включенной опции Добавлять доп. информацию в SCM, Sanny Builder добавляет исходный код в тело скрипта (только при наличии директивы $EXTERNAL или $CLEO). Данная директива изменяет поведение компилятора, не позволяя включать исходник в скомпилированный файл.

Синтаксис:

{$NOSOURCE}

$OPCODE

Эта директива позволяет добавить новый опкод напрямую через скрипт. Обычно описания всех опкодов содержатся в специальном файле, по одному для каждой игры. Но иногда необходимо добавить новый опкод для работы в текущем скрипте. Директива $OPCODE делает это возможным без редактирования оригинального файла с опкодами.

Директива принимает описание опкода в том же синтаксисе, что и файл INI.

Например,

{$OPCODE 0CCC=1,my_new_opcode %1d%}

Директива также принимает имя файла в качестве параметра. Этот файл должен содержать в себе только описания опкодов, которые будут загружены компилятором. Если не указан глобальный путь к файлу, компилятор ищет его по тем же правилам, что и в директиве $INCLUDE.

Например,

{$OPCODE additional_opcodes.ini}

Если директива использована без какого-либо параметра, это ведет к перезагрузке оригинального списка опкодов и отмене всех сделанных изменений.

Например,

{$OPCODE}

Вместо $OPCODE можно использовать короткий вариант $O.


Sanny Builder Help: Редактор

  • Опции программы
    • Общие настройки
    • Форматирование
    • Редактор
    • Подсветка
    • Горячие клавиши
  • Возможности
  • Консоль
  • Горячие клавиши
  • Поиск опкодов (Opcode Search Tool)


Опции программы

Опции программы вызываются нажатием кнопки F10. Вы увидите окно, поделенное на 4 части, каждая из которых содержит определенный вид настроек. По умолчанию открывается страница общих настроек.


Общие настройки

Данная страница содержит в основном настройки (де)компилятора.

Работа программы требует использования определенных файлов игры, поэтому вы должны указать корректный путь к папке, куда была установлена игра. Вы можете ввести адрес вручную или выбрать папку через диалог, появляющийся при нажатии кнопки.

Для корректной работы программы ей требуется INI-файл, со списком опкодов. В данном поле вы можете указать путь к данному файлу. При нажатии на кнопку появится диалог выбора файла.

В правой части находится список доступных языков для интерфейса программы. Сами переводы находится в папке lang. Для установки нового языка интерфейса, выберите его в списке.

Информация о создании новых переводов содержится в файле How to translate.txt в папке lang.

Для удобства работы со скриптами, вы можете ассоциировать их с Sanny Builder’ом.

Когда галочка выбрана, в реестр Windows вносятся необходимые изменения, и при клике по файлу с указанным расширением, он будет автоматически открываться в SB. Для того чтобы прекратить ассоциацию, снимите галочку.

Общий список опций (де)компилятора. В левом столбце находятся опции, сопутствующие процессу работы программы, в правом - конкретные варианты (де)компиляции.

Перезапись выходного файла

При выборе данной опции декомпилятор будет записывать данные в выходной файл, независимо от того, существует он уже или нет. Если опция не выбрана, то при условии существования выходного текстового с таким именем, декомпилятор не будет его перезаписывать, а создаст новый файл, добавив к нему индекс (например, main[0].txt).

Показывать прогресс

При выборе данной опции в процессе работы (де)компилятора в статусбаре будет отображаться текущий прогресс. В противном случае в статусбаре будут слова «Пожалуйста ждите…». Показ прогресса немного замедляет процесс (де)компиляции.

Показывать отчет

При выборе данной опции Sanny Builder будет показывать различную информацию об итогах проделанной декомпиляции либо компиляции.

Показывать предупреждение

Данная опция имеет значение только при компиляции скриптов San Andreas. Если игра запущена ко время компиляции, то файл script.img, содержащий часть скриптов не сможет быть перезаписан, поскольку игра использует данный файл. Компилятор покажет об этом предупреждение. Вы можете отключить его показ, выбрав данную опцию.

Ручной выбор IMG-файла

При декомпиляции программа ищет файл script.img, содержащий часть игровых скриптов. Если файл не будет найден в одной папке с .scm-файлом или в папке игры, то будет показана ошибка. Однако при выборе данной опции вы сможете указать IMG-файл вручную.

Быстрая загрузка игры

Sanny Builder способен пропускать начальные заставки при запуске San Andreas (F8). Если данная возможность вызывает ошибку в вашей версии игры, отключите данную опцию.

Проверка условий

Данная опция имеет 2 значения. При декомпиляции с включенной данной опцией программа будет заменять количество условий в опкоде IF на слова AND и OR. При компиляции программа будет способна компилировать конструкции IF..END, а также определять параметр для опкода IF в условиях со словами AND и OR.

Проверка переменных

Количество используемых глобальных и локальных переменных имеет свои лимиты. При включении данной опции компилятор будет проверять правильность их использования.

Использовать опкоды

Данная опция превращает декомпилятор Sanny Builder из высокоуровневого в низкоуровневый и наоборот. При ее выключении декомпилятор будет использовать доступные классы и кейворды, заменяя ими опкоды. Также не будут записываться опкоды для некоторых простых математических выражений. При включении данной опции все опкоды будут записываться в исходник.

Заменять номера миссий

При включении данной опции декомпилятор будет заменять номера миссий в опкоде start_mission 0 на ее имя. Например, start_mission INITIAL. Имя миссии определяется по имени метки в заголовке файла. Его также можно использовать для быстрого перехода к телу миссии.

Вставлять оригинальные имена миссий

Когда данная опция включена, декомпилятор добавляет заранее определенные имена миссий как комментарии к опкоду start_mission, а также к строке DEFINE MISSION в заголовке файла.

Добавлять дополнительную информацию в SCM.

При включении данной опции компилятор будет записывать определенную информацию в конец файла main.scm. Эта информация будет потом использоваться при декомпиляции файла для максимального соответствия оригинальному скомпилированному файлу. В конец main.scm записываются позиции конструкций hex..end, имена использованных глобальных переменных и т. п. Обратите внимание, что файл, скомпилированный таким образом нельзя будет декомпилировать в старых версиях SB (кроме случая включения опции ignore_unknown).


Форматирование

На данной вкладке вы можете настроить имена исходника, форматы меток, регистры идентификаторов.

Здесь вы можете выбрать как будут называться файлы, получаемые после (де)компиляции. В верхнем поле вы указываете путь и имя текстового файла, в который записывается содержимое декомпилируемого файла. В нижних двух – пути и имена бинарных файлов SCM и IMG, содержащих скомпилированные скрипты. Все поля имеют общий синтаксис. Специальными словами обозначатся часть имени декомпилируемого SCM-файла (для верхнего поля), либо исходного текстового файла (для нижних двух полей).

$dir – путь к указанному файлу
$name – имя файла
$ext – его расширение
$game – папка игры // game path
$sb – папка Sanny Builder // Sanny Builder path

Например, если вы декомпилируете файл C:\MyDir\main.scm, то

$dir = C:\MyDir;
$name = main
$ext - .scm

Тогда при задании маски $dir\$name.txt декомпилированный исходник получит имя C:\MyDir\main.txt (это будет отображаться в строке под одним из 3-х полей.

В этой части страницы вы можете выбрать как будут именоваться метки при декомпиляции scm-файла.

Смещение от начала файла: все метки будут иметь числовое имя, например @12345. Цифра после знака @ будет означать позицию данной метки в декомпилируемом файле.

Имя потока+смещение от его начала: все метки будут иметь имя потока, в котором они находятся (определяется по опкоду name_thread) плюс дополнительно смещение от начала потока. Например, @MAIN_12

Имя потока+смещение от начала файла: данный вариант похож на предыдущий, только после имени потока в метке будет записано ее позиция в файле (как в первом случае). Например, @HELP_34567

Если вы хотите, чтобы смещения в именах меток были указаны в 16-чном формате, поставьте галочку в соответствующем поле внизу. По умолчанию смещения записываются в десятеричном формате.

Здесь вы можете выбрать будет ли декомпилятор использовать имена отдельных элементов скрипта, определенные пользователем в соответствующих файлах.

Имена меток содержатся в файле CustomLabels.ini в папке data\<игра>. Файл представляет собой список имен меток и их смещений от начала файла. Если данная галочка поставлена, декомпилятор, в случае соответствия позиции метки в файле одной из позиций в данном списке, назовет метку как указано в списке. Содержимое файла CustomLabels.ini содержит смещения для оригинального файла main.scm версии 1.0

Имена переменных содержатся в файле CustomVariables.ini для каждой игры. Файл представляет собой список оригинальных числовых имен переменных (DMA) и их текстовые эквиваленты. При включении данной опции декомпилятор будет называть переменные указанными именами.

Имена массивов содержатся в файле CustomArrays.ini. Формат файла следующий: первым числом на строке стоит оригинальное имя переменной – начало массива, затем через пробел количество элементов в массиве – размер, затем текстовое имя. Данная опция предназначена для того, чтобы декомпилятор заменял некоторые идущие подряд глобальные переменные на индексированные переменные.

Эта опция имеет 2 назначения. Декомпилятор, используя данную опцию, будет именовать глобальные переменные, метки, массивы в указанном регистре букв. Компилятор будет записывать строковые значения в SCM также в указанном регистре.


Редактор

На данной странице вы можете изменить настройки IDE.

Цвета

Следующие опции позволяют установить цвета различных элементов окна редактора.

Активная строка - цвет строки, на которой стоит курсор

Отступ - цвет левого края редактора

Поле редактора - фон текста в редакторе

Глубина просмотра кода

Значение глубины просмотра используется при построении списка констант, меток и переменных после нажатия комбинации Ctrl + [space]. Это значение говорит редактору, как много строк кода нужно просмотреть в обе стороны от текущей строки. Если вы поставите число 0, программа будет искать указанные элементы по всему скрипту.

Если опция 'Автосписок' выбрана, список доступных меток, моделей и переменных будет появляться автоматически после набора символа @, $, # и т.д.

Общие опции

Показывать главную панель – показать/спрятать панель с кнопками в главном окне редактора

Показывать информацию об опкодах – при выборе данной опции редактор будет отображать в статусбаре различную информацию: число параметров опкода, имя опкода в классе, номер модели, тип переменной и т. д.

Показывать номера строк – в левом отступе появятся номера строк

Показывать границу отступа – при выборе этой опции левый отступ будет ограничен с правой стороны. Отключите данную опцию, если вы хотите визуально увеличить пространство редактора

Открывать при запуске последний файл – при выборе данной опции программа при запуске будет открывать последний закрытый файл, если таковой имеется

Открывать все закрытые файлы – вы можете открывать разом все закрытые файлы при запуске. Данная опция может быть выбрана только при включенной опции Открывать при запуске последний файл

Подтверждать выход – при закрытии программы вы должны будете подтвердить выход. Полезно для предупреждения случайного закрытия программы

Шрифт

Здесь вы можете выбрать шрифт и его настройки для редактора. Sanny Builder поддерживает только пропорциональные шрифты. Строка AaBbCcDd отражает текущие настройки


Подсветка

На данной вкладке вы можете выбрать варианты подсветки синтаксиса в окне редактора.
Каждый элемент кода имеет 3 свойства: Цвет, Фон, Стиль.

Доступны 3 элемента стиля: B – полужирный, I – курсив, U – подчеркнутый.

Выбранный вариант подсветки используется также при сохранении кода в формат RTF или HTML.

Элементы кода:

Комментарии – текст, находящийся за двойным слешем // либо между фигурными скобками {}.

Метки – идентификаторы, начинающиеся с символа @.

Переменные - – идентификаторы, начинающиеся с символа $ (глобальные), а также заканчивающиеся символом @ (локальные). Также к переменным приравнивается тип aDMA (начинается c &) и массивы.

Кейворды – специальные слова, записанные в файле keywords.ini (общий для всех) и keywords.txt (свой для каждой игры).

Числа – целые и дробные числа.

Строки – текст между символами “…” и ‘…’.

Модели - идентификаторы, начинающиеся с символа #.

Классы – часть класса, идентификатор стоящий перед знаком точки.

Команды - часть класса, идентификатор стоящий после знака точки.

Директивы – идентификаторы, заключенные в фигурные скобки и начинающиеся с $.


Горячие клавиши

Некоторые горячие клавиши могут быть изменены для вашего удобства. Вы можете установить новые сочетания кнопок для вызова инструментов, действий редактора и некоторых других возможностей.


Возможности

Sanny Builder как среда программирования предоставляет пользователю следующие возможности:

Подсветка синтаксиса

Sanny Builder подсвечивает код разными цветами, чтобы облегчить работу с ним. Настройки подсветки могут быть изменены в опциях программы.

Быстрый переход по тексту

Для этого есть два способа:

  1. Установить на нужной строке закладку комбинацией клавиш Ctrl + Shift + <0..9>, а затем быстро перейти к этой строке комбинацией Ctrl + <0..9>. Удалить все закладки можно через меню Правка -> Удалить закладки.
  2. Через опцию 'Перейти...'. Она вызывается комбинацией Ctrl+G. Введите порядковый номер нужной строки, и редактор быстро переместит Вас к ней.

Моментальный поиск

Моментальный поиск позволяет находить слово или метку прямо в редакторе без вызова диалога Поиска.

Чтобы найти в тексте другое вхождение слова под курсором, нажмите Ctrl + Num6 чтобы искать его ниже по тексту или Ctrl + Num4 чтобы искать выше. Курсор немедленно переместится к строке, где есть такое слово. Продолжайте нажимать Ctrl + Num4/Num6 чтобы найти другие строки с нужным словом.

Чтобы перейти к строке, обозначенной меткой (например, :MyLabel), поместите курсор на ссылку на эту метку (@MyLabel) и нажмите Ctrl + Num2. Редактор немедленно переместит курсор к строке с искомой меткой.

Если позиция курсора не изменилась, это означает, что моментальный поиск не смог найти нужное слово в тексте.

Перед изменением позиции курсора моментальный поиск запоминает текущую позицию, и если вы решили вернуться на предыдущее место, нажмите Ctrl + Num8.

Показ различной информации о текущем опкоде

При включенной опции Показывать информацию об опкодах Sanny Builder показывает количество параметров для опкода и, если курсор находится над именем модели, цифрового значения модели (только для моделей из IDE-файлов и только когда определена директория игры).

Конвертирование исходников SA Mission Builder

В текущей версии поддерживается формат SAMB 0.33. Для конвертации откройте файл в Sanny Builder и выберите пункт меню "Сервис->Конвертация->MB->SB". Также можно конвертировать отдельный, выделенный участок кода. Внимание: при конвертировании используется файл MB.ini, в котором содержатся текстовые имена переменных и значения адресов памяти. Если Вы добавляли свои переменные в файл variables.ini в SAMB 0.33, используйте его (переименовав в файл MB.ini).

Поиск нужного опкода

Используйте программу поиска опкодов, чтобы найти нужный опкод.

Изменение координат и угла разворота игрока

Нажмите Ctrl+Alt+1, когда запущена игра, и появится окно менеджера. Здесь вы можете установить новые координаты и угол разворота и скопировать текущие.
В верхнем поле ввода вы можете указать сразу 3 координаты, разделив их пробелом или ",".
Также вы можете быстро вставить координаты игрока в текст комбинацией Ctrl+Shift+C. Вставка угла разворота (z_angle) в текст производится нажатием Ctrl+Shift+E

Поддержка макросов

Иногда скриптеру необходимо писать одни и те же строки кода, например для загрузки моделей. Чтобы сократить время написания такого кода, вы можете вызвать специальный макрос, который вставит в редактор нужный код. Для этого напишите ключевое слово, соответствующее этому макросу, например load и нажмите F2. В редакторе появится код

#.Load

while not #.Available

  wait 0

end
Вам останется только написать нужное имя модели в качестве параметра.

Список используемых макросов содержится в файле 'macroes.txt'. В нем используется следующий синтаксис:
Имя макроса (ключевое слово) пишется отдельной строкой. После имени должен стоять знак равно (=). После знака = можно добавить краткое описание макроса. Поддерживаются только однострочные описания. После строки с именем записывается содержимое макроса, каждая строка обозначается символом =. Место, куда должен быть помещен курсор после вставки обозначается символом |.

Также можно добавить свой макрос в файл 'macroes.txt' прямо из редактора. Для этого достаточно выделить нужный кусок текста и выбрать меню "Сервис->Добавить макрос". В появившемся диалоговом окне вы должны ввести имя нового макроса (вместе или без описания) и нажать кнопку OK. Новый макрос будет сразу же готов к использованию.

В ходе работы можно вызвать список макросов комбинацией Ctrl+J.

Также существует возможность запоминать последовательность нажатия любых клавиш и потом вопроизводить ее в том же порядке.

Например, у вас есть код:

$Actor = Actor.Create(CivMale, #MALE01, 100.0, 100.0, 10.0)
$ActorWithGun = Actor.Create(CivMale, #MALE01, 110.0, 100.0, 20.0)
$Gang01 = Actor.Create(CivMale, #MALE01, 120.0, 100.0, 30.0)
$Gang02 = Actor.Create(CivMale, #MALE01, 130.0, 100.0, 40.0)
$Killer = Actor.Create(CivMale, #MALE01, 140.0, 100.0, 50.0)
$ActorWithoutGun = Actor.Create(CivMale, #MALE01, 150.0, 100.0, 60.0)

Допустим, Вам нужно обменять имена актеров в кажой паре (поставить вместо $Actor $ActorWithGun, а вместо $ActorWithGun - $Actor и т.д.). Путем записи макроса можно сократить время написания такого кода.

Поставьте курсор на первую строку и нажмите Ctrl+M. С этого момента редактор запоминает все нажатия клавиш, так что будьте осторожны.
- Зажмите Ctrl и нажмите один раз стрелку вправо. Ctrl нужен так как строки разной длины.
- Теперь нажмите Shift+Home и Ctrl+Ins.
- Нажмите стрелку вниз. Вы должны оказаться на второй строке, при этом глобальная переменная будет в буфере обмена.
- Нажмите Ctrl+стрелка вправо и Shift+Ins.
- Нажмите Ctrl+стрелка влево, Shift+Home, Ctrl+Ins и кнопку Delete
- Нажмите стрелку вверх
- Нажмите Ctrl+Shift+стрелка вправо и Shift+Ins
- Нажмите кнопку Home.

Теперь первые две строки выглядят так:

$ActorWithGun = Actor.Create(CivMale, 100.0, 100.0, 10.0)
$Actor = Actor.Create(CivMale, 110.0, 100.0, 20.0)

и курсор стоит в начале первой строки. Теперь нажмите Ctrl+M. Макрос записан. Теперь вы можете воспроизводить нажатия клавиш комбинацией Ctrl+P. Установите курсор на 3-ю строку, нажмите Ctrl+P и имена актеров поменяются местами.

Во время записи макроса можно поставить/снять запись на паузу нажатием Ctrl+P.

Замена номеров миссий на их имена

Sanny Builder допускает использовать вместо номера миссии ее имя. Именем миссии явлется имя ее метки, которая определена в блоке DEFINE MISSION.

Например, у вас есть

DEFINE MISSION 10 AT @MYMISSION

Вы можете использовать вместо start_mission 10 команду start_mission MYMISSION.

В SB добавлена опция Заменять номера миссий. Когда она включена, декомпилятор автоматически заменяет все номера миссий в коде на их имена. Эта опция дает возможность безболезненно удалять миссии, не заботясь о переименовывании всех последующих номеров в коде.

Для дополнительного удобства в строке start_mission можно вызвать список имен миссий и их номеров нажатием Ctrl+[space].

Также можно использовать моментальный поиск для перехода к миссии на нее саму.

Изменение оригинальных названий миссий

При декомпиляции файла main.scm Sanny Builder дописывает к строке с миссией ее оригинальное название в качестве комментария. Начиная с версии 3.2.0 для каждого режима редактирования можно создавать собственные списки названий. Имена миссий содержатся в файле missions.txt, расположенном в папке data\<игра>. Если вам нужно декомпилировать main.scm с измененными миссиями, отредактируйте этот файл как вам нужно.

Многоязычный интерфейс

Sanny Builder обладает интерфейсом, переведенным на 15 языков. Переключить язык можно в опциях программы (F10). Информация по созданию своего перевода содержится в файле 'lang\How to translate.txt'.

Меню внешних приложений

Вы можете добавить в меню Инструменты до 9 внешних приложений и запускать по мере необходимости. Каждому приложению можно присвоить комбинацию горячих клавиш и ряд параметров, необходимых для запуска.

В качестве параметра запускаемого приложения может использоваться специальное слово: $SB_FileName. Оно обозначает имя текущего открытого файла и может быть передано во внешнее приложение.

Комментирование кода

Комментарии обозначаются в коде двойным слешем //. Все, что идет после данного знака до конца строки, игнорируется компилятором.

Для того чтобы закомментировать несколько строк сразу либо только часть строки (например в середине или начале) вы можете использовать блочные комментарии {}

0001: wait  {это игнорируется} 0 ms

Начиная с версии 3.06 Sanny Builder поддерживает C++-подобные комментарии /* */.

0001: wait  /* комментарий */ 0 ms

Также вы можете закомментировать несколько строк выделив их и нажав Ctrl+Q. Для раскоментирования выделите текст и нажмите Ctrl+Q еще раз.

Собственные имена для меток

Вы можете давать меткам собственные имена, которые не будут зависеть от опций декомпилятора. Перечень имен содержится в файле CustomLabels.ini (отдельный для каждой игры).

Формат записи следующий:
<смещение метки>=<имя>

Если декомпилятор встретит метку по данному смещению, он заменит ее на указанное имя.

Узнать адрес метки можно включив в опциях формат меток "Смещение от начала". После декомпиляции файла, число после слова Label и будет адресом метки.

Проверка обновлений

Sanny Builder может проверить, доступна ли новая версия программы. Чтобы использовать эту возможность, пройдите в меню "Справка->Проверить обновления...". Программа подключится к серверу обновлений и предложит скачать и установить обновление, если оно найдено. Sanny Builder может автоматически проверять наличие обновления при запуске, если вы включите соответствующую опцию в окне меню обновлений.


Режимы редактирования

Режим редактирования - это набор параметров, определяющих поведение Sanny Builder при работе со скриптами определенной игры. Суть в том, что в серии GTA нет двух игр с одинаковым форматом скриптов. Поэтому каждая игра требует особого подхода при редактировании скриптов. Это является основной причиной появления разных режимов работы Sanny Builder.

Режим редактирования включает (но не ограничен) следующие параметры:

  • Sanny Builder дизассемблирует скрипт особым образом
  • Sanny Builder может компилировать скрипты для выбранной игры
  • вы можете запускать игру из редактора и читать/менять координаты игрока

По умолчанию в редакторе настроено 7 различных режимов:

  • GTA III
  • GTA VC
  • GTA SA (для опкодов с измененным порядком следования параметров)
  • GTA LCS
  • GTA VCS
  • SA Mobile (для мобильной версии San Andreas)
  • GTA SA SCR (для оригинальных опкодов R* )

Вы можете добавлять собственные режимы редактирования путем изменения файла games.xml, расположенного в папке <SB>\data\.

Чтобы переключить режим редактирования на другой кликните в правом нижнем углу программы. Появится список доступных режимов. Выберите нужный и кликните по нему. Sanny Builder загрузит все требуемые файлы и вы можете начать работу.

Перед дизассемблированием или компиляцией скрипта, убедитесь что выбрали правильный режим редактирования, соответствующий скрипту. Даже если скрипт компилируется без ошибок, игра выдаст ошибку при попытке чтения скрипта другого формата.

Скомпилированный скрипт может содержать в себе информацию о том, для какой игры он был сделан. При попытке декомпиляции такого скрипта в другом режиме редактирования, Sanny Builder предложит вам автоматически перейти в правильный режим. Игнорирование этого предложения может вызвать ошибку при дизассемблировании, поскольку формат скрипта будет отличаться от ожидаемого.


Консоль

Назначение консоли в Sanny Builder’е – переключение особых опций программы (в первую очередь (де)компилятора). Консоль вызывается нажатием Ctrl + ~. В поле ввода внизу вы можете писать команды и параметры. После набора команды нажмите Enter. Результат работы будет отображаться в поле консоли.

Команды нечувствительны к регистру, поэтому вы можете набирать их в любом удобном регистре букв.

Список поддерживаемых команд:

help – при вводе команды help откроется окно справки о командах консоли.

clear – очищает поле консоли

list – команда list выводит в консоли список всех поддерживаемых команд.

Дополнительный параметр:
list options – при наборе слов list options в консоли появится список всех возможных опций для переключения. См. команду toggle.

toggle – основная команда для переключения опций программы.

Дополнительный параметр:
toggle <имя опции> [on/off]
Список опций может меняться в разных версиях. Для получения всех возможных опций наберите list options.

После имени опции может стоять либо слово ON (тогда опция будет включена), либо слово OFF (опция будет выключена), либо ничего (тогда опция будет переключена на другое состояние – с ON на OFF или наоборот).

Внимание! Перед использованием особых опций нужно включить режим debug_mode командой toggle debug_mode.

toggle CODE_OFFSETS | – при включении этой опции декомпилятор будет печатать оффсеты для каждого опкода.
toggle VAR_COUNTER | – при включении данной опции после компиляции исходника в поле консоли будет выведен список глобальных переменных, которые использовались в коде только раз. Очень полезно при поиске ненужных переменных.
toggle IGNORE_UNKNOWN | при включении это опции декомпилятор будет пропускать весь неизвестный ему код. Это поможет декомпилировать поврежденные или защищенные scm-файлы.
toggle CONSTANT_INDEXES | декомпилятор будет записывать идущие подряд глобальные переменные как массив, используя числовые константы. Например
 |  | было | стало
 |  | $10 | $10[0]
 |  | $11 | $10[1]
 |  | $12 | $10[2]
 | По умолчанию данная опция включена.
toggle SKIP_SCM_HEADER | - будет пропущено чтение заголовка scm-файла. Это поможет декомпилировать внешние скрипты из файла script.img - компилятор не будет писать заголовок для компилируемого файла. Аналогом использования данной опции является директива $EXTERNAL.

Эти опции могут быть переключены через меню на главной панели.

Вы также можете устанавливать все опции разом при запуске программы. Для этого используется ключ \debug. Параметром ключа является последовательность символов '0' и '1' (без кавычек). Каждый символ отвечает за значение опции под соответствующим номером.

Например, \debug=11000

Первая цифра 1 включит опцию code offsets, вторая - включит ignore_unknown. Нули выключат все остальные опции.

# | Sanny Builder Option | # | Sanny Builder Option
1 | toggle code offsets | 16 |
2 | toggle ignore_unknown | 17 |
3 | toggle var_counter | 18 |
4 | toggle constant_indexes | 19 |
5 | toggle skip_scm_header | 20 |
6 |  | 22 |
7 |  | 23 |
8 |  | 24 |
9 |  | 25 |
10 |  | 26 |
11 |  | 27 |
12 |  | 28 |
13 |  | 29 |
14 |  | 30 |
15 |  | 31 |


Горячие клавиши

Sanny Builder поддерживает стандартные сочетания клавиш для операций с файлами и текстом (Ctrl+N, Ctrl+Z, и т.д.) и отдельные сочетания клавиш для работы со скриптами. Некоторые из них могут быть изменены в опциях.

Меню

F5 | открыть файл как скрипт и декомпилировать его
F6 | компилировать текст в скриптовый файл
F7 | компилировать текст в скрипт и скопировать получившийся файл в директорию скриптов для выбранной игры
F8 | запустить выбранную игру
F10 | открыть окно опций
F12 | открыть файл справки (этот файл)

Текст

TAB , Shift+TAB | двигать выделенный блок текста влево/вправо
Ctrl + Alt + A / D | двигать выделенный блок текста влево/вправо (на один символ)
Ctrl + Alt + B / N / M | различные режимы выделения текста: Обычный, По столбцам (аналог - выделение с зажатым Alt), По строкам
Ctrl + Shift + U / L | перевод слова в верхний/нижний регистр
Ctrl + Num+ | увеличить размер шрифта в редакторе
Ctrl + Num- | уменьшить размер шрифта в редакторе
Ctrl + T | удалить слово
Ctrl + Y | удалить строку
Ctrl + Shift + Y | очистить строку
Ctrl + Q | закомментировать / раскомментировать строку

Курсор

Ctrl + Shift + B | перемещение между скобками: {}, (), <>, []
Ctrl + Shift + Num8 / Num2 | прокрутить страницу на одну строку вверх/вниз
Ctrl + Scroll Up / Down | страница вверх/вниз
Ctrl + Shift + 0..9 | добавить закладку
Ctrl + 0..9 | перейти на закладку
Ctrl + G | переход к строке с номером
Ctrl + Num4 / Num6 | искать слово под курсором ниже/выше в тексте
Ctrl + Num2 | переход к метке под курсором
Ctrl + Num8 | вернуть курсор на предыдущую позицию
Ctrl + Enter | открыть файл по имени под курсором (см. очередность открытия относительных путей)

Код

Ctrl + [space] | показать список классов/свойств/моделей/меток/переменных/миссий
Ctrl + Shift + [space] | показать подсказку для текущей команды класса
Ctrl + Shift + C | вставить текущие координаты игрока
Ctrl + Shift + E | вставить текущий угол поворота игрока
F1 | искать опкод с данным словом (без учета '_' и '.')
Ctrl + F1 | искать опкод с данным словом (с учетом '_' и '.')
F2 | использовать макрос
Ctrl + J вызвать список макросов
Ctrl + M запись последовательности нажатия клавиш / остановка записи
Ctrl + P воспроизведение записанной последовательности / пауза во время записи
Ctrl + H | конвертировать число под курсором из 10-чной системы счисления в 16-чную и наоборот
Ctrl + Alt + H | конвертировать имя модели под курсором в ID и наоборот

Разное

Ctrl + ~ открыть консоль
Alt + S | (когда активен список моделей) - пересортировать список


Поиск опкодов (Opcode Search Tool)

Вы можете вызвать программу OST нажатием Ctrl+Alt+2 или через меню
Сервис->Инструменты->Поиск опкодов

Чтобы найти нужный опкод, впишите в верхнем поле слова, соответствующие ему, например 'actor car' (без кавычек). В списке останутся команды, содержащие эти слова. Вписывайте уточняющие слова, пока нужный опкод не будет найден. При поиске можно пользоваться специальными операторами (подробнее о них ниже).

Также программа учитывает кол-во введенных одинаковых слов и ищет их в необходимом количестве. Т.е, если вы напишете три слова 'car', то программа будет искать опкоды, в которых именно три слова car.

Вы можете регулировать задержку перед началом поиска. Если вы хотите найти длинное слово, например 'weapon', то лишний отсев, который происходит, пока вы пишете слово, может быть нежелателен. Чтобы увеличить или уменьшить задержку, откройте настроечный файл settings.ini и измените значение параметра delay на нужное. Единица измерения - миллисекунда. По умолчанию задержка - 300 мс.

Есть также еще один вариант. Измените значение параметра extra_search на 1, и теперь, если SCROLL LOCK будет включен, то поиск осуществляться не будет. Напишите нужное вам выражение, отключите SCROLL LOCK, и поиск будет осуществлен.

Если при открытии окна поиска в редакторе был выделен участок строки, он будет автоматически вставлен в строку поиска.

Копирование:

После того, как вы нашли нужный вам опкод, выделите его в списке и нажмите ENTER. Опкод будет записан в буфер. Если вы хотите добавить к нему еще один опкод, нажмите SHIFT+ENTER. Тогда в буфере обмена будет уже два ваших опкода.
F2 - скопировать весь список целиком.

Горячие клавиши:

ENTER | по выделенному опкоду - скопировать в буфер
SHIFT + ENTER | по выделенному опкоду - добавить его к содержимому буфера
SCROLL LOCK | (при параметре extra_search=1) включить/отключить поиск
F1 | вызвать справку по поиску
F2 | скопировать все опкоды в списке в буфер
F3 | сортировка по опкодам
F4 | сортировка по словам
F11 | очистить строку поиска, показать все опкоды
ESC | выход

Операторы поиска:

ЛОГИЧЕСКИЕ ОПЕРАТОРЫ
Оператор И (AND)

В программе эту функцию выполняет одиночный пробел между словами.

Пример: @ player

Будут показаны опкоды, где встречаются И символ @, И слово player

Оператор ИЛИ (OR)

В программе эту функцию выполняет символ | между словами.

Пример: @ | player

Будут показаны опкоды, где встречаются ИЛИ символ @, ИЛИ слово player

Если поставить | первым элементом, программа будет связывать все последующие слова оператором OR.

Пример: | actor player car

Будут показаны опкоды, где есть хотя бы одно из этих слов.

Оператор НЕТ (NOT)

Для всех случаев это два минуса перед исключаемым словом --

Пример: car --car2

Будут показаны опкоды, где ЕСТЬ слово car И НЕТ слова car2

Для слов и символов $ и @ можно использовать один минус. Это сделано, чтобы не перепутать исключение с поиском отрицательных чисел.

Пример: -10 -@ -car --3

Будут показаны опкоды, где ЕСТЬ число -10 И НЕТ символа @, слова car и цифры 3.

ДРУГИЕ ОПЕРАТОРЫ

^ | показать все условия в списке
^выражение | найти выражение в условных опкодах

Пример: ^car ==

Будут показаны условные опкоды, где есть слово car и знак ==

-^ исключить все условия из списка

Пример: player -^

Будут показаны все опкоды, где есть слово player, и этот опкод не является условием в IF.

-^выражение исключить условия, содержащие выражение

Пример: player -^actor

Будут показаны все опкоды, где есть слово player, исключая условные опкоды со словом actor.

% искать в заданном порядке

Пример: % @ == @

Будут показаны все опкоды, где эти символы идут в данном порядке


Документация по SCM

Скриптовые лимиты

Список опкодов (INI)

Структура файла

GTA SA

GTA VC

GTA LCS

Использовались материалы следующих авторов:
Alexander aka Alexander Koryakin, Barton Waterduck, Bigun, DeeZire, Opius, pdescobar, San'OK aka Alexander Golovnev, Seemann, VcSaJen, spaceeinstein, spinnie, Xieon, Wesser, http://www.lzfdownloads.de/


Sanny Builder | Help

Скриптовые лимиты
 | GTA III | Vice City | San Andreas | LCS
Размер майна | 131072 | 225512 | 200000
Размер одной миссии | 32768 | 35000 | 69000
Кол-во миссий | 120 | 120 | 200
Mission Cleanup List | 50 | 50 | 75
Кол-во моделей (2-й сегмент) | 200 | 220 | 395
Кол-во работающих потоков | 128 | 128 | 96
Локальные переменные | 16 + 2 timers | 16 + 2 timers | 32 + 2 timers 1024 total in missions | 96 + 2 timers
Кол-во вложенных gosub | 4 | 6 | 8
Text_Draw | 2 | 48 | 96
Jump Table Labels | - | - | 75
Общее число внешних скриптов | n/a | n/a | 82
Общее число активных внешних скриптов | n/a | n/a | 70
Парковки машин (014B:) | 160 | 185 | 500
Кол-во маркеров | 32 | 75 | 175
Кол-во пикапов | 336 | 336 | 620
Максимальный опкод | 0481 | 05a8 | 0a4e
Число сфер на экране | 16 | 16 | 16
Типы гаражей, сохраняющих машины | 16..18 | 16..18,24..32 | 16..18, 24..32, 39..45

Originally posted by CyQ on GTAForums.com


Список опкодов (INI)

Основной файл, благодаря которому осуществляется процесс компиляции и декомпиляции – INI-файл со списком опкодов. Для каждой игры существует свой собственный список. В Sanny Builder’е эти файлы находятся в папке data\<имя игры>:

data\gta3 : SCM.INI
data\vc : VCSCM.INI
data\sa : SASCM.INI
data\lcs : LCSSCM.INI
data\vcs : VCSSCM.INI

Все файлы имеют одинаковую структуру. В начале файла могут идти специальные параметры с информацией о данном INI-файле. Откройте SASCM.INI и посмотрите:

VERSION – в данной строке определяется версия INI-файла. См. директива $VERSION
PUBLISHER – информация о человеке, выпустившем данную версию файла.
DATE – дата последнего обновления.

При декомпиляции эти значения вставляются в начале исходного файла.

После этого идет перечень опкодов с указанием параметров.

Каждая строка имеет следующий формат:

xxxx=N, yyyy

где XXXX – номер опкода, N – число параметров, YYYY – описание опкода.

Не допускается редактирование первых 2х значений (опкод и число параметров). Описание опкода может меняться свободно.

Обратите внимание на специальные элементы описания, обозначенные символами %. Таким образом оформляется параметр опкода. Например:

0001=1,wait %1d% ms

Данная строка указывает декомпилятору, что при декомпиляции опкода 0001 следует написать слова wait и ms, а между ними единственный параметр опкода.

Цифра в параметре %1d% указывает на его порядковый номер. Дело в том, что в некоторых опкодах параметры могут идти не в том порядке, как они записаны в SCM. Делается это для удобства чтения исходного кода. Например:

0053=5,%5d% = create_player %1o% at %2d% %3d% %4d%

Обратите внимание, декомпилятор записывает пятый параметр опкода в самом начале. Если бы параметры шли в своем обычном порядке, опкод 0053 в исходнике выглядел бы как

0053: сreate_player #NULL at 2488.562 -1666.865 12.8757 $PLAYER_CHAR

Следует отметить, что данный порядок следования параметров характерен для gtama и SASCM.INI от PLPynton.

После порядкового номера в параметре стоит его тип. Он обозначается одной из следующих букв:

d = любое значение
p = метка
o = имя модели
g = gxt-ключ
x = внешний скрипт

В зависимости от типа параметра, декомпилятор ведет себя по-разному. Например, для параметров g он добавляет комментарий с содержимым gxt, для p он преобразует число в метку, для o – пишет соответствующее имя модели (как в 0053 - #null).

Внимание! Ни в коем случае нельзя менять порядок следования параметров в опкоде, поскольку это приведет к несовместимости исходных кодов у разных пользователей. Меняйте порядок следования параметров только если вы не собираетесь публиковать скрипт для других пользователей.

Вы можете свободно менять слова-описания между параметрами, а также типы параметров, если это требуется.

Если в файле содержатся несколько одинаковых опкодов, программа будет использовать тот, что идет позже.


Структура файла

Игровые скрипты заключены в файле main.scm. Данный файл представляет собой нетипизированный бинарный файл с определенной структурой. При декомпиляции получается исходный файл, строение которого выстроено в точности по данной структуре.

Файл main.scm состоит из следующих частей:
  1. заголовок
  2. «майн»
  3. миссии

В San Andreas’е часть игровых скриптов, однако, вынесена в отдельный файл script.img. Он состоит из набора небольших scm-файлов. Их отличие от главного main.scm заключается в отсутствии заголовка. При декомпиляции эти скрипты добавляются в конец исходника, составляя таким образом четвертую его часть.

Нас будет интересовать прежде всего строение текстового исходника, поскольку работа с бинарным, скомпилированным файлом прерогатива декомпилятора. Итак, какое строение должен иметь типичный исходник, чтобы быть успешно скомпилированным в рабочий main.scm.

Заголовок

В самом верху исходного файла вы можете увидеть заголовок. Он представляет собой набор полей, определяющих часть структуры заголовка. Каждое поле начинается со слова DEFINE.

Первой частью заголовка является сегмент (или блок) моделей. Он начинается со строки

DEFINE OBJECTS 389

Слово DEFINE указывает на то, что эта строка – часть заголовка. OBJECTS указывает на то, что мы определяем размер сегмента объектов, а точнее – число объектов, чьи названия будут указаны ниже. 389 – число этих объектов (число может отличаться в разных исходниках). Допустимые значения – положительные числа и ноль. Смотрите также Лимиты объектов.

После этой строки перечисляются имена объектов.

DEFINE OBJECT INFO // Object number -1

Слово OBJECT указывает компилятору, что данная строка содержит имя импортируемой модели. Особенностью данных моделей является то, что они не требуют загрузки при использовании, а обращение к ним в скрипте происходит не по их реальному ID, а по порядковому номеру, который указан в комментарии (-1). Например,

0213: $PICKUP_INFO_HOSPITAL = create_pickup #INFO type 3 at 2027.77 -1420.52 16.49

или

0213: $PICKUP_INFO_HOSPITAL = create_pickup -1 type 3 at 2027.77 -1420.52 16.49

INFO – имя DFF-модели из gta3.img или другого архива.

Самая первая модель в списке не используется игрой.

Обратите внимание, что данный сегмент заголовка опционален и не обязателен к указыванию. Если вы не укажете какие модели следует компилировать как импортируемые, компилятор сделает это за вас, когда будет обнаруживать использование имен моделей в скрипте, чьи имена не содержатся в IDE-файлах (модели из IDE-файлов можно использовать по их ID, не требуется указывать их в заголовке). См. также: Объекты.

Второй частью заголовка является сегмент миссий. Он начинается со строки

DEFINE MISSIONS 135

Здесь указывается, какое число миссий будет присутствовать в данном исходнике. Компилятор будет искать именно заданное число миссий и если их будет меньше или больше возникнет ошибка.

После указания общего числа миссий следует перечисление миссий:

DEFINE MISSION 0 AT @INITIAL // Initial 1

Разберем данную строку. После слова DEFINE стоит слово MISSION, указывающее что здесь определяется начало миссии. После него стоит порядковый номер миссии. Этот номер используется в опкоде start_mission. После слова AT вы должны указать метку миссии, с которой она начнется.

На этой строке может также стоять комментарий с названием миссии из оригинального main.scm. Вы можете отключить показ оригинальных имен миссий в опциях программы.

См. также:
Создание миссии. Часть 1
Создание миссии. Часть 2
Создание миссии. Часть 3
Создание миссии. Часть 4

Указанные выше части заголовка являются общими для всех игр, поддерживаемых Sanny Builder’ом. Следующие части заголовка указываются только для игры San Andreas.

DEFINE EXTERNAL_SCRIPTS 78 // Use -1 in order not to compile AAA script

В данной части заголовка определяются внешние скрипты. После слова EXTERNAL_SCRIPTS указывается общее число внешних скриптов. В исходном файле эти скрипты должны располагаться сразу после всех миссий. Как и в случае с последними, компилятор будет искать заданное количество скриптов.

Обратите внимание, что внешние скрипты имеют в своем составе особый скрипт с названием AAA. Содержимое этого скрипта заполняется компилятором и делается это исключительно с целью максимального соответствия оригинальным файлам игры. Если вы указываете число EXTERNAL_SCRIPTS как 0, скрипт AAA тем не менее будет скомпилирован. Для того чтобы не делать этого, укажите в качестве значения число -1. Тогда script.img вообще не будет создаваться.

Версия 3.0 позволяет также перезаписать скрипт AAA. Для этого создайте свой собственный скрипт и назовите его этим именем.

Определение внешнего скрипта происходит в строке

DEFINE SCRIPT PLAYER_PARACHUTE AT @PLCHUTE // 0

Здесь PLAYER_PARACHUTE – имя скрипта в файле script.img. @PLCHUTE – имя метки с которой начинает тело скрипта.

В комментарии указан порядковый номер скрипта, который используется в опкодах, например:

08A9: load_external_script 0

После сегмента внешних скриптов идут еще два блока, назначение которых неизвестно. Скорее всего игра не использует эти значения.

DEFINE UNKNOWN_EMPTY_SEGMENT 0

DEFINE UNKNOWN_THREADS_MEMORY 574

Если вы пользуетесь урезанным скриптом (stripped.txt) без миссий и скриптов, вы можете не указывать заголовок совсем.

Шаблон заголовка можно вызывать в редакторе, используя макрос headsa или headvc.

Майн

Сразу после заголовка идет основной блок скрипта, именуемый майном. Здесь находятся все потоки, которые создаются и работают во время игры. Начало майна обозначено комментарием //-------------MAIN---------------.

Майн состоит из набора отдельных потоков. Самым первым потоком, который автоматически запускает игра, является поток MAIN (начинается с опкода 03A4: name_thread 'MAIN'). Все остальные потоки активируются уже из данного потока опкодами 004F или 00D7 (обратите внимание, эти опкоды по сути одинаковы, только 004F еще дополнительно может передавать в создаваемый поток параметры). Замечание по поводу создания потоков из MAIN верно только для новой игры. При загрузке сейва игра уже сама восстанавливает ранее созданные потоки.

Потоки состоят из опкодов, выражений и меток. Также при компиляции в скрипте могут встречаться конструкции (VAR..END, CONST..END, FOR..END и т.д.) и директивы, которые служат исключительно для удобства работы с кодом. После компиляции эти конструкции так или иначе преобразуются в опкоды, выражения или метки.

Опкод – (OpCode - Operation Code - код операции) - число, обозначающее одну из инструкций для парсера скриптов игры и указывающее на определенную последовательность действий, которые необходимо выполнить с учетом переданных параметров.

Например, 0001 это код операции wait, которое указывает машине, что нужно приостановить выполнение потока на число миллисекунд, переданных как параметр этого опкода. Все опкоды хранятся в INI-файле.

Выражение – это опкод с математической или логической операцией. Например,

$var += 1
10 < 5@
&10 = 0

и т.д. Некоторые выражения могут писаться без указания номера опкода (как в примере выше). Логические выражения (условия) используются для проверки каких-либо значений.

Метка – это идентификатор, обозначающий позицию в скрипте. Имя метки должно быть уникальным. По своей сути это число, обозначающее смещение от начала майна или миссии до того места, где стоит метка. В коде она обозначается символом :

:MAIN_177

Сами по себе метки бесполезны, если их не используют. Под использованием метки понимается переход на нее в одном из специальных опкодов. Существуют два вида перехода на метку: условное и безусловное.
Безусловный переход осуществляется опкодами jump, gosub.

jump @MAIN_177

Обратите внимание, что имя метки для перехода обозначается символом @ в начале. При включении автоматического списка, редактор будет выводить список используемых меток в коде.
Когда игра достигнет этого опкода, она сразу перейдет на то место в скрипте, где стоит метка (:MAIN_177).

Отличительной особенностью команды gosub является то, что после перехода на метку игра может (и должна) вернуться обратно после того, как встретит команду return.

…
gosub @MAIN_177
$var += 1
…

:MAIN_177
$var = 1
return

Когда игра достигнет команды gosub, она сразу перейдет по указанной метке на команду $var = 1. После выполнения этой команды, она перейдет на команду return. Смысл ее заключается в «вернуться-на-то-место-где-был-последний-gosub». В нашем примере это будет команда $var += 1. Команды jump (или goto), gosub и return являются базовыми понятиями в любом языке программирования.

Условный переход в отличие от безусловного осуществляется только при определенном условии. Для этого используется опкод jump_if_false (jf). Он является составной частью любого условия в скриптах.

00D6: if
08AB: external_script 75 loaded
004D: jump_if_false @MAIN_4492
0913: run_external_script 75

В данном примере сначала проверяется загружен ли в память внешний скрипт 75. После опкода 08AB: состояние условия будет либо правдивым (True) либо ложным (False), в зависимости от того, загружен скрипт или нет.
Состояние условия определяет два различных поведения игры после проверки условия. Если условие было правдивым (т.е. скрипт был загружен) игра пропустит опкод jump_if_false. Следующим шагом, таким образом, станет опкод 0913.
Если условие было ложным (т.е. скрипт не был загружен) игра выполнит опкод jump_if_false и перейдет на метку @MAIN_4492.
Собственно из перевода слов jump_if_false видно, что это переход, если ложь.

См. также:
Условия , а также смотрите здесь
Переходы
Таблицы переходов

Майн заканчивается там, где начинаются миссии.

Миссии

Блок миссий начинается с метки нулевой миссии из заголовка (в оригинале :INITIAL). Обычно там стоит комментарий //-------------Mission 0---------------.

Особенностью миссий является то, что в игре может одновременно быть запущена только одна миссия. После команды start_mission игра полностью загружает тело миссии в отдельную область памяти, после чего начинает работать с ним как с обычным потоком из майна. Все сказанное по поводу опкодов, выражений и меток в майне действительно и для миссий. Миссия как и обычный поток заканчивается командой end_thread.

Все миссии в исходном файле должны идти в той же последовательности, что и в заголовке файла. Миссия должна идти одним блоком, не допускается вложение части одной миссии в тело другой.

Внешние скрипты

Игра San Andreas также использует внешние скрипты, которые вставляются в исходник сразу после всех миссий. Таким образом началом данного блока является конец блока миссий. Там должна стоять метка первого внешнего скрипта (если таковые используются). Обычно там стоит комментарий
//-------------External script 0 (PLAYER_PARACHUTE)---------------.

Внешний скрипт представляет собой обычный поток со своими опкодами, выражениями и метками. Этот поток загружается в отдельную область памяти.

См. также Внешние скрипты.


Документация по SCM: GTA SA

GTA SA

ID банд

ID погоды

Варианты изменения автомобиля

Взрывы

Иконки радара

Имена гаражей

Интерьеры

Номера клавиш

Номера оружия

Объекты

Одежда: ноги

Одежда: обувь, цепочки, часы

Одежда: очки, шляпы, специальные

Одежда: торс

Специальные актеры

Статистика ID

Стрижки

Татуировки

Типы зон

Типы пешеходов

Типы поездов

Части тела игрока

Эффекты частицы


GTA SA ID банд

ID банд

0237: set_gang 1 weapons_to 24 29 4

Gang0 Ballas
Gang1 Grove Street Families
Gang2 Los Santos Vagos
Gang3 San Fierro Rifa
Gang4 Da Nang Boys
Gang5 Mafia
Gang6 Mountain Cloud Triad
Gang7 Varrio Los Aztecas
Gang8 (unused)
Gang9 (unused)


GTA SA ID погоды

ID погоды

01b6: set_weather 1

0 | Extra Sunny | Los Santos
1 | Sunny | Los Santos
2 | Extra Sunny Smog | Los Santos
3 | Sunny Smog | Los Santos
4 | Cloudy | Los Santos
5 | Sunny | San Fierro
6 | Extra Sunny | San Fierro
7 | Cloudy | San Fierro
8 | Rainy | San Fierro
9 | Foggy | San Fierro
10 | Sunny | Las Venturas
11 | Extra Sunny | Las Venturas
12 | Cloudy | Las Venturas
13 | Extra Sunny | Countryside
14 | Sunny | Countryside
15 | Cloudy | Countryside
16 | Rainy | Countryside
17 | Extra Sunny | Desert
18 | Sunny | Desert
19 | Sandstorm | Desert
20 | Underwater |
21 | Extracolours 1 |
22 | Extracolours 2 |


GTA SA Варианты изменения автомобиля

Варианты изменения автомобиля

0506: set_vehicle_model #PONY next_variation 0 0

Большинство машин может иметь только одно изменение, поэтому 2-й и 3-й параметры должны быть одинаковыми. Однако некоторые машины могут иметь и два изменения.

Вариант -1 - модель по умолчанию, без изменений.
Варианты от 0 до 5 - возможные изменения. Если модель не поддерживает данный номер - будет установлена модель по умолчанию. Варианты больше 5 приведут к ошибке игры.

#MODEL_ID | ID | Changes | 0 | 1 | 2 | 3 | 4 | 5
#ambulan | 416 | Numbers: | 37 | 71 | x | x | x | x
#artict1 | 435 | Side Ads: | Cok-o-Pops | Munky Juice | Hinterland | Zip | RS Haul | Ranch
#artict2 | 450 | Contents: | Filled with gravel /coal /stone | x | x | x | x | x
#bagboxb | 607 | Contents: | Various distributions of loose baggage |  |  | x | x | x
#baggage | 485 | Rear Cargo Items: | Earmuffs | Small Case | Large Case | x | x | x
#barracks | 433 | Bed Covering: | Opaque Fabric | Camo Netting | x | x | x | x
#benson | 499 | Side Ads: | Shady Industries | LSD | The Uphill Gardener | Discount Furniture | x | x
#bf400 | 581 | Exhausts: Fairings (with Windshields): | Single Type1 | Single Type2 | Dual Type3 | Half-size | Full-size | x
#bfinject | 424 | Body: | Side Panels | x | x | x | x | x
#bloodra | 504 | Numbers/ Roof Color: | 328/ White | 464/ Check | 172/ Check | 100/ White | 284/ White | 505/ Check
#bobcat | 422 | Bed Items: | Spare Tire | Sprunk Cans |  |  |  |
#burrito | 482 | Roof Items: | Roof Lights + Spoiler | x | x | x | x | x
#caddy | 457 | Rear Cargo Driver Side: Rear Cargo Pass Side: | Golfbag1 | Satchel1 | Golfbag2 | Satchel2 | Golfbag3 | Golfbag4
#camper | 483 |  | Open Curtains & Second Bench Seat | Open Roof Vent Closed Curtains Bed in Back Peace Sign | x | x | x | x
#cheetah | 415 | Side Mirrors: | Single, Placed High | Dual, Placed Normally | x | x | x | x
#coach | 437 | Name on Side: | Big O Tours | Bikini Line | x | x | x | x
#coastg | 472 | Various Items: | Items all Over, | Items Grouped in Back | Items all Over +2 Oars in Front | x | x | x
#fcr900 | 521 | Exhausts: Fairings (with Windshields): | Single Type1 | Dual Type1 | Dual Type2 | Half-size | Full-size | x
#firetruk | 407 | Numbers: | 64 | 16 | 47 | x | x | x
#flatbed | 455 | Cargo: | Crates in Front | Crates in center under Tarp | Two Sets of crates (Front and Back) | x | x | x
#hotknife | 434 |  | Partial Engine Cover | x | x | x | x | x
#hotrina | 502 | Numbers: | 96 | 67 | 73 | 52 | 45 | 14
#hotrinb | 503 | Numbers: | 82 | 26 | 65 | 07 | 36 | 60
#kart | 571 | Body Panels: | Both Sides | Steering Column | x | x | x | x
#launch | 595 | Roofs: | Over passenger section | Over driver section | x | x | x | x
#marquis | 484 |  | Windshield over cabin Entrance | x | x | x | x | x
#mesa | 500 |  | Roof Over Back | Roll Bar in Back | x | x | x | x
#monstera | 556 |  | Roof Spoiler | Roof Lights | Roll Bar with Lights | x | x | x
#monsterb | 557 |  | x | Roof Lights | x | x | x | x
#mrwhoop | 423 | Rear Sign: | Cherry Popping Good, | Slow Children Ahead | x | x | x | x
#mule | 414 | Side Ads: | Toy Corner | Binco | Semi | Shafted Appliances | x | x
#nrg500 | 522 | Exhausts: Fairings (with Windshields): | Single Pair1 | Single Pair2 | Dual Pair2 | Smooth | With Side Cutouts | x
#patriot | 470 | Cargo Area: | Low Cover | Roof/High Cover | Roll Bar | x | x | x
#peren | 404 |  | Roof Rack | x | x | x | x | x
#picador | 600 | Items in Bed | Planks | Sprunk Cans | x | x | x | x
#pony | 413 |  | Sound System in Back | x | x | x | x | x
#reefer | 453 | Items in Back: | Boxes of Fish | Bench | x | x | x | x
#romero | 442 | Coffins: | Brown Style1 | Black Style2 | Brown Style3 | x | x | x
#rumpo | 440 | Side Ads: | Cok-o-Pops | Harry Plums | Dick Goblin's | Final Build | Transfender | Wheel Arch Angels
#sadler | 543 | Items in Bed | Two Propane Tanks & Crate | Two Barrels | Sprunk Cans | Open Crates | x | x
#sadlshit | 605 | Items in Bed | Two Propane Tanks & Crate | Two Barrels | Sprunk Cans | Open Crates | x | x
#securica | 428 | Side Logo: | Chuff | Lock&Load | x | x | x | x
#slamvan | 535 | Steering Wheel: | Normal | Chain | x | x | x | x
#stallion | 439 | Roof: | Hardtop | Softtop (up) | Softtop (folded) | x | x | x
#supergt | 506 |  | Full Roof | x | x | x | x | x
#swatvan | 601 | Number: | 1 | 9 | 6 | 7 | x | x
#topfun | 459 |  | Boxes of Toys in Back | x | x | x | x | x
#tram | 449 |  | ? | ? | ? | ? | ? | x
#trash | 408 |  | Some bits of trash sticking out of the back | x | x | x | x | x
#utility | 552 |  | Cones, Barrel in back, Cone lying on passenger | driver side rail |  | x | x | x | x
#walton | 478 | Items in Bed | Two Propane Tanks | Open Crates | Propane Tank and Barrel | x | x | x
#windsor | 555 |  | Roof |  |  |  |  |
#yankee | 456 | Side Ads: | Big Gas | RS Haul | Star Balls | Flower Power | x | x
#zr350 | 477 |  | Rear Spoiler | x | x | x | x | x


Взрывы

Взрывы создаются командами:

020c: create_explosion_with_radius 0 at 1945.6265 -2356.5925 13.5469
0948: create_explosion_at 1945.6265 -2356.5925 13.5469 type 0 camera_shake 1

Несмотря на подпись первого параметра первого опкода, от него зависит не радиус взрыва, а его тип.

Ещё есть проверка, есть ли взрыв в определённом кубе:

0356: explosion_type 0 in_cube_cornerA 1579.04 -1721.85 5.17837 cornerB 1524.631 -1633.711 11.8784

и создание звука взрыва:
0565: create_soundless_explosion_at 1945.6265 -2356.5925 13.5469 type 0

А вот и сами типы взрывов со скриншотами, сделанными 400 миллисекунд после начала взрыва:

№ | Описание | Ссылка на скриншот
0 | Стандартный средний взрыв, используется чаще всего | Highslide JS
1 | Взрыв как от коктейля Молотова. По-этому после него появлятся много огня и звук тихий. Следует также учитывать то, что именно этот взрыв визуально появляется вне зависимости высоты у самой земли. | Highslide JS
2 | Похож на тип 0 | Highslide JS
3 | Похож на тип 0 | Highslide JS
4 | Один-три взрывных линий. Следует иметь в виду, что в типах 4 и 5 не звучит грохот взрыва. Так что комбинируйте этот тип с другими типами или создавайте звук отдельно опкодом 0565 (описан выше) | Highslide JS
5 | Похоже на тип 4 | Highslide JS
6 | Большой взрыв, один из самых больших | Highslide JS
7 | Чуть покороче чем тип 6 | Highslide JS
8 | Звука нет, эффекта нет, трясение камеры есть, здоровье отнимает. | Highslide JS
9 | То же самое, что и тип 8 | Highslide JS
10 | Наряду с типом 6 самый большой взрыв | Highslide JS
11 | Как тип 0, но чуть пожиже | Highslide JS
12 | Самый маленький взрыв, как от взрыва RC-машинки. | Highslide JS
13+ | Тринадцатый и последующие типы, по-видимому, не поддерживаются игрой: взрывы без звука, без эффекта. | Highslide JS

Что имеем в итоге? Любителям больших взрывов следует использовать типы 6 и 10, что-бы от взрывов было много огня, нужно комбинировать взрывы с типом 1, и ещё можно комбинировать средние взрывы с типами 4-5 (у больших и так отлетают горящие линии). Для обычных взрывов можно использовать тип 0, а для очень маленьких - тип 12.

Можно увидеть все взрывы воочию, использовав скрипт ExpShow.cs, исходник ExpShow.txt.


GTA SA Иконки радара

Иконки радара

Я думаю, что все знают, что такое иконка и маркер, но я всё равно расскажу о них:
Иконка - обозначение на карте к-л объекта, например дома CJ'я, буквы N на радаре...
Маркерами являются сферы (такие красные круги, на которые надо зайти, чтобы начать миссию) и стрелки над актёрами, в Vice City они были больше пошожи на стрелки, чем San Andreas.

Стрелка над актёром создаётся вот этой командой:
marker.CreateAboveActor($Mark,$Actor)
$Mark - имя маркера,
$Actor - имя актёра.

Стрелка над машиной создаётся вот так:
marker.CreateAboveCar($Mark,$Car)
$Mark - имя маркера,
$Car - имя машины.

Стрелка над любым объектом создаётся вот этой командой:
marker.CreateAboveObject($Mark,$Object)
$Mark - имя маркера,
$Object - имя объекта.

Чтобы создать стрелку над пикапом используем это:
03DC: $mark = create_marker_above_pickup $PickUp
$Mark - имя маркера,
$PickUp - имя пикапа.

Просто иконка на радаре создаётся этой командой:
marker.CreateIconWithoutSphere($Icon,15,1024.0,768.0,128.0)
$Icon - имя(название) нашей иконки,
15 - это номер картинки иконки (перекраска,слово CJ,буква $,т.е. школа...),все номера описаны ниже,
1024.0 - координата по оси X,
768.0 - координата по оси Y,
128.0 - координата по оси Z.

А вот иконка на радаре и сфера(всегда используется,чтобы указать место,на которое надо стать чтобы началась миссия) создаётся этой командой:
marker.CreateIconAndSphere($Icon,15,1024.0,768.0,128.0)
$Icon - имя(название) нашей иконки,
15 - это номер картинки иконки (перекраска,слово CJ,буква $,т.е. школа...),все номера описаны ниже,
1024.0 - координата по оси X,
768.0 - координата по оси Y,
128.0 - координата по оси Z.

Стрелки всегда видны на радаре. Просто иконка видна на радаре только тогда, когда вы рядом с ней, т.е. если она в зоне видимости радара. Иконки со сферой видны на радаре всегда,но вот если надо создать иконку со сферой, и чтобы это всё не было видно на радаре (как иконка со сферой возле дома девушки,если CJ рядом,то видно,далеко-не видно), пользуются вот этой командой:
0570: $ICON = create_asset_radar_marker_with_icon 31 at 2479.947 -1662.025 13.3437
$Icon - имя(название) нашей иконки,
31 - это номер картинки иконки , все номера описаны ниже,
2479.947 - координата по оси X,
-1662.025 - координата по оси Y,
13.3437 - координата по оси Z.

018A: 1@ = create_checkpoint_at 1290.4906 -788.3314 95.4531 - создаёт чекпоинт.

08FB: set_checkpoint 1@ type_to 2 - устанавливает чекпоинту определённый тип.

0A40: 1@ = create_entrance_marker_at 1685.7 -2238.9 14.0 color 14 - создаёт входной маркер.

08E7: set_entrance_markers 0 - выключает входные маркеры(как в зданиях).

024F: create_corona 0.2 2 0 with_color 255 0 0 at_point $X $Y $Z - создаёт корону.

04AE: unknown $ICON_CJ radar_icon_or_model 15 - можно ассоциировать переменную с номером.

marker.Disable($Mark) - уничтожить маркер

marker.SetColor($Mark,2) - установить цвет маркера

marker.SetIconSize($Mark,4) - установить размер

Вот номера всех иконок,которые существуют в игре:

0 | небольшой желтый квадрат
1 | белый квадрат
2 | позиция игрока
3 | позиция игрока, которая отображается на большой карте в меню
4 | север(буква N)
5 | кладбище самолётов
6 | аммунация
7 | парикмахерская
8 | Большой Смоук
9 | якорь ( Docks)
10 | Выстрел бургера
11 | Карьер
12 | Каталина
13 | Цезарь
14 | Закусочная "Циплёнок"
15 | дом CJ'я
16 | буква С, но с мигалкой посредине
17 | мороженное
18 | Emmet
19 | Вражеская атака
20 | Огонь
21 | Девушка
22 | Больница
23 | череп (Loco Syndicate)
24 | МэдДог или миссии Бешеного Пса
25 | Мафия
26 | MC Strap
27 | Гараж для тюнинга
28 | OG Loc
29 | Пиццерия
30 | Полиция
31 | зелёная иконка дома
32 | красная иконка дома
33 | Гонки
34 | Ryder
35 | Сохранение
36 | школа
37 | Неизвестный
38 | Sweet
39 | Татуировки
40 | The Truth
41 | указатель пути
42 | Ранчо Торено
43 | Триады
44 | Казино Триад
45 | Магазин одежды
46 | Вузи
47 | Зеро
48 | Дискотека
49 | Бар
50 | Рестаран
51 | дальнобойшик
52 | Миссия грабителя
53 | Гонки
54 | спортзал
55 | машинка
56 | что-то светлое (игра вылетает при вхождении в карту в меню)
57 | три точки, которые показывают взлётную полосу, если игрок в самолёте
58 | Гангстеры Los Aztecas (иконка чувачка)
59 | Гангстеры Баллас (иконка чувачка)
60 | Гангстеры Los Santos Vagos (иконка чувачка)
61 | Гангстеры San Fierro Rifa (иконка чувачка)
62 | Гангстеры Грув Стрит (иконка чувачка)
63 | Перекраска

Вот вам пример использования маркеров:
Создаём иконку со сферой,если игрок останавливается в этой сфере, то появляется охранник с М4, создаём затем над охранником стрелку, убираем сферу, в которой остановились, и пока охранник жив, над ним есть стрелка, как только охранник погибнет, то стрелка исчезнет и можно будет идти за новым охранником.

Copy to Clipboard
create_thread @MyGuarder

:MyGuarder
wait 0
model.Load(#FAM3)
model.Load(#M4)
038B: load_requested_models
marker.CreateIconAndSphere($Mark,18,2508.7458,-1683.5065,13.5561)

:MyGuarder_2
wait 0
if and
model.Available(#FAM3)
model.Available(#M4)
0101: actor $PLAYER_ACTOR stopped_near_point 2508.7458 -1683.5065 13.56 radius 3.0 3.0 10.0 sphere 1
jf @MyGuarder_2
wait 2000
actor.Create($Man,CivMale,#FAM3,2514.2583,-1691.2355,14.046)
01B2: give_actor $Man weapon 31 ammo 6000
05D3: AS_actor $Man go_to 2509.0459 -1686.9645 13.5669 speed 4 5000 ms
wait 5000
0631: put_actor $Man in_group $PLAYER_GROUP
Actor.WeaponAccuracy($Man) = 100
Actor.Health($Man) = 2000
0568: (unknown) $Man 1
0446: set_actor $Man immune_to_headshots 0
08AF: (unknown) $Man 7000
077A: (unknown) $Man 4 25
marker.CreateAboveActor($ActMark,$Man)
marker.SetColor($ActMark,1)
marker.Disable($Mark)

:MyGuarder_3
wait 0
if
actor.Dead($Man)
jf @MyGuarder_3
marker.Disable($ActMark)
jump @MyGuarder


GTA SA Имена гаражей

Имена гаражей

Гараж в СА тоже самое, что и самый обыкновенный гараж. У каждого гаража есть свой ID(имя).

Garage.Activate('BODLAWN')

Вот команды,которые можно применять к гаражам:

garage.Activate('ID') - активирует гараж
garage.Open('ID') - открывает гараж
garage.ChangeType('ID',Type(integer) ) - изменяет тип гаража
garage.Close('ID') - закрывает гараж
garage.Deactivate('ID') - деактивирует гараж
garage.SetToAcceptCar('ID',#CARMODEL) - гараж может принимать только машину с опр. моделью

Проверки,применяемые к гаражам:

garage.IsClosed('ID') - проверка на закрытость гаража
garage.IsOpen('ID') - проверка на открытость гаража

Вот ID гаражей,они разделены по местности нахождения:

 | Лос Сантос |
ID | Координаты | Описание
CJSAFE | (2502.31, -1699.36, 12.4323) | Гараж домв Карла
CESAFE1 | (1352.58, -636.657, 108.135) | Гараж в мухоленде
MUL_LAN | (1640.37, -1520.07, 12.5118) | Гараж в цетре, туда надо было фургон DJ'я пригнать
DUF_LAS | (1873.97, -2096.55, 12.487) | Гараж Эль Корона (из миссии)
LASBOMB | (1843.91, -1858.8, 12.3645) | Гараж 8 болл,возле лоурайдеров
MODGLAS | (1809.46, -2150.67, 12.4283) | Гараж Цезаря
CARLAS1 | (1694.8, -2088.7, 12.3636) | Гараж Эль Корона
BURG_LK | (2738.4, -2012.55, 12.5759) | Гараж миссии грабителя
MODLAST | (2640.78, -2049.99, 12.543) | Локо Лоу Ко
SPLAW2 | (491.103, -1747.55, 9.45516) | Перекраска в районе пляжа
BEACSV | (319.326, -1768.93, 3.35686) | Гараж на пляже в районе маяка
BODLAWN | (1038.24, -1025.67, 31.1027) | Гараж тюнинга (район центра)
SPRLAE | (2056.6, -1835.9, 12.5443) | Идлвудская перекраска
SPRLAE | (1021.81, -1018.71, 30.9081) | Перекраска в цетре (рядом с гаражом тюнинга)
 | Сан Фиеро |
FDORSFE | (-2171.43, 649.416, 49.8742) | Гараж Визи
MICHDR | (-1790.97, 1209.71, 23.763) | Гараж Мишёль
SAV1SFE | (-2108.92, 886.553, 75.566) | Гараж в доме с длинной лестницей
MDS1SFS | (-2728.53, 212.295, 3.45112) | Гараж "Wheels Arch Angel"
TBON | (-2735.46, 60.7331, 3.07005) | Гараж в районе "Wheels Arch Angel"
SVGSFS1 | (-2454.02, -131.556, 25.0886) | Гарраж хашберри
MDSSFSE | (-1941.04, 251.714, 33.4274) | Гараж тюнинга
SPRSFSE | (-1908.93, 292.353, 40.0413) | Перекраска в центре
BRGSFSE | (-2112.48, -21.214, 34.303) | Гараж миссии грабителя
HBGDSFS | (-2057.35, 150.803, 27.8286) | Гараж на бензоколонке Дохерти (левый)
LCKSFSE | (-2043.1, 118.609, 27.821) | Гараж на бензоколонке Дохерти (правый)
SPRSFW | (-2430.13, 1013.71, 49.3413) | Перекраска
SAV1SFW | (2699.12, 821.489, 49.0042) | Гараж парадис
noname | (-1694.78, 1033.15, 44.1937) | Место,на котором можно хранить машины(парковка)
noname | (-1794.15, 1429.69, 4.37321) | Место,на котором можно хранить машины (эсплантада)
 | Лас Вентурас |
VGELOCK | (2602.6, 1438.84, 9.8337) | Перекраска
VECMOD | (2382.28, 1044, 9.8337) | Гараж тюнинга
VESVGRG | (2449.5, 695.018, 10.4742) | Гараж в западном рокшоре
VGSHNGR | (1550.98, 1155.36, 8.97329) | Ангар для АТ-400 в аэропорту
BLOB2 | (2002.96, 2303.72, 9.61706) | Гараж для заминирования машин
BLOB1 | (1968.23, 2157.88, 9.59696) | Вотсточная перекраска
BLOB6 | (1408.65, 1899.52, 10.115) | Западный гараж
BLOB69 | (1269.2, 2525.14, 9.80013) | Гараж района колючей сосны
BLOB7 | (929.554, 2008.59, 10.115) | Гараж поместья ваитвуд
TIMY1 | (2389.6, 1483.26, 9.81843) | неиспользуемая перекраска (дверь не работает)
 | Гаражи пересечной местности |
CN2SPRY | (-103.636, 1112.42, 18.7017) | Перекраска форта карсон
CN2GAR1 | (-364.439, 1194.37, 18.597) | Гараж форта карсон
CN2GAR2 | (430.059, 2542.31, 15.166) | Гараж кладбища самолётов
GHOSTDR | (-397.297, 2223.17, 41.3824) | Гараж миссии "Отлучение"
DHANGAR | (383.843, 2433.28, 15.166) | Ангар кладбища самолётов
CESPRAY | (715.806, -462.403, 14.9635) | Дилмурская перекраска
BURBDOO | (2227.6, 168.649, 26.4635) | Гараж в Паломино Крик
BURBDO2 | (783.155, -492.75, 16.3361) | Гараж в дилмуре
CNSPRAY | (-1424.11, 2576.61, 54.8156) | Гараж в Эль Квебрадос
AMUMIS | (-2114.42, -2462.27, 29.4809 ) | Гараж аммунации Сосны Ангела

Вот типы гаражей , которые могут понадобиться при создании к-л модификации :

1 - загатовка для гаража(не открывается)
2 - 8-ball(бомба,которая взрывается через некоторое время,после зарядки)
3 - 8-ball(бомба,которая взрывается если кто-то сядет в машину)
4 - 8-ball(бомба на радиоуправлении)
5 - перекраска
32 - обыкновенный гараж на 4 машины
33 - гараж с дверью, сквозь которую можно передвигаться (зачем такое надо ?)
38 - гараж,который не закрывается,если в нём есть машина

Всё остальное или повторяется или не работает ...

Запомните,что если вы создали машину командой car.create и в памяти есть ещё о ней сведения, то гараж не сможет сохранить или починить её, чтобы гараж нормально работал с этой машиной надо удалить сведения об этой машине , делается это командой Car.RemoveReferences($CAR), т.е полная конструкция выглядит вот так:

car.create($CAR,#Model,X,Y,Z)
Car.RemoveReferences($CAR)


Интерьеры

Интерьер - это как-бы отдельная часть игровой карты,например дом CJ, улица, Стрип Клуб, казино- это всё интерьеры, т.е разные игровые помещения.

Вот этой командой мы выбираем нужный нам интерьер :

select_interior 0

0 - номер интерьера

Есть такая вещь, что один и тот же интерьер может иметь по несколько координат, ну вот и сам список интерьеров:

Number | Name | Description
1 | ABATOIR | Sindacco Abattoir
1 | AMMUN1 | Ammu-Nation
1 | CARMOD1 | TransFender
1 | FDREST1 | World of Coq
1 | GF1 | Denise's
1 | JETINT | Shamal interior
1 | LACS1 | Sub Urban
1 | LAHS1B | House
1 | MAFCAS | Caligulas Casino
1 | MAFCAS2 | Penthouse Suites
1 | - | Saint Mark's
1 | SMASHTV | Warehouse
1 | - | Stadium with wooden sandbox
1 | SVVGHO1 | Hotel Suite
1 | SWEETS | Sweet's House
1 | - | Trailer
1 | TSDINER | Truck Stop
1 | WUZIBET | Wu Zi Mu's
2 | BARBERS | Barber
2 | BDUPS1 | B Dup's Crack Palace
2 | CARMOD2 | Loco Low Co.
2 | CARTER | Smokes Crack Palace
2 | GF2 | Katie's
2 | LAHS1A | House
2 | LASTRIP | Strip Club
2 | RYDERS | Ryder's Place
2 | SVVGHO2 | Hotel Suite
2 | VGHSB1 | House
2 | VGHSB3 | House
3 | BARBER2 | Barber
3 | BDUPS | B Dup's apartment
3 | BIKESCH | Bike School
3 | BROTHL1 | Whore House
3 | CARLS | The Johnson House
3 | CARMOD3 | Wheel Arch Angels
3 | CHANGER | Wardrobe
3 | CSSPRT | Pro-Laps
3 | DRIVES | Driving School
3 | DRIVES2 | Driving School
3 | GENOTB | Inside Track Betting
3 | GF3 | Helena's
3 | LAHSB4 | House
3 | OGLOCS | OG Loc's
3 | PAPER | Planning Department
3 | PDOMES | The Pleasure Domes
3 | PDOMES2 | The Pleasure Domes
3 | POLICE3 | LVPD HQ
3 | SEXSHOP | Sex Shop
3 | S1TEST | Middle of nowhere
3 | STRIP2 | Strip Club
3 | STUDIO | Blastin' Fools Records studio
3 | TATTO3 | Tattoo Parlor
4 | AMMUN2 | Ammu-Nation
4 | DINER1 | Diner
4 | DIRBIKE | Dirt Stadium
4 | GF4 | Michelle's
4 | LAHS2A | House
4 | LAHSS6 | House
4 | SFHSM2 | House
4 | X711S2 | 24-7
5 | CSDESGN | Victim
5 | DINER2 | Diner
5 | FDPIZA | Pizza Stack
5 | GANG | Vagos Gang House
5 | GF5 | Barbara's
5 | GYM1 | Ganton Gym
5 | LACRAK | Crack Den
5 | LAHSB3 | House
5 | MADDOGS | Madd Dogg's Crib
5 | MDDOGS | Madd Dogg's Crib
5 | SFHSB1 | House
5 | SVHOT1 | Hotel Suite
5 | VGHSM2 | House
6 | AMMUN3 | Ammu-Nation
6 | AMMUN5 | Ammu-Nation
6 | BROTHEL | Whore House
6 | GF6 | Millie's
6 | GYM2 | Cobra Marital Arts
6 | LAHSB1 | House
6 | POLICE1 | LSPD HQ
6 | RCPLAY | Zero's RC Shop
6 | REST2 | Secret Valley
6 | SFHSB2 | House
6 | SFHSS2 | House
6 | SVCUNT | Safe House
6 | SVSFSM | Safe House
6 | X7_11S | 24-7
7 | 8TRACK | 8-Track Stadium
7 | AMMUN4 | Ammu-Nation
7 | GYM3 | Below the Belt Gym
7 | LAHSB2 | House
7 | OFTEST | Middle of nowhere
8 | BURHOUS | Colonel Fuhrberger's
8 | SFHSS1 | House
8 | SVLAMD | Safe House
9 | FDCHICK | Cluckin' Bell
9 | LAHS2B | House
9 | SFHSB3 | House
9 | SVGNMT2 | Motel room
9 | SVVGMD | Safe House
10 | DESHOUS | Abandoned AC tower
10 | FDBURG | Burger Shot
10 | POLICE2 | SFPD HQ
10 | SVGNMT1 | Motel room
10 | TRICAS | The Four Dragon's
10 | - | The Four Dragon's Casino's maintenance room
10 | SVSFMD | Safe House
10 | VGHSM3 | House
10 | X711S3 | 24-7
10 | - | Zero's No Man's Land
11 | BAR2 | Bar
11 | SVLASM | Safe House
12 | BARBER3 | Barber
12 | MOROOM | Motel room
12 | SVLABIG | Safe House
14 | CSEXL | Didier Sachs
14 | AIRPOR2 | Los Santos International Airport
14 | AIRPORT | Francis Intl. Airport
15 | CSCHP | Binco
15 | MOTEL1 | Jefferson Motel
15 | SFHSM1 | House
15 | VGHSS1 | House
15 | VGSHM2 | House
15 | VGSHM3 | House
15 | VGSHS2 | House
16 | - | Stadium with giant round circular raised platform in middle
16 | TATTOO | Tattoo Parlor
16 | X7_11C | 24-7
17 | BAR1 | Bar
17 | DAMIN | Generator Hall
17 | FDDONUT | Rusty Brown's
17 | TATTO2 | Tattoo Parlor
17 | X7_11D | 24-7
18 | ATRIUME | Atrium
18 | ATRIUMX | Attrium
18 | CLOTHGP | Zip
18 | GENWRHS | Warehouse
18 | UFOBAR | Lil' Probe Inn
18 | X7_11B | 24-7

Вот этой командой мы делаем интерьер активным,точнее включаем или выключаем его:

07FB: set_interior 'GYM1' accessible 1

'GYM1' - имя интерьера, имена и номера находятся в зависимости между собой 1 - интерьер включается, если 0, то выключается.

Установить цвет интерьера, в городе ещё и на погоду влияет:

04F9: interior_colors 1 0

Чтобы всунуть в интерьер объект, машину, актёра ... надо пользоваться вот этими командами:

0566: object $Obj set_interior 1 - выбирает интерьер объекту
0840: link_car $Car to_interior 1 - выбирает интерьер машине
0860: link_actor $Actor to_interior 1 - выбирает интерьер актёру

077E: $ACTIVE_INTERIOR = active_interior - в переменную записывается активный интерьер.
09E8: $Int = actor $Act active_interior - записыватеся активный интерьер актёра

Чтобы поместить игрока или к-л актёра, объект... в интерьер нужны всего 3 команды, если конечно интерьер уже включен, так вот:
Например поместим игрока в дом CJ'я :

select_interior 3
0860: link actor $PLAYER_ACTOR to interior 3
actor.PutAt($PLAYER_ACTOR,2494.05, -1696.73 ,1013.75)


GTA SA Номера клавиш

Номера клавиш

Клавиши существуют для того, чтобы после их нажатия или не нажатия пошло выполняться какое - либо действие. Клавишими, которыми можно пользоваться являются только те, которые задействованы в опциях игры. К примеру в GTA нет такой клавиши, как "Shift", а есть клавиша "Спринт", короче от настроек самой игры зависит то, на какую вам кнопку на клавиатуре прийдётся нажимать. Каждая клавиша в игре имеет свой номер, не важно, что это за кнопка на клавиатуре, номер всё равно останиться неизменным.
Когда игрок едет в к-л транспортном средстве, то клавиши означают одно, но когда игрок вне транспортного средства,то эти же самые клавиши означают совсем другое,заметьте, что где-бы не находился игрок каждая клавишя постоянно сохраняет свой номер.

ONFOOT CONTROLS |  |
# | CONTROL | GXT ENTRY VALUES
0 | left/right | ~k~~GO_LEFT~ / ~k~~GO_RIGHT~
1 | forward/backward | ~k~~GO_FORWARD~ / ~k~~GO_BACK~
2 | special ctrl left/right | ~k~~VEHICLE_LOOKLEFT~/~k~~VEHICLE_LOOKRIGHT~
3 | special ctrl up/down | -unknown-
4 | action/secondary fire | ~k~~PED_ANSWER_PHONE~/ ~k~~PED_FIREWEAPON_ALT~
5 | previous weapon/zoom in | ~k~~PED_CYCLE_WEAPON_LEFT~/ ~k~~PED_SNIPER_ZOOM_IN~
6 | aim weapon | ~k~~PED_LOCK_TARGET~
7 | next weapon/zoom out | ~k~~PED_CYCLE_WEAPON_RIGHT~/ ~k~~PED_SNIPER_ZOOM_OUT~
8 | group CTRL forward | ~k~~GROUP_CONTROL_FWD~
9 | group CTRL back | ~k~~GROUP_CONTROL_BWD~
10 | conversation - no | ~k~~CONVERSATION_NO~
11 | conversation - yes | ~k~~CONVERSATION_YES~
12 | (does not exist) | -- -- --
13 | change camera | ~k~~CAMERA_CHANGE_VIEW_ALL_SITUATIONS~
14 | jump | ~k~~PED_JUMPING~
15 | enter vehicle | ~k~~VEHICLE_ENTER_EXIT~
16 | sprint | ~k~~PED_SPRINT~
17 | fire | ~k~~PED_FIREWEAPON~
18 | crouch | ~k~~PED_DUCK~
19 | look behind | ~k~~PED_LOOKBEHIND~
LALT | sneak | ~k~~SNEAK_ABOUT~
VEHICLE CONTROLS |  |
# | CONTROL | GXT ENTRY VALUES
0 | left/right | ~k~~VEHICLE_STEERLEFT~/ ~k~~VEHICLE_STEERRIGHT~
1 | steer back/up | ~k~~VEHICLE_STEERUP~/ ~k~~VEHICLE_STEERDOWN~
2 | special ctrl left/right | ~k~~VEHICLE_TURRETLEFT~/ ~k~~VEHICLE_TURRETRIGHT~ (NUM6)
3 | special control up/down | ~k~~VEHICLE_TURRETUP~/ ~k~~VEHICLE_TURRETDOWN~
4 | secondary fire | ~k~~VEHICLE_FIREWEAPON_ALT~
5 | look left | ~k~~VEHICLE_LOOKLEFT~
6 | hand brake | ~k~~VEHICLE_HANDBRAKE~
7 | look right | ~k~~VEHICLE_LOOKRIGHT~
8 | next radio station | ~k~~VEHICLE_RADIO_STATION_UP~
9 | previous radio station | ~k~~VEHICLE_RADIO_STATION_DOWN~
10 | no | ~k~~CONVERSATION_NO~
11 | yes / trip skip | ~k~~CONVERSATION_YES~
12 | (does not exist) | -- -- --
13 | camera | ~k~~CAMERA_CHANGE_VIEW_ALL_SITUATIONS~
14 | brake/reserve | ~k~~VEHICLE_BRAKE~
15 | enter/exit | ~k~~VEHICLE_ENTER_EXIT~
16 | accelerate | ~k~~VEHICLE_ACCELERATE~
17 | fire | ~k~~VEHICLE_FIREWEAPON~
18 | horn | ~k~~VEHICLE_HORN~
19 | submission | ~k~~TOGGLE_SUBMISSIONS~
RMB | vehicle mouse look | ~k~~VEHICLE_MOUSELOOK~

Проверка на нажатость клавиши выглядит вот так:

00E1: key_pressed 0 19

параметр 0, всегда должен равнятся 0, а вот 19 - номер клавиши.

Проверка на не нажатость клавиши выглядит вот так:

80E1: not key_pressed 0 19

параметр 0, всегда должен равнятся 0, а вот 19 - номер клавиши.

Если надо сделать проверку для одной клавиши, то вот так:

if
00E1: key_pressed 0 19
jf @XXX

А если надо сделать проверку на нажатость сразу нескольких клавиш, то:

if and // условие с выполнением всех подусловий.
00E1: key_pressed 0 19
00E1: key_pressed 0 16
00E1: key_pressed 0 17
00E1: key_pressed 0 N
jf @XXX

Бывает, что надо сделать проверку на нажатость одной из нескольких клавиш, она выглядит так:

if or // условие с выполнением хотя бы одного подусловия.
00E1: key_pressed 0 19
00E1: key_pressed 0 16
00E1: key_pressed 0 17
00E1: key_pressed 0 N
jf @XXX

Примеры :

1) Давайте напишем скрипт,в котором по нажатию "прицел" и "спринт", когда игрок не в машине, перед вами появляется Монстр, большой такой джип, если кто не знает.

Copy to Clipboard
create_thread @Monster  //создаём поток с именем Monster

:Monster  // начинаем поток
wait 0    // ждём 0 мс,не напищем-вылетит
model.load(#MONSTER)   // объявляем нужную для загрузки модель #MONSTER
038B: load_requested_models // загружаем ранее объявленые модели

:Monster_2 // создаём второй label
wait 0     // ждём 0 мс,не напищем-вылетит
if and     // условие с выполнением всех подусловий
player.Defined($PLAYER_CHAR) // подусловие(игрок уже создался и существует)
model.Available(#MONSTER)//подусловие(модель #MONSTER уже загружена в память)
not actor.Driving($PLAYER_ACTOR)  // подусловие(если игрок не в машине)
00E1: key_pressed 0 6      // подусловие(если нажата клавиша "прицел")
00E1: key_pressed 0 16      // подусловие(если нажата клавиша "спринт")
jf @Monster_2
  // если хотя бы одно из подусловий не выполнилось,то идём к началу label'a
04C4: create_coordinate $X_1 $Y_1 $Z_1 from_actor $PLAYER_ACTOR offset 0.0 10.0 3.0
 // создаём координаты напротив игрока
car.create($Car,#MONSTER,$X_1,$Y_1,$Z_1) //создаём машину по этим координатам
car.removereferences($Car)      // удаляем все сведения о машине
wait 5000
//ждём 5 секунд,если бы мы не ждали,то на месте машины появилась бы другая,но
// первая всё равно осталась бы и они застряли бы
jump @Monster_2  // прыгаем в начало label'a.

2) Вот ещё простенький, но полензный скрипт с использованием клавиш :

По нажатию "Спринт" + "Сесть в машину" к игровому времени прибавляется один час:

Copy to Clipboard
create_thread @TimeM  // создаём поток с именем TimeM

:TimeM  // Начинаем наш поток
wait 0  // ждём 0 мс, если не напишем, то игра вылетит
if and  // условие с выполнением всех проверок(подусловий)
00E1: key_pressed 0 15  // проверка (если нажата клавиша "СЕСТЬ В МАШИНУ")
00E1: key_pressed 0 16  // проверка (если нажата клавиша "СПРИНТ")
jf @TimeM  // если все проверки не выполнились,то переходим на начало
wait 100  // ждём 100 мс, если не напишем небольшую задержку,то игровое время
// будет изменятся с бешеной скоростью(из-за скорости процессора вашего компа)
$time += 1// тут к переменной $time прибавляем 1, если устанавливается значение
// больше, чем 23, то оно автоматически переводится на 0
00C0: set_current_time $time 0 // и устанавливаем игровое время на $time
jump @TimeM  // и прыгаем в начало

3) Давйте напишем скрипт,с помощью которого можно будет изменять скорость игры :
При нажатии "Прыжок" + "Атака" скорость постепенно уменьшается , при нажатии "Прыжок" +"Прицел/Вторичная атака" скорость будет увеличиваться, при нажатии "Прыжок" + "Действие" , скорость будет становится нормальной :

Copy to Clipboard
create_thread @TimeSpeed // создаём поток с именем TimeSpeed

:TimeSpeed // начинаем поток
wait 0  // ждём 0 мс
$Var = 1.0// берём переменную $Var и присваиваем ей значение 1.0 - скорость игры

:TimeSpeed_2 // создаём второй label потока
wait 100 // ждём 100 мс для того,чтобы скорость не сильно быстро менялась
if and  // условие с выполнением всех подусловий(проверок)
00E1: key_pressed 0 6  // проверка(если нажата клавиша "Прицел")
00E1: key_pressed 0 14 // проверка(если нажата клавиша "Прыжок")
jf @TimeSpeed_3  // Если хоть одно из подусловий не выполнилось, то переходим к другой
$Var += 0.1  // проверке,если же выполнилось, то к нашей переменной прибавляем 0.1
015D: set_gamespeed $Var// и устанавливаем скорость, равной нашей переменной $Var

:TimeSpeed_3  // создаём третий label
wait 100 // ждём 100 мс для того, чтобы скорость не сильно быстро менялась
if and  // условие с выполнением всех подусловий(проверок)
00E1: key_pressed 0 17  // проверка(если нажата клавиша "Атака")
00E1: key_pressed 0 14  // проверка(если нажата клавиша "Прыжок")
jf @TimeSpeed_4 // Если хоть одно из подусловий не выполнилось, то переходим к другой
$Var -= 0.1
// проверке, если же выполнилось,то от нашей переменной отнимаем 0.1
015D: set_gamespeed $Var// и устанавливаем скорость, равной нашей переменной $Var

:TimeSpeed_4 // создаём четвёртый label
wait 100 // ждём 100 мс для того, чтобы игра не вылетила
if and   // условие с выполнением всех подусловий(проверок)
00E1: key_pressed 0 4  // проверка(если нажата клавиша "Действие")
00E1: key_pressed 0 14 // проверка(если нажата клавиша "Прыжок")
jf @TimeSpeed_2  // если все подусловия выполнились, то делаем скорость нормальной, а
015D: set_gamespeed 1.0//если нет, то скорость остаётся прежней и выполнение скрипта
jump @Prosto_2  // переходит к первой проверке

Может на игроке и не очень видно ускорение, но вот на проезжающих машинах - это реактивно.

4) Очень часто просят привести пример замедления времени при нажатии на "Прицел". Ловите :

Copy to Clipboard
create_thread @Prosto   // создаём поток с именем Prosto

:Prosto  // начинаем поток
wait 10  // ждём 10 мс,чтобы не вылетило
015D: set_gamespeed 1.0   // устанавливаем скорость на нормальную
if and   // условие с выполнением всех подусловий(проверок)
player.Defined($PLAYER_CHAR)  // проверка(игрок существует), на всякий случай
not actor.Driving($PLAYER_ACTOR)   // проверка(игрок не за рулём)
82D8: not actor $PLAYER_ACTOR currentweapon == 34// у актёра в руках не снайперка
82D8: not actor $PLAYER_ACTOR currentweapon == 35// у актёра в руках не базука(1)
82D8: not actor $PLAYER_ACTOR currentweapon == 36
// у актёра в руках не базука(2)
jf @Prosto  // если чего-нибудь не выполнилось, то переходим на начало

:Prosto_2  // создаём второй label
wait 10   // ждём 10 мс,на всякий случай
if   // обыкновенное условие
00E1: key_pressed 0 6   // проверка(нажата клавиша "Прицел")
jf @Prosto
// если это не правда, то переходим на начало, и там скорость становится
//обыкновенной
015D: set_gamespeed 0.25 // устанавливаем меньшую скорость игры
jump @Prosto_2   // и прыгаем в начало этого же label'a


GTA SA Номера оружия

Номера оружия

Номера оружия используются с

01B2: give_actor $PLAYER_ACTOR weapon 28 ammo 60
01B9: set_actor $PLAYER_ACTOR armed_weapon_to 0

и аналогичными опкодами.

number | Weapon Group | Name | ModelID | Model name | Icon
gift
10 | 11 | Purple Dildo | 321 | #gun_dildo1 |
11 | 11 | White Dildo | 322 | #gun_dildo2 |
12 | 11 | Long White Dildo | 323 | #gun_vibe1 |
13 | 11 | White Dildo 2 | 324 | #gun_vibe2 |
14 | 11 | Flowers | 325 | #flowera |
15 | 11 | Cane | 326 | #gun_cane |
melee
0 | 1 | Unarmed |  |  |
1 | 1 | Brass Knuckles | 331 | #brassknuckle |
2 | 2 | Golf Club | 333 | #golfclub |
3 | 2 | Night Stick | 334 | #nitestick |
4 | 2 | Knife | 335 | #knifecur |
5 | 2 | Baseball Bat | 336 | #bat |
6 | 2 | Shovel | 337 | #shovel |
7 | 2 | Pool cue | 338 | #poolcue |
8 | 2 | Katana | 339 | #katana |
9 | 2 | Chainsaw | 341 | #chnsaw |
projectiles
16 | 9 | Grenades | 342 | #grenade |
17 | 9 | Tear Gas | 343 | #teargas |
18 | 9 | Molotovs | 344 | #molotov |
handguns
22 | 3 | Pistol | 346 | #colt45 |
23 | 3 | Silenced Pistol | 347 | #silenced |
24 | 3 | Desert Eagle | 348 | #desert_eagle |
shotguns
25 | 4 | Shotgun | 349 | #chromegun |
26 | 4 | Sawn Off Shotgun | 350 | #sawnoff |
27 | 4 | Combat Shotgun | 351 | #shotgspa |
sub-machineguns
28 | 5 | Micro Uzi (Mac 10) | 352 | #micro_uzi |
29 | 5 | MP5 | 353 | #mp5lng |
32 | 5 | Tec9 | 372 | #tec9 |
machineguns
30 | 6 | AK47 | 355 | #ak47 |
31 | 6 | M4 | 356 | #m4 |
rifles
33 | 7 | Rifle | 357 | #cuntgun |
34 | 7 | Sniper Rifle | 358 | #sniper |
specials
35 | 8 | RPG | 359 | #rocketla |
36 | 8 | Missile Launcher | 360 | #heatseek |
37 | 8 | Flame Thrower | 361 | #flame |
38 | 8 | Minigun | 362 | #minigun |
39 | 9 | Sachet Charges | 363 | #satchel |
40 | 13 | Detonator | 364 | #bomb |
41 | 10 | Spray Paint | 365 | #spraycan |
42 | 10 | Fire Extinguisher | 366 | #fire_ex |
43 | 10 | Camera | 367 | #camera |
44 | 12 | Nightvision Goggles | 368 | #nvgoggles |
45 | 12 | Thermal Goggles | 369 | #irgoggles |
46 | 12 | Parachute | 371 | #gun_para |
Other
 |  | jetpack | 370 | #jetpack |


GTA SA Объекты

Объекты

Объектами являляются все небольшие вещи, которые существуют в игре(игровые автоматы,заборы...). Чтобы создать объект используется вот эта команда:

object.Create($obj,#DYNAMITE,1024.0,768.0,32.0)

$Obj - имя объекта
#DYNAMITE - модель объекта, модели приведены ниже
1024.0 - координата по оси X
768.0 - координата по оси Y
32.0 - координата по оси Z

Команды для объектов:

Object.Create($obj,#DYNAMITE,1024.0,768.0,32.0) - создать объект.
Object.Init($obj,#WATERJUMPX2,2481.3701,-1661.8964,13.3302) - создать объект.
Object.Destroy($Obj) - уничтожить объект.
071F: set_object $Obj mass 10 - задаёт объекту массу.
Marker.CreateAboveObject($Mark,$Obj) - cоздать маркер $Mark над объектом $Obj.
0681: attach_object $Obj to_car $Car at_offset 0.5 0.3 0.3 rotation 0.0 0.0 0.0 - прицепить объект к машине на опред. расстоянии от центра и под опред. углом.
069A: attach_object $Obj1 to_object $Obj1 at_offset 0.0 0.0 3.0 rotation 0.0 0.0 0.0 - прицепить объект к другому объекту на опред. расстоянии от центра и под опред. углом.
069B: attach_object $Obj to_actor $Act at_offset 0.0 0.0 0.0 rotation 0.0 0.0 0.0 - прицепить объект к актёру на опред. расстоянии от центра и под опред. углом.
Object.Angle($Obj) = 180.0 - устанавливает угол поворота объекта по оси Z.
0453: object $Obj set_rotation 0.0 0.0 0.0 - устанавить все углы поворота объекта.
Object.PutAt($obj,1600.0,1200.0,16.0) - перемещает объект в заданные координаты.
Object.RemoveReferences($Obj) - удалить все сведения об объекте.
Object.StorePos($Obj,$X,$Y,$Z) - записать координаты объекта $Obj в переменные $X,$Y и $Z.
0566: object $Obj set_interior 8 - установить интерьер объекта.
08E9: set_object $Obj liftable 1 - сделать объект поднимаемым(1-да,0-нет).
Object.CollisionDetection($Obj) = True - проверка объекта $Obj на форму (вкл.).
Object.ToggleInMovingList($Obj) = True - внести в лист движений (вкл.).
Object.SetImmunities($Obj,1,1,1,1,1) - установить иммунитеты объекта $Obj.Вот пояснение:
первая цифра - защита от пуль, вторая - от огня, третья - от взрывов, четвертая - от оружия ближнего боя,а вот пятая,наверное,от падения.
035D: toggle_object $Obj targetable 1 - даёт возможность делать объект целью,0 - не даёт.
Object.KeepInMemory($obj) = True - хранить все сведения об объекте в памяти.

Проверки (подусловия) для объектов:

03CA: object $Obj exists - объект $Obj существует.
83CA: not object $Obj exists - объект $Obj не существует.
0685: object $Obj attached - объект прицеплен к ч-л.
8685: not object $Obj attached - объект не прицеплен к ч-л.
023B: actor $Act colliding_with_object $Obj - актёр соприкасается с объектом.
823B: not actor $Act colliding_with_object $Obj - актёр не соприкасается с объектом.
0179: actor $Act picked_up_object $Obj - актёр поднял объект (относится к пикапам).
8179: not actor $Act picked_up_object $Obj - актёр не поднял объект (относится к пикапам).
0737: actor $Act lifting_object $Obj - актёр поднимает объект.
8737: not actor $Act lifting_object $Obj - актёр не поднимает объект.
0366: object $Obj blown_up - объект $Obj взорвался.
8366: not object $Obj blown_up - объект $Obj не взорвался.
04E7: object $Obj in water - объект $Obj в воде.
84E7: not object $Obj in water - объект $Obj не в воде.
0471: unknown_actor $Act near_object $Obj radius 50.0 50.0 unknown 0 - актёр находится в определённом радиусе от объекта.
8471: not unknown_actor $Act near_object $Obj radius 50.0 50.0 unknown 0 - актёр не находится в определённом радиусе от объекта.

Список объектов

Модель: | Описание:
#INFO | жёлтый инфо значок
#KEYCARD | ключ карта
#AD_FLATDOOR | серая дверь
#KB_BANDIT_U | игровой автомат
#ROULETTE_TBL | стол с рулеткой
#OTB_MACHINE | автомат для игры на скачках
#CJ_COIN_OP_3 | игровой автомат space monkey
#CJ_COIN_OP_2 | игровой автомат
#CJ_COIN_OP_1 | игровой автомат
#CJ_COIN_OP | игровой автомат
#SWANK_CONSOLE | игровая приставка CJD 500
#SNESISH | игровая приставка SUPERPLAYBOX
#LOW_CONSOLE | видик
#VENDMACHFD | автомат с содой
#VENDMACH | автомат с содой
#VENDIN3 | автомат с кофе
#CJ_SPRUNK1 | автомат с содой SPRUNK
#CJ_CANDYVENDOR | автомат с чипсами
#CJ_EXT_CANDY | автомат с чипсами
#CJ_EXT_SPRUNK | автомат с содой SPRUNK
#ICESCART_PROP | мороженица с зонтиком
#CHILLIDOGCART | латок с хот-догами
#NOODLECART_PROP | латок с супами
#GATE_AUTOL | решётка левая
#GATE_AUTOR | решётка правая
#GYM_BIKE | велосипед в спорт зале
#GYM_BENCH1 | тренажер
#GYM_TREADMILL | беговая дорожка
#GYM_MAT1 | батут
#BSKBALL_LAX | баскетбольное кольцо
#BSKBALLHUB_LAX01 | баскетбольное кольцо
#VGSXREFBBALLNET | баскетбольное кольцо в зале
#VGSXREFBBALLNET2 | верх баскетбольного кольца
#K_POOLTABLESM | бильярдный стол
#NEIL_SLOT | 1 автомат из казино
#CJ_SLOT_BANK | 5 автоматов из казино
#BLCK_JACK | стол для BLACK JACK
#WHEEL_O_FORTUNE | колесо фортуны
#CRACKFACT_SFS | ангар
#CF_EXT_DEM_SFS | здание
#LODCRACKFACT_SFS | лод здания
#LODEXT_DEM_SFS | лод здания
#PICKUPSAVE | пикап сохранения не крутящийся
#WOODENBOX | деревянный ящик
#NF_BLACKBOARD | школьная доска
#NF_LIST_1 | надпись розыска
#NF_LIST_2 | надпись розыска
#NF_LIST_3 | надпись розыска
#WANTED_CROSS_OFF | надпись розыска пустая
#WS_APGATE | решётка
#GEN_DOOREXT03 | дверь
#GEN_DOOREXT07 | дверь
# GEN _ DOORSHOP 02 | дверь с стеклом
#GEN_DOOREXT04 | дверь с большим стеклом
#GEN_DOORSHOP3 | дверь магазина
#CUNTGIRLDOOR | дверь
#PIZZAHIGH | поднос с пиццей
#CJ_PIZZA_1 | кусок пиццы
#CJ_PIZZA_2 | кусок пиццы
#BURGERHIGH | поднос с картошкой
#CJ_BURG_1 | бургер
#CJ_BURG_2 | бургер
#CIGAR | сигарета с дымом
#TRDCSGRGDOOR_LVS | решётка
#MD_POSTER | центральная часть a taste of come
# С R_DOOR_01 | дверь
#CR_DOOR_03 | дверь
# SHUTTER _ VEGAS | дверь гаража копов
#CR1_DOOR | решётка
#CT_GATEXR | дверь
#A51_BLASTDOORR | дверь контейнера
#A51_BLASTDOORL | дверь гаража
#A51_LABDOOR | дверь гаража
#A51_JETDOOR | дверь
#PORTAKABIN | домик на стройке
#FREIGHT_SFW_DOOR | дверь
#AB_CASDORLOK | дверь
#IMY_SHASH_WALL | кусок дома зелёного в конце игры
#TWRCRANE_M_04 | низ крана
#TWRCRANE_M_01 | верх крана
#TWRCRANE_M_02 | детали от крана
#LODCRANE_M_04 | лод низ крана
#LODCRANE_M_01 | лод верх крана
#MAGNOCRANE_01 | низ крана
#MAGNOCRANE_02 | верх крана
#MAGNOCRANE_03 | часть крана
#LODNOCRANE_01 | лод низ крана
#LODNOCRANE_02 | лод крана
#LODNOCRANE_03 | лод крана
#QUARRY_CRANEBASE | кран лас вентураса
#QUARRY_CRANE | верх крана лас вентураса
#QUARRY_CRANEARM | кусок крана
#BODYARMOUR | броня
#BRIBE | звезда от ментов
#A51_VENTCOVERB | заглушка вентиляции зоны 51
#CARRIER_DOOR_SFSE | кусок объекта
#CARRIER_LIFT2_SFSE | кусок объекта
#CARRIER_LIFT1_SFSE | кусок объекта
#GWFORUM1_LAE | кусок стадиона
#GANGSHOPS4_LAE2 | кусок домов с гров стрит
#CE_HILLSEAST06 | кусок земли с винивуда
#CUNTEGROUND23 | кусок земли с винивуда
#HILLSEAST05_LAE | кусок земли с винивуда
#K_POOLQ | кий
#K_POOLBALLCUE | кий
#K_POOLBALLSPT01 | бильярдный шар
#K_POOLBALLSPT02 | бильярдный шар
#K_POOLBALLSPT03 | бильярдный шар
#K_POOLBALLSPT04 | бильярдный шар
#K_POOLBALLSPT05 | бильярдный шар
#K_POOLBALLSPT06 | бильярдный шар
#K_POOLBALLSPT07 | бильярдный шар
#K_POOLBALL8 | бильярдный шар
#K_POOLBALLSTP01 | бильярдный шар
#K_POOLBALLSTP02 | бильярдный шар
#K_POOLBALLSTP03 | бильярдный шар
#K_POOLBALLSTP04 | бильярдный шар
#K_POOLBALLSTP05 | бильярдный шар
#K_POOLBALLSTP06 | бильярдный шар
#K_POOLBALLSTP07 | бильярдный шар
#K_POOLQ2 | кий
#CIGAR_GLOW | огонёк сигареты
#DYN_WINE_BIG | бутылка
#KB_BEER | бутылка пива
#LAEROAD30 | дорога
#CASKET_LAW | цветной гроб
#LAEJEFFERSALPHA | кусок моста
#LAELODPARK02 | кусок земли
#LAEMACPARK02 | кусок земли
#BD_WINDOW | стекло
#BREAK_WALL_1B | кусок из дома горящего девушки
#BREAK_WALL_2B | кусок из дома горящего девушки
#BREAK_WALL_3B | кусок из дома горящего девушки
#BD_FIRE1_O | какой-то огонь
#CR_AMMOBOX | ящик с боеприпасами
#BREAK_WALL_1A | кусок из дома целого девушки
#BREAK_WALL_2A | кусок из дома целого девушки
#BREAK_WALL_3A | кусок из дома целого девушки
#BD_WINDOW_SHATTER | стекло бьющееся
#SEC_KEYPAD | настенный датчик на миссии дядюшки сэма
#KMB_RAMP | железная рампа
#IMCMPTRKDRL_LAS | железная дверь левая
#IMCMPTRKDRR_LAS | железная дверь правая
#BARREL4 | красная взрывающаяся бочка
#HEALTH | пикап жизни не крутящийся
#IMY_BBOX | ящик
#IMY_LA_DOOR | дверь
#DB_AMMO | ящик
#MED_BED_8 | кровать с полками
#CR_GUNCRATE | ящик
#GUNBOX | ящик
#TMP_BIN | мусорный ящик
#AMMOTRN_OBJ | зелёный крытый груз поезда
#KMB_FRONTGATE | решётка
#WAREHOUSE_DOOR2B | гаражная дверь
#WAREHOUSE_DOOR1 | кусок стенки
#CJ_CARDBRD_PICKUP | ящик у крана в las ventyras
#NF_PED_COLL | кол педа
#CM_BOX | коробка
#FAKE_MULE_COL | кол чего-то
#CARDBOARDBOX2 | коробка
#LAE_SMOKECUTSCENE | мусорка и другие предметы без кола
#IMMMCRAN | небольшой кран
#TRNTRK8_LAS | кусок железнодорожной станции
#IMY_TRACK_BARRIER | ограждение
#KMB_SKIP | строительные работы из миссии
#STORM_DRAIN_COVER | решётка из миссии big smok' а
#WHEEL_OR1 | колесо без кола
#DYN_WOODPILE2 | дрова в форме пирамиды
#KMB_RHYMESBOOK | книга рифм мэт дога
#CJ_JUICE_CAN | банка лимонада
#DYN_ROADBARRIER_2 | дорожное ограждение
#KMB_GOFLAG | зелёный флаг без кола
#IMY_SKYLIGHT | решётка без кола
#KMB_TROLLEY | стол на колёсиках
#LXR_MOTEL_DOORSIM | дверь мотеля
#LXR_MOTELVENT | решётки вентиляции мотеля
#DYN_SCAFFOLD_4B | строительные леса
#MUNCH_DONUT | пончик сломанный на 2 части
#CHOPCOP_ARMR | рука
#CHOPCOP_LEGR | нога
#CHOPCOP_HEAD | голова копа
#CHOPCOP_TORSO | тело копа
#WD_FENCE_ANIM | забор без кола
#CHOPCOP_ARML | рука
#CHOPCOP_LEGL | нога
#DYN_SCAFFOLD_3B | строительные леса
#ROADWORKBARRIER1 | дорожное ограждение
#BRIEFCASE | коричневый кейс
#KMB_ATM1 | целый ящик для оплаты
#KMB_ATM2 | сломанный ящик для оплаты
#KMB_ATM3 | каркас ящика для оплаты
#MTSAFE | сейф без кола
#CAT2_SAFE_COL | кол сейфа
#MAN_SAFENEW | сейф открытый с деньгами
#KEV_SAFE | сейф закрытый без денег
#RIDER1_DOOR | дверь
#KMB_MARIJUANA | тюк марихуаны
#SW_HAYBREAK02 | квадратный стог сена
#GRASSPLANT | плантация марихуаны
#PARKBENCH1 | скамейка
#PORTALOO | туалет
#HUBHOLE1_SFSE | кусок земли со стройки
#HUBHOLE2_SFSE | кусок земли со стройки
#HUBHOLE3_SFSE | кусок земли со стройки
#HUBHOLE4_SFSE | кусок земли со стройки
#CLOTHESP | пикап майки
#LAMPPOST3 | фонарный столб
#CT_STALL1 | стол с зонтом
#CT_TABLE | стол с фруктами
#CHINATGARAGEDOOR | дверь гаража
#CHINA_TOWN_GATEB | тюремная решётка
#A51_SPOTBASE | деталь прожектора
#A51_SPOTHOUSING | деталь прожектора
#A51_SPOTBULB | деталь прожектора
#KMB_CONTAINER_RED | контейнер
# CJ _ CHRIS _ CRATE | контейнер открытый
# CJ _ CHRIS _ CRATE _ LD | дверь контейнера левая
#CJ_CHRIS_CRATE_RD | дверь контейнера правая
#CJ_PADLOCK | цепь с замком на контейнер
#KATANA_ANIM | катана без кола
#KATANA_LHAND | катана без кола
#MOBILE1993B | мобильник
#WONGS_GATE | большая решётка
#DYN_RAMP | деревянный трамплин
#SNIPER_ANIM | винтовка без кола
#KMB_PACKET | белый свёрток
#NTO_B_S 1 | баллон азота
#CARDBOARDBOX | коробка
#DYN_ROADBARRIER_3 | ограждение объезда
#DYN_ROADBARRIER_4 | ограждение
#DYN_DUMPSTER | мусорка с строительным хламом
#KMB_CONTAINER_BLUE | синий контейнер
#KMB_CONTAINER_YEL | жёлтый контейнер
#KMB_CONTAINER_OPEN | синий открытый контейнер
#TEMP_STINGER2 | шипы не работают
#TRAFFICCONE | красный конус
#AD_JUMP | трамплин
#GARYS_LUV_RAMP | трамплин из авто школы
#AD_ROADMARK1 | зелёные полосы
#AD_ROADMARK2 | зелёные полосы
#AD_FINISH | какой-то финиш
#MINIGUN_BASE | установка минигана
#WONGS_ERECTION | антенна zero
#WONGS_ERECTION2 | антенна zero
#RCBOMB | сломанная антенна zero
#BARREL2 | бочка не взрывающаяся
#MINI_MAGNET | мини магнит zero
#KMB_PLANK | пластина zero
#KMB_HOLDALL | сумка
#KMB_PARACHUTE | сумка с парашютом
#AMMO_CAPSULE | военная капсула
#BARREL1 | жёлтая бочка
#KB_BARREL | жёлтая бочка
#CR_CRATESTACK | ящик
#D9_RUNWAY | кусок неба !
#CARGO_TEST | самолет
#CARGO_STUFF | ящики самолёта
# CARGO _ STORE | каркас ящиков самолёта
#KMILITARY_CRATE | ящик
#KMILITARY_BASE | поддон ящика
#BLOCKPALLET | ящик
#TEMP_CRATE1 | ящик
#K_SMASHBOXES | коробки
#K_CARGO1 | железный ящик
#K_CARGO4 | ящик liberty lines
#GREEN_GLOOP | зелёная гадость
#BASEJUMP_TARGET | зелёная гадость
#DES_QUARRYGATE2 | решётка
#DES_QUARRYGATE | решётка
#CJ_DYN_PLUNGE_1 | аккумулятор
#DYNAMITE | динамит
#DES_QUARRYGATE | решётка
#CJ_DYN_PLUNGE_1 | аккумулятор
#DYNO_BOX_A | низ коробки с динамитом
#DYNO_BOX_B | верх коробки с динамитом
#PRIVATESIGN3 | знак опасности
#PRIVATESIGN1 | знак опасности
#BARRIER_4ANDY | ограждение без кола
#CJ_CHIP_MAKER_BITS | передняя часть аппарата
#CJ_CHIP_MAKER | задняя часть аппарата
#CJ_WHEELCHAIR1 | инвалидная коляска
#AB_CARCASS | замороженная туша
#AB_HOOK | крюк
#FREEZER_DOOR | дверь камеры
#CJ_MEAT_BAG_1 | мешок с крабами
#CJ_MEAT_1 | мясо нога
#CJ_MEAT_2 | мясо туша
#JET_BAGGAGE_DOOR | дверка багажа
#JET_INTERIOR | корпус самолёта
#SMLPLANE_DOOR | дверь
#JET_DOOR | лесенка самолёта
#SMASH_BOX_STAY | коробки сломанные
#SMASH_BOX_BRK | коробки
#SMASHBOXPILE | коробки
#ST_ARCH_PLAN | синий план казино Калигула
#GEN_DOORINT01 | дверь
#KMB_LOCKEDDOOR | закрытая дверь
#DYN_AIRCON | кондиционер
#SW_BIT_09 | кусок земли
#GENERATOR_BIG | генератор
#AB_VAULTDOOR | дверь хранилища
#GENERATOR_BIG_D | сломанный генератор
#CJ_MONEY_BAG | зелёная сумка с деньгами
#PARA_PACK | парашют
#CARGO_REAR | внутренняя часть самолёта
#D9_RAMP | дверь самолёта
#PARACHUTE | парашют (открытый)
#OPMANS01_CUNTE | здание в виде гриба
#CEHOLLYHIL06 | кусок земли
#SUNSET22_LAWN | кусок земли
#DRG_NU_EXT | кусок земли
#MISSILE_07_SFXR | ракета на колёсах взрывается
#KMB_KEYPAD | настенный датчик зелёный
#WATERJUMPX2 | водный трамплин
#BBALL_INGAME | чё-то падает и исчезает
#CJ_WIN_POP2 | кусок стены
#LA_FUCKCAR1 | сгоревшая машина
#LA_FUCKCAR2 | сгоревшая машина
#TARGET_FRAME | цель в амуниции
#TARGET_LLEG | цель в амуниции
#TARGET_RLEG | цель в амуниции
#TARGET_LTORSO | цель в амуниции
#TARGET_RTORSO | цель в амуниции
#TARGET_LARM | цель в амуниции
#TARGET_RARM | цель в амуниции
#TARGET_HEAD | цель в амуниции
#DEAD_TIED_COP | связанный коп
#DYN_QUARRYROCK03 | камень
#BLACKBAG2 | мешок мусора
#DYN_WOODPILE | деревянные доски
#DYN_QUARRYROCK02 | камень
#BOUY | буй
#WATERJUMP1 | водный трамплин
#LANDJUMP2 | водный трамплин
#BB_PICKUP | пикап починки
#PARA_COLLISION | квадрат повреждения
#CJ_WHEEL_1 | колесо в игровом автомате
#CJ_WHEEL_02 | колесо в игровом автомате
#CJ_WHEEL_03 | колесо в игровом автомате
#CHIP_STACK07 | фишки
#CHIP_STACK08 | фишки
#CHIP_STACK12 | фишки
#CHIP_STACK09 | фишки
#CHIP_STACK11 | фишки
#WHEEL_WEE | колесо покера
#ROULETTE_MARKER | жёлтый круглый маркер
#PEDALS | педали велосипеда
#BEACHTOWEL01 | полотенце на пляже
#KMB_BPRESS | гантели
#BEACHTOWEL03 | полотенце на пляже
#BEACHTOWEL04 | полотенце на пляже
#KMB_DUMBBELL_R | гантеля правая
#KMB_DUMBBELL_L | гантеля левая
#BBALL_COL | баскетбольный мяч
#KMB_ROCK | камень со скалы
#CHIP_STACK10 | фишки
#CHIP_STACK13 | фишки
#CHIP_STACK14 | фишки
#WHEEL_SUPPORT | труба
#WHEEL_TABLE | стол игровой
#CLICKER | фишки
#MONEY | деньги
#CJ_FF_TILL_QUE | касса
#CJ_BURG_CHAIR | стул
#CJ_PIZZA_CHAIR | стул
#CJ_PIZZA_CHAIR2 2 | кресла
#CJ_PIZZA_CHAIR3 | кресло
#TATTOO_KIT | аппарат для нанесения тату
#CJ_BARSTOOL | дверь
#CJ_BINCO_DOOR | дверь
#CJ_SUBURB_DOOR_2 | дверь
#CJ_PRO_DOOR_01 | дверь
#CJ_GAP_DOOR_ | дверь
#CJ_VICTIM_DOOR | дверь
#CJ_DS_DOOR | дверь
#PIZZALOW | поднос с едой
#PIZZAMED | поднос с едой
#PIZZA_HEALTHY | поднос с едой
#CLUCKLOW | поднос с едой
#CLUCKMED | поднос с едой
#CLUCKHIGH | дверь
#CLUCK_HEALTHY | поднос с едой
#BURGERLOW | поднос с едой
#BURGERMED | поднос с едой
#BURGER_HEALTHY | поднос с едой
#POLICE_BARRIER | коповский барьер
#KMB_SHUTTER | дверь гаража
#SFCOPDR | дверь коповского гаража

Пример:
Давайте создадим трамплин и знак предупреждения у дома СJ'я:

Copy to Clipboard
create_thread @Example1

:Example1
wait 0
model.Load(#WATERJUMPX2)
model.Load(#PRIVATESIGN3)
038B: load_requested_models

:Example1_2
wait 0
if and
model.Available(#WATERJUMPX2)
model.Available(#PRIVATESIGN3)
jf @Example1_2
object.Create(1@,#WATERJUMPX2,2504.7883,-1668.9213,12.0)
object.Angle(1@) = 270.0
object.Create(2@,#PRIVATESIGN3,2499.9551,-1675.63,12.0)
object.Angle(2@) = 270.0
end_thread


GTA SA Одежда: Ноги

Одежда: Ноги

Player.SetClothes($PLAYER_CHAR, "TEXTURE", "MODEL", BODY_PART)
Player.Build($PLAYER_CHAR)

См. также (Части тела игрока).

TEXTURE | MODEL | BODY PART | NAME
 |  | LEGS |
player_legs | legs | 2 | Legs ; (default)
worktrcamogrn | worktr | 2 | Woodland Camo
worktrcamogry | worktr | 2 | Urban Camo
worktrgrey | worktr | 2 | Gray Pants
worktrkhaki | worktr | 2 | Olive Pants
tracktr | tracktr | 2 | Sweat Pants
tracktreris | tracktr | 2 | Track Pants
jeansdenim | jeans | 2 | Blue Jeans
legsblack | legs | 2 | Black Boxers
legsheart | legs | 2 | Heart Boxers
biegetr | chinosb | 2 | Beige Pants
tracktrpro | tracktr | 2 | Track Pants
tracktrwhstr | tracktr | 2 | Black Track Pants
racktrblue | tracktr | 2 | Blue Track Pants
tracktrgang | tracktr | 2 | Green Track Pants
bbshortwht | boxingshort | 2 | Ball Shorts
boxshort | boxingshort | 2 | Boxing Shorts
bbshortred | boxingshort | 2 | Dribbler Shorts
shellsuittr | tracktr | 2 | Leisure Pants
shortsgrey | shorts | 2 | Gray Shorts
shortskhaki | shorts | 2 | Olive Shorts
chongergrey | chonger | 2 | Gray Chonglers
chongergang | chonger | 2 | Green Chonglers
chongerred | chonger | 2 | Red Chonglers
chongerblue | chonger | 2 | Blue Chonglers
shortsgang | shorts | 2 | Green Shorts
denimsgang | jeans | 2 | Green Jeans
denimsred | jeans | 2 | Red Jeans
chinosbiege | chinosb | 2 | Beige Khakis
chinoskhaki | chinosb | 2 | Olive Khakis
cutoffchinos | shorts | 2 | Beige Shorts
cutoffchinosblue | shorts | 2 | Blue Shorts
chinosblack | chinosb | 2 | Black Khakis
chinosblue | chinosb | 2 | Blue Khakis
leathertr | leathertr | 2 | Leather Pants
leathertrchaps | leathertr | 2 | Leather Chaps
suit1trgrey | suit1tr | 2 | Gray Pants
suit1trblk | suit1tr | 2 | Black Pants
cutoffdenims | shorts | 2 | Jean Shorts
suit1trred | suit1tr | 2 | Red Pants
suit1trblue | suit1tr | 2 | Blue Pants
suit1tryellow | suit1tr | 2 | Yellow Pants
suit1trgreen | suit1tr | 2 | Tweed Pants
suit1trblk2 | suit1tr | 2 | Tuxedo Pants
suit1trgang | suit1tr | 2 | Green Pants


GTA SA Одежда: обувь, цепочки, часы

Одежда: обувь, цепочки, часы

Player.SetClothes($PLAYER_CHAR, "TEXTURE", "MODEL", BODY_PART)
Player.Build($PLAYER_CHAR)

См. также (Части тела игрока).

TEXTURE | MODEL | BODY PART | NAME
 |  | SHOES |
foot | feet | 3 | Shoes ; (default)
cowboyboot2 | biker | 3 | Cowboy Boots
bask2semi | bask1 | 3 | Hi-Top Kicks
bask1eris | bask1 | 3 | Hi-Top Sneaks
sneakerbincgang | sneaker | 3 | Green Low-Tops
sneakerbincblu | sneaker | 3 | Blue Low-Tops
sneakerbincblk | sneaker | 3 | Black Low-Tops
sandal | flipflop | 3 | Sandals
sandalsock | flipflop | 3 | Sandal & Socks
flipflop | flipflop | 3 | Flip-Flops
hitop | bask1 | 3 | Mid-Top Sneaker
convproblk | conv | 3 | Black Hi-Tops
convproblu | conv | 3 | Blue Hi-Tops
convprogrn | conv | 3 | Green Hi-Tops
sneakerprored | sneaker | 3 | Red Sneakers
sneakerproblu | sneaker | 3 | Blue Sneakers
sneakerprowht | sneaker | 3 | White Sneakers
bask1prowht | bask1 | 3 | White Mid-Tops
bask1problk | bask1 | 3 | Black Mid-Tops
boxingshoe | biker | 3 | Boxing Shoes
convheatblk | conv | 3 | Black Hi-Tops
convheatred | conv | 3 | Red Hi-Tops
convheatorn | conv | 3 | Orange Hi-Tops
sneakerheatwht | sneaker | 3 | White Low-Tops
sneakerheatgry | sneaker | 3 | Gray Low-Tops
sneakerheatblk | sneaker | 3 | Black Low-Tops
bask2heatwht | bask1 | 3 | White Hi-Tops
bask2heatband | bask1 | 3 | Strap Sneakers
timbergrey | bask1 | 3 | Gray Boots
timberred | bask1 | 3 | Red Boots
timberfawn | bask1 | 3 | Brown Boots
timberhike | bask1 | 3 | Hiking Boots
cowboyboot | biker | 3 | Cowboy Boots
biker | biker | 3 | Biker Boots
snakeskin | biker | 3 | Snake Skin
shoedressblk | shoe | 3 | Black Shoes
shoedressbrn | shoe | 3 | Brown Shoes
shoespatz | shoe | 3 | Spats
 |  | NECKLACES |
dogtag | neck | 13 | Dogtags
neckafrica | neck | 13 | Africa Pendant
stopwatch | neck | 13 | Stop Watch
necksaints | neck | 13 | Saints Chain
neckhash | neck | 13 | Leaf Chain
necksilver | neck2 | 13 | Silver Cuban
neckgold | neck2 | 13 | Gold Cuban
neckropes | neck2 | 13 | Silver Chain
neckropeg | neck2 | 13 | Gold Chain
neckls | neck | 13 | L.S. Chain
neckdollar | neck | 13 | Dollar Chain
neckcross | neck | 13 | Cross Chain
 |  | WATCHES |
watchpink | watch | 14 | Pink Watch
watchyellow | watch | 14 | Yellow Watch
watchpro | watch | 14 | Pro-Laps White
watchpro2 | watch | 14 | Pro-Laps Black
watchsub1 | watch | 14 | Face Watch
watchsub2 | watch | 14 | Face Black
watchzip1 | watch | 14 | Zip Blue
watchzip2 | watch | 14 | Zip Gold
watchgno | watch | 14 | Gold Gnocchi
watchgno2 | watch | 14 | Silver Gnocchi
watchcro | watch | 14 | Gold Crowex
watchcro2 | watch | 14 | Silver Crowex


GTA SA Одежда: очки, шляпы, специальные

Одежда: очки, шляпы, специальные

Player.SetClothes($PLAYER_CHAR, "TEXTURE", "MODEL", BODY_PART)
Player.Build($PLAYER_CHAR)

См. также (Части тела игрока).

TEXTURE | MODEL | BODY PART | NAME
 |  | GLASSES |
groucho | grouchos | 15 | Joke Glasses
zorro | zorromask | 15 | Joke Mask
eyepatch | eyepatch | 15 | Eyepatch
glasses01 | glasses01 | 15 | Black Shades
glasses04 | glasses04 | 15 | Brown Shades
bandred3 | bandmask | 15 | Red Rag
bandblue3 | bandmask | 15 | Blue Rag
bandgang3 | bandmask | 15 | Green Rag
bandblack3 | bandmask | 15 | Black Rag
glasses01dark | glasses01 | 15 | Aviators
glasses04dark | glasses04 | 15 | Sun Glasses
glasses03 | glasses03 | 15 | Green Tint
glasses03red | glasses03 | 15 | Red Tint
glasses03blue | glasses03 | 15 | Blue Tint
glasses03dark | glasses03 | 15 | Black Shades
glasses05dark | glasses03 | 15 | Black Shades
glasses05 | glasses03 | 15 | Black Rim
 |  | HATS |
bandred | bandana | 16 | Red Rag Back
bandblue | bandana | 16 | Blue Rag Back
bandgang | bandana | 16 | Green Rag Back
bandblack | bandana | 16 | Black Rag Back
bandred2 | bandknots | 16 | Red Rag Front
bandblue2 | bandknots | 16 | Blue Rag Front
bandblack2 | bandknots | 16 | Black Rag Front
bandgang2 | bandknots | 16 | Green Rag Front
capknitgrn | capknit | 16 | Watch Cap
captruck | captruck | 16 | Trucker Hat
cowboy | cowboy | 16 | Cowboy Hat
hattiger | cowboy | 16 | Leopard Cowboy
helmet | helmet | 16 | Fullface Helmet
moto | moto | 16 | MotoX Helmet
boxingcap | boxingcap | 16 | Boxing Helmet
hockey | hockeymask | 16 | Hockey Mask
capgang | cap | 16 | Green Cap
capgangback | capback | 16 | Green Cap (Back)
capgangside | capside | 16 | Green Cap (Side)
capgangover | capovereye | 16 | Grn Cap (Tilt)
capgangup | caprimup | 16 | Grn Cap (Up)
bikerhelmet | bikerhelmet | 16 | Helmut
capred | cap | 16 | Red Cap
capredback | capback | 16 | Red Cap (Back)
capredside | capside | 16 | Red Cap (Side)
capredover | capovereye | 16 | Red Cap (Tilt)
capredup | caprimup | 16 | Red Cap (Up)
capblue | cap | 16 | Blue Cap
capblueback | capback | 16 | Blue Cap (Back)
capblueside | capside | 16 | Blue Cap (Side)
capblueover | capovereye | 16 | Blue Cap (Tilt)
capblueup | caprimup | 16 | Blue Cap (Up)
skullyblk | skullycap | 16 | Black Skully
skullygrn | skullycap | 16 | Green Skully
hatmancblk | hatmanc | 16 | Black Sun Hat
hatmancplaid | hatmanc | 16 | Plaid Sun Hat
capzip | cap | 16 | Cap
capzipback | capback | 16 | Cap (Back)
capzipside | capside | 16 | Cap (Side)
capzipover | capovereye | 16 | Cap Tilted
capzipup | caprimup | 16 | Cap Rim Up
beretred | beret | 16 | Red Beret
beretblk | beret | 16 | Black Beret
capblk | cap | 16 | Black Cap
capblkback | capback | 16 | Black Cap (Back)
capblkside | capside | 16 | Black Cap (Side)
capblkover | capovereye | 16 | Black Cap (Tilt)
capblkup | caprimup | 16 | Black Cap (Up)
trilbydrk | trilby | 16 | Dark Trilby
trilbylght | trilby | 16 | Light Trilby
bowler | bowler | 16 | Black Derby
bowlerred | bowler | 16 | Red Derby
bowlerblue | bowler | 16 | Blue Derby
bowleryellow | bowler | 16 | Yellow Derby
boater | boater | 16 | Gray Boater
bowlergang | bowler | 16 | Green Derby
boaterblk | boater | 16 | Black Boater
 |  | SPECIAL |
gimpleg | gimpleg | 17 | Gimp Suit
valet | valet | 17 | Valet Uniform
countrytr | countrytr | 17 | Rural Clothes
croupier | valet | 17 | Croupier
policetr | policetr | 17 | Cop
balaclava | balaclava | 17 | Ski Mask
pimptr | pimptr | 17 | Pimp Suit
garageleg | garagetr | 17 | Racing Suit
medictr | medictr | 17 | Medic Uniform


GTA SA Одежда: торс

Одежда: торс

Player.SetClothes($PLAYER_CHAR, "TEXTURE", "MODEL", BODY_PART)
Player.Build($PLAYER_CHAR)

См. также (Части тела игрока).

TEXTURE | MODEL | BODY PART | NAME
 |  | TORSO |
player_torso | torso | 0 | Torso ;(default)
vestblack | vest | 0 | Black Tank
vest | vest | 0 | White Tank
tshirt2horiz | tshirt2 | 0 | Striped T-Shirt
tshirtwhite | tshirt | 0 | White T-Shirt
tshirtilovels | tshirt | 0 | L.S. T-Shirt
tshirtblunts | tshirt | 0 | Sharps T-Shirt
shirtbplaid | shirtb | 0 | Plaid Shirt
shirtbcheck | shirtb | 0 | Checkered Shirt
field | field | 0 | Combat Jacket
tshirterisyell | tshirt | 0 | Eris T-Shirt
tshirterisorn | tshirt | 0 | Eris T-Shirt2
trackytop2eris | trackytop1 | 0 | Track Top
bbjackrim | bbjack | 0 | Rimmers Jacket
bballjackrstar | bbjack | 0 | R-Star Jacket
baskballdrib | baskball | 0 | Dribblers Vest
baskballrim | baskball | 0 | Saint's Shirt
sixtyniners | tshirt | 0 | 69ers T-Shirt
bandits | baseball | 0 | Bandits Top
tshirtprored | tshirt | 0 | ProLaps T-Shirt
tshirtproblk | tshirt | 0 | ProLaps Black T
trackytop1pro | trackytop1 | 0 | Track Top
hockeytop | sweat | 0 | Slappers Top
bbjersey | sleevt | 0 | Baseball T
shellsuit | trackytop1 | 0 | Leisure Top
tshirtheatwht | tshirt | 0 | White Heat T
tshirtbobomonk | tshirt | 0 | Bobo Ape T
tshirtbobored | tshirt | 0 | Red Bobo T
tshirtbase5 | tshirt | 0 | Base 5 T
tshirtsuburb | tshirt | 0 | Suburban T
hoodyamerc | hoodya | 0 | Mercury Hood
hoodyabase5 | hoodya | 0 | Base 5 Hood
hoodyarockstar | hoodya | 0 | Rockstar Hood
wcoatblue | wcoat | 0 | Vest & T-Shirt
coach | coach | 0 | Grn Windbreaker
coachsemi | coach | 0 | Blk Windbreaker
sweatrstar | sweat | 0 | Rockstar Sweat
hoodyAblue | hoodyA | 0 | Blue Hoody
hoodyAblack | hoodyA | 0 | Black Hoody
hoodyAgreen | hoodyA | 0 | Green Hoody
sleevtbrown | sleevt | 0 | Brown Shirt
shirtablue | shirta | 0 | Sky Blue Shirt
shirtayellow | shirta | 0 | Yellow Shirt
shirtagrey | shirta | 0 | Gray Shirt
shirtbgang | shirtb | 0 | Green Shirt
tshirtzipcrm | tshirt | 0 | Cream Logo T
tshirtzipgry | tshirt | 0 | Gray Logo T
denimfade | denim | 0 | Jean Jacket
bowling | hawaii | 0 | Bowling shirt
hoodjackbeige | hoodjack | 0 | Hooded Jacket
baskballloc | baskball | 0 | Loc-Down Vest
tshirtlocgrey | tshirt | 0 | Loc-Down T
tshirtmaddgrey | tshirt | 0 | Madd Tagg T
tshirtmaddgrn | tshirt | 0 | Green Tagg T
suit1grey | suit1 | 0 | Gray Jacket
suit1blk | suit1 | 0 | Black Jacket
leather | leather | 0 | Biker Jacket
painter | painter | 0 | Chore Coat
hawaiiwht | hawaii | 0 | Hawaiian Shirt
hawaiired | hawaii | 0 | Blue Hawaiian
sportjack | trackytop1 | 0 | Sports Jacket
suit1red | suit1 | 0 | Red Jacket
suit1blue | suit1 | 0 | Blue Jacket
suit1yellow | suit1 | 0 | Yellow Jacket
suit2grn | suit2 | 0 | Tweed Jacket
tuxedo | suit2 | 0 | Tuxedo Pants
suit1gang | suit1 | 0 | Green Jacket
letter | sleevt | 0 | Letterman Top


Sanny Builder Help: GTA SA / Специальные актеры

GTA SA / Специальные актеры

Актер | Описание
'ANDRE' | Andre
'BBTHIN' | Big Bear (thin)
'BB' | Big Bear (fat)
'CAT' | Catalina
'CESAR' | Cesar
'COPGRL1' | The naked girl 1
'COPGRL2' | Girl 1
'CLAUDE' | Claude from GTA3
'CROGRL1' | The naked girl 2
'CROGRL2' | Girl 2
'DWAYNE' | Dwayne
'EMMET' | Emmet
'FORELLI' | Forelli
'JANITOR' | mechanic
'JETHRO' | Jethro
'JIZZY' | Jizzy
'HERN' | Hernandes
'GANGRL1' | The naked girl 3
'GANGRL2' | Girl 3
'GUNGRL1' | The naked girl 4
'GUNGRL2' | Girl 4
'KENDL' | Kendel
'MACCER' | Maccer
'MADDOGG' | Mad Dog
'MECGRL1' | The naked girl 5
'MECGRL2' | Girl 5
'NURGRL1' | The naked nurse
'NURGRL2' | nurse
'NURGRL2' | nurse
'OGLOC' | OG Loc
'PAUL' | Kent Paul
'PULASKI' | Pulaski
'ROSE' | Ken Rosenberg
'RYDER1' | Ryder (1)
'RYDER2' | Ryder (2)
'RYDER3' | Ryder (3)
'SINDACO' | Sindaco
'SMOKE' | Big Smoke
'SMOKEV' | with body armour
'SUZIE' | Suzie
'SWEET' | Sweet
'TBONE' | T Bone
'TENPEN' | Tenpeni
'TORINO' | Torino
'TRUTH' | righteous man
'WUZIMU' | Wu Zi
'ZERO' | Zero


GTA SA Статистика ID

Статистика ID

Чтобы изменить статистику игрока используется вот эта команда:

0627: change_stat 225 to $VAR_1

225 - это номер статистики,которую мы хотим изменить

$VAR_1 - это число, на которое мы меняем значение статистики, оно может быть целым или дробным.
Ниже перечислены все возможные пункты статистики, не все из которых можно увидеть в игре воочию (в меню Статистика, например). Все статы делятся на 2 группы: статы с дробными значениями (их номера с 0 до 119), статы с целыми значениями (их номера больше 119).

ID | Statistics ID
0-81 | - all floats
0 | Progress made
1 | Total progress
2 | Furthest Hoop
3 | Distance travelled on foot
4 | Distance travelled by car
5 | Distance travelled by motorbike
6 | Distance travelled by boat
7 | Distance travelled by golf cart
8 | Distance travelled by helicopter
9 | Distance travelled by plane
10 | Longest Wheelie distance
11 | Longest Stoppie distance
12 | Longest 2 wheels distance
13 | Weapon Budget
14 | Fashion Budget
15 | Property Budget
16 | Auto Repair and Painting Budget
17 | Longest Wheelie time
18 | Longest Stoppie time
19 | Longest 2 wheels time
20 | Food Budget
21 | Fat
22 | Stamina
23 | Muscle
24 | Max Health
25 | Sex appeal
26 | Distance travelled by swimming
27 | Distance travelled by bicycle
28 | Distance travelled on treadmill
29 | Distance travelled on exercise bike
30 | Tattoo budget
31 | Hairdressing budget
32 | Girlfriend budget
33 | Prostitute budget
34 | Furniture budget
35 | Money spent gambling
36 | Money made from pimping
37 | Money won gambling
38 | Biggest gambling win
39 | Biggest gambling loss
40 | Largest burglary swag
41 | Money made from burglary
42 | Money spent building property
43 | Unused
44 | Longest treadmill time
45 | Longest exercise bike time
46 | Heaviest weight on bench press
47 | Heaviest weight on dumbbells
48 | Best time in 8-Track
49 | BMX best time
50 | Lightest weight
51 | Longest chase time with 5 or more stars
52 | Last chase time with 5 or more stars
53 | Wage bill
54 | Strip club budget
55 | Car modification budget
56 | Time spent shopping
57 | Time spent gambling
58 | Time spent on longest mission
59 | Time spent on quickest mission
60 | Average mission time
61 | Drugs budget
62 | Total shopping budget
63 | Time spent underwater
64 | Total respect
65 | Girlfriend respect
66 | Clothes respect
67 | Fitness respect
68 | Respect
69 | Pistol Skill
70 | Silenced Pistol Skill
71 | Desert Eagle Skill
72 | Shotgun Skill
73 | Sawn-Off Shotgun Skill
74 | Combat Shotgun Skill
75 | Machine Pistol Skill
76 | SMG Skill
77 | AK-47 Skill
78 | M4 Skill
79 | Rifle Skill
80 | Appearance
81 | Gambling
82-119 | Unused
120-337 | - all integers
120 | People wasted by others
121 | People you've wasted
122 | Road Vehicles destroyed
123 | Boats destroyed
124 | Planes & Helicopters destroyed
125 | Cost of property damaged
126 | Bullets fired
127 | Kgs of explosives used
128 | Bullets that hit
129 | Tires popped with gunfire
130 | Number of headshots
131 | Total number of wanted stars attained
132 | Total number of wanted stars evaded
133 | Times busted
134 | Days passed in game
135 | Number of hospital visits
136 | Safehouse visits
137 | Times cheated
138 | Vehicle Resprays
139 | Maximum INSANE Jump distance
140 | Maximum INSANE Jump height
141 | Maximum INSANE Jump flips
142 | Maximum INSANE Jump rotation
143 | Best INSANE stunt awarded
144 | Unique Jumps found
145 | Unique Jumps done
146 | Mission attempts
147 | Missions passed
148 | Total number of missions in game
149 | Cash made in a Taxi
150 | Passengers dropped off
151 | People saved in an Ambulance
152 | Criminals killed on Vigilante Mission
153 | Total fires extinguished
154 | Packages Delivered
155 | Assassinations
156 | Last dance score
157 | Highest Vigilante Mission level
158 | Highest Paramedic Mission level
159 | Highest Firefighter Mission level
160 | Driving skill
161 | Number of Truck missions passed
162 | Money made in Truck
163 | Recruited gang members killed
164 | Armor
165 | Energy
166 | Photographs Taken
167 | Rampages attempted
168 | Rampages passed
169 | Flight time
170 | Times drowned
171 | Number of girls pimped
172 | Best position in 8-Track
173 | Time on jetpack
174 | Shooting range levels passed
175 | Most cars parked on 'Valet Parking'
176 | Kills since last checkpoint
177 | Total legitimate kills
178 | Number of 'Bloodring' kills
179 | Total time in bloodring
180 | No more hurricanes Flag
181 | City unlocked
182 | Number of Police bribes
183 | Number of cars stolen
184 | Current number of girlfriends
185 | Number of disastrous dates
186 | Number of girls dated
187 | Number of times scored with a girl
188 | Number of successful dates
189 | Number of girls dumped
190 | Number of prostitutes visited
191 | Number of houses burgled
192 | Number of safes cracked
193 | Burgular status
194 | Number of stolen items sold
195 | Number of eight balls in pool
196 | Total number of wins playing pool
197 | Total number of losses playing pool
198 | Times visited the gym
199 | Body type
200 | Number of meals eaten
201 | Money made in Quarry
202 | Time taken to Complete Quarry
203 | Number of furniture purchased
204 | Favorite console game
205 | Highest civilian peds killed on Rampage
206 | Highest police peds killed on Rampage
207 | Highest civilian vehicles destroyed on Rampage
208 | Highest police vehicles destroyed on Rampage
209 | Highest number of tanks destroyed on Rampage
210 | Pimping level
211 | Kickstart best score
212 | Best lap time in 8-Track
213 | Number of vehicles exported
214 | Number of vehicles imported
215 | Highest basketball score
216 | Fires started
217 | Amount of drugs sold
218 | Amount of drugs bought
219 | Best lap time in dirt track
220 | Best time in dirt track
221 | Best position in dirt track
222 | NRG-500 best time
223 | Flying skill
224 | Respect Mission
225 | Lung capacity
226 | Game gore rating
227 | Game sex rating
228 | Respect Mission Total
229 | Bike skill
230 | Cycling skill
231 | Snapshots taken
232 | Total snapshots
233 | Luck
234 | Territories taken over
235 | Territories lost
236 | Territories held
237 | Highest number of territories held
238 | Gang members recruited
239 | Enemy gang members killed
240 | Friendly gang members killed
241 | Horseshoes collected
242 | Total horseshoes
243 | Oysters collected
244 | Total oysters
245 | Calories
246 | 2 Player Rampage best time
247 | 2 Player Car Rampage best time
248 | 2 Player On Foot Rampage best time
249 | 2 Player Chopper Rampage best time
250 | 2 Player Bike Rampage best time
251 | 'Keepie Uppy' best time
252 | Progress with Denise
253 | Progress with Michelle
254 | Progress with Helena
255 | Progress with Barbara
256 | Progress with Katie
257 | Progress with Millie
258 | Best position in Lowrider Race
259 | Best time in Lowrider Race
260 | Best position in Little Loop
261 | Best time in Little Loop
262 | Best position in Backroad Wanderer
263 | Best time in Backroad Wanderer
264 | Best position in City Circuit
265 | Best time in City Circuit
266 | Best position in Vinewood
267 | Best time in Vinewood
268 | Best position in Freeway
269 | Best time in Freeway
270 | Best position in Into the Country
271 | Best time in Into the Country
272 | Best position in Badlands A
273 | Best time in Badlands A
274 | Best position in Badlands B
275 | Best time in Badlands B
276 | Best position in Dirtbike Danger
277 | Best time in Dirtbike Danger
278 | Best position in Bandito County
279 | Best time in Bandito County
280 | Best position in Go-Go-Kart
281 | Best time in Go-Go-Kart
282 | Best position in San Fierro Fastlane
283 | Best time in San Fierro Fastlane
284 | Best position in San Fierro Hills
285 | Best time in San Fierro Hills
286 | Best position in Country Endurance
287 | Best time in Country Endurance
288 | Best position in SF to LV
289 | Best time in SF to LV
290 | Best position in Dam Rider
291 | Best time in Dam Rider
292 | Best position in Desert Tricks
293 | Best time in Desert Tricks
294 | Best position in LV Ringroad
295 | Best time in LV Ringroad
296 | Best time in World War Aces
297 | Best time in Barnstorming
298 | Best time in Military Service
299 | Best time in Chopper Checkpoint
300 | Best time in Whirly Bird Waypoint
301 | Best time in Heli Hell
302 | Drive-thru mission accomplished
303 | Management Issues mission accomplished
304 | 555 WE TIP mission accomplished
305 | Yay Ka-Boom-Boom mission accomplished
306 | Fish in a Barrel mission accomplished
307 | Breaking the Bank at Caligula's mission accomplished
308 | A Home In The Hills mission accomplished
309 | maybe set riot mode
310 | Ryder's mission Robbing Uncle Sam accomplished
311 | Mike Toreno mission accomplished
312 | Architectural Espionage mission accomplished
313 | Jizzy mission accomplished
314 | Reuniting the Families mission accomplished
315 | Small Town Bank mission accomplished
316 | Photo Opportunity mission accomplished
317 | Don Peyote mission accomplished
318 | Local Liquor Store mission accomplished
319 | Badlands mission accomplished
320 | Playing time
321 | Hidden Packages found
322 | Tags sprayed
323 | Least favorite gang
324 | Gang members wasted
325 | Criminals wasted
326 | Most Favorite Radio Station
327 | Least Favorite Radio Station
328 | Current weapon skill
329 | Weapon skill levels
330 | Pilot ranking
331 | Strongest Gang
332 | 2nd strongest gang
333 | 3rd strongest gang
334 | Money lost gambling
336 | Gang strength
337 | Territory under control
338 | Are you going to San Fierro? mission accomplished
339 | High Noon mission accomplished
340 | The Green Sabre mission accomplished
341 | maybe Catalina meeting
342 | maybe Wu Zi meeting
343 - 344 | - Unused

Теперь описав все статистики игрока, его можно хорошенько прокачать: мускулы, привлекательность, умение обращаться с оружеем...

Copy to Clipboard
create_thread @MaxPoints // создаём поток с названиeм MaxPoints

:MaxPoints // начинаем поток
thread 'MPoint'
// вот этой командой присваеваем потоку имя, чтобы при декомпиляции
// можно было сразу найти свой поток.
wait 3000
062A: change_stat 165 to 2000.0
// Тут изменяем статистики,если интерестно, то посмотрите сами, какие
062A: change_stat 23 to 1000.0
062A: change_stat 21 to 0.0
0629: change_stat 22 to 1000
062A: change_stat 80 to 2000.0
062A: change_stat 225 to 2000.0
062A: change_stat 223 to 1000.0
062A: change_stat 229 to 1000.0
062A: change_stat 230 to 2000.0
062A: change_stat 24 to 1000.0
062A: change_stat 69 to 1000.0
062A: change_stat 70 to 1000.0
062A: change_stat 71 to 1000.0
062A: change_stat 72 to 1000.0
062A: change_stat 73 to 1000.0
062A: change_stat 74 to 1000.0
062A: change_stat 75 to 1000.0
062A: change_stat 76 to 1000.0
062A: change_stat 77 to 1000.0
062A: change_stat 78 to 1000.0
062A: change_stat 160 to 1000.0
wait 100
Actor.Health($PLAYER_ACTOR) = 1000
// Если мы увеличили макс. здоровье, то надо
// установить уровень здоровья на максимальный
0627: change_stat 243 to 50 // стат устриц
0627: change_stat 241 to 50 // стат подков
0627: change_stat 231 to 50 // стат фотографий
end_thread // заканчиваем поток


GTA SA Стрижки

Стрижки

Player.SetClothes($PLAYER_CHAR, "TEXTURE", "MODEL", BODY_PART)
Player.Build($PLAYER_CHAR)

См. также (Части тела игрока).

TEXTURE | MODEL | BODY PART | Name
afro | afro | 1 | Afro
afrobeard | afro | 1 | Afro & Beard
afroblond | afro | 1 | Blonde Afro
afrogoatee | afro | 1 | Afro & Goatee
afrotash | afro | 1 | Afro & Stash
bald | head | 1 | Bald Head
baldbeard | head | 1 | Bald & Beard
baldgoatee | head | 1 | Bald & Goatee
baldtash | head | 1 | Bald & Stash
beard | head | 1 | Cesar & Beard
cornrows | cornrows | 1 | Cornrow
cornrowsb | cornrows | 1 | Blonde Cornrow
elvishair | elvishair | 1 | Elvis Hair
flattop | flattop | 1 | FlatTop
goatee | head | 1 | Cesar & Goatee
groovecut | groovecut | 1 | Groove Cut
hairblond | head | 1 | Blonde Hair
hairblue | head | 1 | Blue Hair
hairgreen | head | 1 | Green Hair
hairpink | head | 1 | Pink Hair
hairred | Head | 1 | Red Hair
highafro | highafro | 1 | High Afro
highfade | head | 1 | High Fade
jhericurl | jheri | 1 | Jheri Curl
mohawk | mohawk | 1 | Mowhawk
mohawkbeard | mohawk | 1 | Mohawk & Beard
mohawkblond | mohawk | 1 | Blonde Mowhawk
mohawkpink | mohawk | 1 | Pink Mowhawk
player_face | head | 1 | Cesar
slope | slope | 1 | Slope
tash | head | 1 | Cesar & Stash
tramline | tramline | 1 | Detail Cut
wedge | wedge | 1 | Wedge


GTA SA Татуировки

Татуировки

Player.SetClothes($PLAYER_CHAR, "TEXTURE", "MODEL", BODY_PART)
Player.Build($PLAYER_CHAR)

См. также (Части тела игрока).

TEXTURE | MODEL | BODY PART | NAME
4weed | 4WEED | 4 | Weed
4rip | 4RIP | 4 | Grave
4spider | 4SPIDER | 4 | Spider
5gun | 5GUN | 5 | Gun
5cross | 5CROSS | 5 | Cross
5cross2 | 5CROSS2 | 5 | Rose
5cross3 | 5CROSS3 | 5 | Clown
6aztec | 6AZTEC | 6 | Aztec
6crown | 6CROWN | 6 | Web
6clown | 6CLOWN | 6 | Clown
6africa | 6AFRICA | 6 | Africa
7cross | 7CROSS | 7 | Cross
7cross2 | 7CROSS2 | 7 | Cross
7cross3 | 7CROSS3 | 7 | Cross
7mary | 7MARY | 7 | Mary
8sa | 8SA | 8 | Grove St .
8sa2 | 8SA2 | 8 | San Andreas
8sa3 | 8SA3 | 8 | San Fierro
8westside | 8WESTSD | 8 | Westside
8santos | 8SANTOS | 8 | Los Santos
8poker | 8POKER | 8 | Card
8gun | 8GUN | 8 | Gun
9crown | 9CROWN | 9 | Crown
9gun | 9GUN | 9 | Gun
9gun2 | 9GUN2 | 9 | Gun
9homeboy | 9HOMBY | 9 | Homeboy
9bullet | 9BULLT | 9 | Bullet
9rasta | 9RASTA | 9 | Rasta
10ls | 10LS | 10 | Los Santos
10ls2 | 10LS2 | 10 | Los Santos
10ls3 | 10LS3 | 10 | Los Santos
10ls4 | 10LS4 | 10 | Los Santos
10ls5 | 10LS5 | 10 | Los Santos
10og | 10OG | 10 | O.G.
10weed | 10WEED | 10 | Grove
11grove | 11GROVE | 11 | Grove
11grove2 | 11GROV2 | 11 | Grove
11grove3 | 11GROV3 | 11 | Grove
11dice | 11DICE | 11 | Dice
11dice2 | 11DICE2 | 11 | Dice
11jail | 11JAIL | 11 | Jail
11godsgift | 11GGIFT | 11 | God's Gift
12angels | 12ANGEL | 12 | Angel
12mayabird | 12MAYBR | 12 | Mayan Bird
12dagger | 12DAGER | 12 | Dagger
12bandit | 12BNDIT | 12 | Masks
12cross7 | 12CROSS | 12 | Cross
12mayaface | 12MYFAC | 12 | Mayan Face


GTA SA Типы зон

Типы зон

Вся территория Сан Андреаса разделена на зоны, зона - это клочок земли , на котором действуют свои праила, т.е. на этой территории ходят актёры и ездят машины только определённого для данной территории типа. Контроль банд тоже делиться по этим же зонам. Вот список команд, которые можно применять к зонам:

Команда определяющая тип зоны,от типа зависит,какие машины и актёры там будут появляться:

0767: set_zone 'MARKST' type 14

'MARKST' - имя зоны, имена зон и их координаты приведены ниже .

14 - тип зоны,вот все типы зон,которые есть в Сан Андреасе:

Чтобы зону контроллировали какие-либо гангстеры, используем вот эту команду:

076C: set_zone 'ELCO1' controlled_by_gang 2 density 40

'ELCO1' - имя зоны
2 - тип гангстеров,вот типы :
0 - Баллас
2 - Бандиты Грув Стрит
3 - Лос Сантос вагос
40 - радиус зоны или плотность гангстеров на ней

076A: set_zone 'CHC1A' to_pedgroup 4 - устанавливает зоне опред. вид актёров.

0879: toggle_gang_wars 1 - включает войну между бандами, территории которых рядом.

0A24: toggle_military_zones_wanted_level 1 - включает вам макс. уровень розыска, если вы залезли на какую-либо из военных зон (военнаая база или авианосец)

09E4: toggle_aircraftcarrier_sam 1

Вот все типы зон:
0 | Бизнес
1 | Пустыня
2 | Зона развлечений
3 | Сельская местность
4 | Богатая жилая зона
5 | Жилая зона среднего уровня богатости
6 | Бедная жилая зона
7 | Бандитская зона
8 | Пляж
9 | Магазины
10 | Парк
11 | Промышленная зона
12 | Деловая зона
13 | Деловая зона магазинов
14 | Зона очень хороших магазинов
15 | Богатая уединённая жилая зона
16 | Аэропорт
17 | Гольф-клуб
18 | Заводы, вне городов
19 | Взлётно-посадочная полоса аэропорта

Если в какой либо зоне есть своя музыка, например соревнования лоурайдеров... , то можно эту музыку отключить или наоборот, т.е. включить:

0917: audio_zone 'LOWRIDE' enable_sound 1

'LOWRIDE' - имя музыкальной зоны, имена ниже

1 - включить музыку , если 0 , то выключить.

Вот все аудио зоны игры:

OTB, 24, 1, 817.121, -2.78276, 1001.62, 838.373, 12.6744, 1009.04
clothgp, 54, 1, 142.539, -102.507, 1000.17, 184.344, -64.2128, 1012.64
CSprt, 59, 1, 194.849, -144.97, 1001.52, 218.016, -124.358, 1007.22
Csdesgn, 56, 1, 194.716, -17.2763, 1000, 231.977, 2.30468, 1009.28
Csexl, 26, 1, 192.996, -173.041, 998.588, 219.548, -149.881, 1005.59
Fdchick, 44, 1, 361.299, -15.7529, 1000.05, 382.863, -1.76698, 1007.15
Fdburg, 44, 1, 357.348, -80.0982, 1000, 385.773, -53.4915, 1006.2
Fdpiza , 44, 1, 365.41, -137.368, 1000, 382.554, -110.282, 1006
Fddonut, 44, 1, 369.139, -197.672, 998.688, 384.387, -174.151, 1004.39
FDrest1, 37, 1, 437.03, -23.961, 998.295, 462.047, -2.50022, 1008.3
rest2, 44, 1, 437.028, -70.3095, 995.308, 453.113, -47.9337, 1005.31
diner1, 44, 1, 430.883, -93.8502, 996.641, 462.261, -77.9169, 1003.36
diner2, 44, 1, 441.06, -112.256, 997.499, 462.047, -102.574, 1002.8
bar1, 29, 1, 471.534, -29.927, 997.934, 509, 1.02761, 1009.73
ammun1, 48, 1, 271.514, -55.4682, 1000, 352.134, -3.80515, 1011.16
ammun2, 48, 1, 271.514, -94.279, 1001.16, 330.049, -55.4682, 1011.16
ammun3, 48, 1, 280.105, -115.931, 1000, 302.03, -100.071, 1005.3
ammun4, 48, 1, 271.977, -147.912, 997.08, 321.869, -122.254, 1010.18
ammun5, 48, 1, 269.769, -173.992, 997.274, 326.533, -155.365, 1007.27
STORE, 54, 1, 195.959, -115.936, 1002.7, 220.53, -93.2475, 1012.7
Hip-Hop, 58, 1, 193.986, -55.8739, 995.887, 218.469, -30.5802, 1009.29
Gang, 26, 1, 2310.45, -1191.18, 1026.34, 2358.44, -1168.72, 1036.34
Burhous, 26, 1, 2800.26, -1180.17, 1023.78, 2822.91, -1155.75, 1033.78
Motel1, 26, 1, 2175.24, -1204.5, 1023.75, 2260.84, -1133.86, 1038.83
Carter1, 50, 1, 2515.48, -1329.43, 1021.92, 2586.11, -1276.02, 1053.67
JetInt, 36, 1, -0.847597, 20.9498, 1198.14, 5.5024, 38.3711, 1202.74
Carls, 26, 1, 2487.84, -1714.16, 1012.13, 2504.68, -1686.43, 1022.13
Morrom, 26, 1, 441.517, 504.739, 999.499, 458.6, 517.047, 1005
PDOME, 34, 1, 2551.6, -1307.4, 1053.61, 2570.69, -1298.9, 1059.53
DANANG, 15, 1, -2476.34, 1534.17, 32.7057, -2468.94, 1555.32, 35.7157
DANANG , 15, 1, -2479.38, 1537.89, 32.7057, -2476.34, 1551.73, 35.7157
destr1, 41, 1, -1629.51, 1114.31, 1000, -1175.64, 1392.18, 1184.96
Bowl, 41, 1, -1629.51, 834.818, 1000, -1175.64, 1112.7, 1184.96
OVAL, 41, 1, -1629.51, -27.045, 1000, -1175.64, 278.62, 1184.96
8stad, 41, 1, -1629.51, -353.222, 1000, -1175.64, -50.3353, 1184.96
dirtsta, 41, 1, -1629.51, -816.208, 1000, -1175.64, -504.985, 1184.96
destr2, 41, 1, -1629.51, 1458.29, 1000, -1175.64, 1736.17, 1184.96
AWARDS, 10, 0, 1022.89, -1124.57, 23.3801, 75
BEACH, 5, 0, 535.964, -1887.77, 2.29791, 89.4802
LOWRIDE, 13, 0, 1792.2, -1921.04, 12.3925, 75
Bar2, 58, 1, 484.777, -90.5392, 995.544, 516.78, -63.5023, 1005.3
tattoo, 58, 1, -208.518, -13.1026, 1000, -194.903, 0.334491, 1007.1
sexshop, 26, 1, -118.731, -30.6256, 998.673, -94.2415, -5.49561, 1006.57
seven11, 21, 1, -40.252, -36.2282, 1000, -20.2452, 1.15293, 1010
seven11, 21, 1, -16.7722, -36.2282, 1000, 15.2386, 1.15293, 1010
seven11, 21, 1, -39.6959, -63.1184, 1000, -14.8674, -46.2969, 1010
seven11, 21, 1, -40.25, -95.2795, 1000, -11.2008, -69.3744, 1010
seven11, 21, 1, -40.25, -145.865, 1000, -11.2008, -119.96, 1010
seven11, 21, 1, -38.3214, -192.049, 1000, -0.266899, -166.144, 1010
House, 26, 1, 214.681, 1282.94, 1078.47, 235.428, 1296.18, 1088.47
House, 26, 1, 248.148, 1280.34, 1078.47, 270.348, 1298.77, 1088.47
House, 26, 1, 248.148, 1233.72, 1078.47, 270.348, 1260.26, 1088.47
House, 26, 1, 214.554, 1233.72, 1078.47, 236.753, 1260.26, 1088.47
House, 26, 1, 217.911, 1182.72, 1078.47, 248.801, 1214.57, 1088.47
lahss6, 26, 1, 215.098, 1138.12, 1078.47, 231.779, 1162.64, 1088.47
lahsb3, 26, 1, 223.274, 1102.6, 1078.47, 252.799, 1124.42, 1088.47
lahsb1, 26, 1, 217.622, 1061.84, 1078.47, 251.28, 1089.99, 1091.27
lahsb2, 26, 1, 216.074, 1014.13, 1078.47, 260.839, 1054.1, 1091.57
vghss1, 26, 1, 281.763, 1468.87, 1078.47, 307.958, 1491.36, 1088.47
House, 26, 1, 316.311, 1466.74, 1078.47, 342.505, 1493.49, 1088.47
House, 26, 1, 369.161, 1450.53, 1078.47, 388.284, 1474.59, 1088.47
House, 26, 1, 352.252, 1406.71, 1078.47, 381.7, 1433.66, 1088.47
vghsb1, 26, 1, 432.813, 1392.39, 1078.47, 462.262, 1422.03, 1088.47
vghsb3, 26, 1, 473.153, 1394.19, 1078.47, 504.369, 1427.09, 1088.47
sfhss1, 26, 1, -57.2451, 1392.48, 1080.77, -32.0049, 1417.22, 1090.77
sfhss2, 26, 1, -76.5638, 1342.39, 1077.2, -50.5664, 1369.84, 1087.2
vghsm3, 26, 1, 13.7811, 1329.3, 1080.77, 39.7785, 1356.75, 1092.57
vghsm2, 26, 1, 11.5303, 1394.48, 1080.77, 37.5277, 1421.94, 1090.77
sfhsb2, 26, 1, 79.2551, 1362.19, 1080.77, 105.252, 1389.65, 1092.97
sfhsb3, 26, 1, 72.2893, 1313.45, 1080.77, 99.0744, 1348.32, 1092.47
sfhsb1, 26, 1, 132.241, 1361.97, 1080.77, 156.08, 1392.65, 1092.57
House, 26, 1, 299.587, 1110.51, 1079.88, 339.742, 1134.23, 1089.93
GYM1, 61, 1, 751.216, -12.2984, 997.756, 779.818, 19.0384, 1007.76
GYM2, 26, 1, 751.726, -56.1599, 997.756, 785.017, -12.9777, 1009.26
GYM3, 59, 1, 751.726, -84.3097, 997.756, 785.017, -56.6731, 1009.26
Brothel, 66, 1, 926.527, -20.8921, 995.096, 978.96, 11.6384, 1015.1
Brothl2, 66, 1, 926.527, -66.7347, 995.096, 978.96, -34.2041, 1015.1
Casino, 17, 1, 1109.12, -18.9072, 998.587, 1149.37, 14.7279, 1008.59
LASTRIP, 66, 1, 1189.75, -19.378, 998.587, 1230, 22.0627, 1008.59
STRIP2, 66, 1, 1200.05, -48.9516, 998.587, 1222.19, -20.772, 1008.59
Genwrhs, 50, 1, 1241.59, -79.3579, 998.587, 1320.52, 18.21, 1008.59
police1, 39, 1, 179.99, 132.814, 999.625, 305.097, 200.052, 1019.63
police2, 39, 1, 212.031, 101.112, 996.147, 280.84, 130.697, 1016.15
police3, 39, 1, 209.279, 56.9806, 996.332, 283.592, 96.3581, 1016.33
Barbers, 61, 1, 406.188, -28.0137, 998.295, 419.948, -8.48435, 1008.3
Barbers, 59, 1, 406.986, -58.1445, 998.295, 417.718, -46.0363, 1008.3
Barbers, 57, 1, 415.112, -89.1412, 998.295, 425.845, -71.1, 1008.3
MADDOGl, 57, 0, 1211.49, -845.642, 1068.9, 1313.38, -747.984, 1108.9
tsdiner, 37, 1, 669.257, -472.145, -28.6995, 693.872, -439.763, -18.6995
wuzibet, 26, 1, -2173.09, 634.048, 1050.99, -2156.1, 648.195, 1060.99
rcplay, 56, 1, -2247.29, 125.322, 1034.4, -2216.43, 139.23, 1041.5
pdomes, 34, 1, -2698.98, 1385.34, 900.739, -2626.64, 1437.78, 930.339
drives, 26, 1, -2038.22, -123.696, 1029.7, -2019.59, -98.1206, 1041.3
Cargo, 51, 1, 305.443, 968.374, 1940, 326.247, 1048.91, 1966.7
Plandep, 25, 1, 313.076, 137.255, 1000.96, 398.629, 221.354, 1032.76
abattoi, 20, 1, 923.51, 2091.8, 997.445, 974.866, 2185.65, 1037.45
Tricas, 17, 1, 1914.26, 957.671, 989.878, 2027.27, 1076.03, 1012.38
Bikesch, 26, 1, 1484.23, 1299.92, 1090.63, 1504.47, 1312.94, 1098.14
sfhsm1, 26, 1, -303.948, 1465.71, 1081.68, -277.594, 1484.1, 1093.78
sfhsm2, 26, 1, -281.497, 1443.78, 1081.58, -255.144, 1462.17, 1093.68
svssfbg, 26, 1, 2179.77, -1228.5, 1046.73, 2205.14, -1196.51, 1056.73
svssfmd, 26, 1, 2245.62, -1226.58, 1046.73, 2279.36, -1198.43, 1056.73
svssfsm, 26, 1, 2301.8, -1221.66, 1046.73, 2324.74, -1203.35, 1056.73
svlabig, 26, 1, 2306.04, -1153.22, 1046.73, 2342.98, -1132.11, 1058.43
svlasm1, 26, 1, 2274.35, -1143.58, 1046.73, 2289.87, -1132.1, 1058.43
svlabmd, 26, 1, 2356.1, -1144.62, 1046.73, 2379.37, -1116.96, 1058.43
svhot1, 26, 1, 2222.95, -1120.32, 1046.73, 2243.27, -1102.59, 1058.43
svvgho2, 26, 1, 2231.51, -1090.57, 1046.73, 2248.38, -1062.55, 1058.43
svcunt, 26, 1, 2327.24, -1088.08, 1046.73, 2346.97, -1058.94, 1058.43
svgnmt1, 26, 1, 2242.16, -1144.4, 1046.73, 2257.68, -1132, 1058.43
svgnmt2, 26, 1, 2258.13, -1144.4, 1046.73, 2271.78, -1132, 1058.43
svvghot, 26, 1, 2198.75, -1083.41, 1046.73, 2224.39, -1064.91, 1058.43
STMARKS, 4, 1, -797.537, 483.725, 1359.26, -774.834, 512.337, 1393.49
tatto2, 58, 1, -208.518, -31.1169, 1000, -194.903, -17.6798, 1007.1
tatto3, 58, 1, -208.518, -47.8647, 1000, -194.903, -34.4276, 1007.1
DANANGI, 12, 1, -2441.8, 1531.45, 0.746528, -2365.2, 1558.44, 15.4446
MAFCAST, 26, 1, 2256.54, 1615.19, 1082.42, 2274.64, 1678.92, 1097.52
MAFCAST, 26, 1, 2175.1, 1617.5, 1041.3, 2193.2, 1636.62, 1056.4
DAM, 23, 1, -965.662, 1844.33, 2.54777, -935.481, 1956.38, 30.676
cupboar, 30, 1, 247.632, -46.4901, 999.224, 261.853, -34.1703, 1009.22
MAFCASB, 26, 1, 2123.85, 1541.66, 990.651, 2236.98, 1647.89, 1003.45
MAFACS , 17, 1, 2125.62, 1530.7, 1003.45, 2299.84, 1722.26, 1022.65
Amphib, 12, 1, -1439.79, 1478.97, -1.00996, -1385.81, 1499.7, 6.06402
Amphidr, 15, 1, -1384.85, 1482.83, 0.212394, -1369.5, 1496.72, 9.73239
Amphidr, 15, 1, -1385.58, 1483.97, 9.73239, -1374.34, 1495.78, 12.7936
area69, 15, 1, 209.285, 1812.14, 5.55343, 230.154, 1832.85, 11.6534
PDOME, 34, 1, 2551.6, -1290.47, 1053.61, 2570.69, -1280.12, 1059.53
Carter1, 50, 1, 2515.48, -1329.43, 1053.67, 2586.11, -1276.02, 1073.03
Toreno, 26, 1, -692.686, 931.812, 11.0342, -683.524, 943.421, 18.8662
Grayimp, 50, 1, 2115.28, -2295.22, 11.3153, 2181.37, -2228.81, 25.1478
uncleSa, 50, 1, 2774, -2430.34, 11.4556, 2802.05, -2405.02, 22.3996
uncleSa, 50, 1, 2774, -2468.22, 11.4556, 2802.05, -2442.9, 22.3996
bankbit, 26, 1, 2301.27, -18.7446, 25.3056, 2321.61, 1.30569, 31.3056
upupawa, 50, 1, 2539.05, 2804.09, 8.47018, 2616.48, 2850.96, 26.7368
verdant, 26, 1, 411.5, 2534.13, 8.07921, 425.857, 2543.7, 15.1792
vertica, 12, 1, -1465.48, 488.507, -3.05748, -1287.22, 514.464, 10.1613
vertica, 15, 1, -1297.61, 488.516, 10.1971, -1287.22, 493.324, 15.5971
vertica, 12, 1, -1465.48, 488.777, 10.1613, -1298.24, 514.464, 16.7205
vertica, 12, 1, -1298.24, 493.114, 10.1613, -1287.22, 514.464, 16.7203
Crack, 50, 1, -2190.02, -269.839, 34.4413, -2138.88, -226.149, 45.4413
crack2, 50, 1, -2190.02, -226.149, 34.8272, -2181.13, -204.931, 41.5372
chips, 50, 1, 1055.19, 2076.12, 8.53484, 1095.91, 2145.42, 18.5348
chips, 50, 1, 1055.19, 2145.42, 8.93499, 1068.77, 2155.81, 18.935
chips, 50, 1, 1095.91, 2099.22, 6.66854, 1106.89, 2122.32, 16.6685
chips, 50, 1, 1064.2, 2136.85, 8.61189, 1082.66, 2151.34, 18.6119
Atrium, 26, 1, 1699.57, -1684.56, 16.3552, 1743.05, -1637.25, 44.0552
UFOBAR, 53, 1, -235.121, 1391.18, 26.766, -215.13, 1414.33, 31.096
A69, 19, 1, 201.82, 1784.73, -31.272, 369.31, 1908.79, 13.493
MADDOGS, 26, 1, 1211.14, -846.778, 1068.9, 1314.14, -746.778, 1108.9
GF1, 57, 1, 242.378, 299.46, 997.122, 251.372, 308.201, 1003.86
GF2, 59, 1, 265.627, 301.104, 997.122, 274.622, 309.845, 1003.86
GF3, 53, 1, 278.413, 302.827, 997.122, 294.424, 312.355, 1006.89
GF4, 58, 1, 296.663, 299.17, 997.122, 312.674, 316.035, 1010.22
GF5, 26, 1, 315.87, 301.341, 997.122, 328.678, 318.988, 1007.21
GF6, 26, 1, 341.567, 299.189, 997.122, 352.326, 313.483, 1007.21

Не знаю почему, но свою зону можно добавить только командой типа

AWARDS, 10, 0, 1022.89, -1124.57, 23.3801, 75.0

10 - музыка зоны,вот часть:
52 Playback FM
53 K-ROSE
54 K-DST
55 Bounce FM
56 SFUR
57 Radio Los Santos
58 Radio X
59 CSR
60 K-JAH West
61 MasterSounds
62 WCTR
0 - её работа с начала,ставьте тут всегда 0,а потом уже включайте скриптом
1022.89 , -1124.57 , 23.3801 - координаты её центра
75.0 - радиус от центра,в котором зона действует.

В данной таблице приведены имена и координаты всех зон, если провести прямые между соот. координатами первой и второй точек , то вы как бы получите условное изображение зоны. Первая точка показывает начало зоны, а вторая конец, думаю,что поняли,чтобы определить зону, закачайте какую-нибудь прогу для определения координат, без запущеной игры, главное, чтобы там была карта Сан Андреаса. Ладно, перейдём к таблице:

ТАБЛИЦА ЗОН
 | Первая точка |  |  | Вторая точка
ЗОНА | X | Y | Z | X | Y | Z
SUNMA | -2353.17 | 2275.79 | 0.0 | -2153.17 | 2475.79 | 200.0
SUNNN | -2741.07 | 2175.15 | 0.0 | -2353.17 | 2722.79 | 200.0
BATTP | -2741.07 | 1268.41 | -4.577640005 | -2533.04 | 1490.47 | 200.0
PARA | -2741.07 | 793.411 | -6.103520005 | -2533.04 | 1268.41 | 200.0
CIVI | -2741.07 | 458.411 | -7.629390005 | -2533.04 | 793.411 | 200.0
BAYV | -2994.49 | 458.411 | -6.103520005 | -2741.07 | 1339.61 | 200.0
CITYS | -2867.85 | 277.411 | -9.155270005 | -2593.44 | 458.411 | 200.0
OCEAF1 | -2994.49 | 277.411 | -9.155270005 | -2867.85 | 458.411 | 200.0
OCEAF2 | -2994.49 | -222.589 | -0.000106812 | -2593.44 | 277.411 | 200.0
OCEAF3 | -2994.49 | -430.276 | -0.00012207 | -2831.89 | -222.589 | 200.0
SILLY3 | -2270.04 | -430.276 | -0.00012207 | -2178.69 | -324.114 | 200.0
SILLY4 | -2178.69 | -599.884 | -0.00012207 | -1794.92 | -324.114 | 200.0
HASH | -2593.44 | -222.589 | -0.000106812 | -2411.22 | 54.722 | 200.0
JUNIHO | -2533.04 | 968.369 | -6.103520005 | -2274.17 | 1358.9 | 200.0
ESPN1 | -2533.04 | 1358.9 | -4.577640005 | -1996.66 | 1501.21 | 200.0
ESPN2 | -1996.66 | 1358.9 | -4.577640005 | -1524.24 | 1592.51 | 200.0
ESPN3 | -1982.32 | 1274.26 | -4.577640005 | -1524.24 | 1358.9 | 200.0
FINA | -1871.72 | 744.17 | -6.103520005 | -1701.3 | 1176.42 | 300.0
CALT | -2274.17 | 744.17 | -6.103520005 | -1982.32 | 1358.9 | 200.0
SFDWT1 | -1982.32 | 744.17 | -6.103520005 | -1871.72 | 1274.26 | 200.0
SFDWT2 | -1871.72 | 1176.42 | -4.577640005 | -1620.3 | 1274.26 | 200.0
SFDWT3 | -1700.01 | 744.267 | -6.103520005 | -1580.01 | 1176.52 | 200.0
SFDWT4 | -1580.01 | 744.267 | -6.103520005 | -1499.89 | 1025.98 | 200.0
JUNIHI | -2533.04 | 578.396 | -7.629390005 | -2274.17 | 968.369 | 200.0
CHINA | -2274.17 | 578.396 | -7.629390005 | -2078.67 | 744.17 | 200.0
SFDWT5 | -2078.67 | 578.396 | -7.629390005 | -1499.89 | 744.267 | 200.0
THEA1 | -2329.31 | 458.411 | -7.629390005 | -1993.28 | 578.396 | 200.0
THEA2 | -2411.22 | 265.243 | -9.155270005 | -1993.28 | 373.539 | 200.0
THEA3 | -2253.54 | 373.539 | -9.155270005 | -1993.28 | 458.411 | 200.0
GARC | -2411.22 | -222.589 | -0.000114441 | -2173.04 | 265.243 | 200.0
DOH1 | -2270.04 | -324.114 | -0.00012207 | -1794.92 | -222.589 | 200.0
DOH2 | -2173.04 | -222.589 | -0.000106812 | -1794.92 | 265.243 | 200.0
SFDWT6 | -1993.28 | 265.243 | -9.155270005 | -1794.92 | 578.396 | 200.0
SFAIR3 | -1499.89 | -50.0963 | -0.000106812 | -1242.98 | 249.904 | 200.0
EASB1 | -1794.92 | 249.904 | -9.155270005 | -1242.98 | 578.396 | 200.0
EASB2 | -1794.92 | -50.0963 | -0.000106812 | -1499.89 | 249.904 | 200.0
ESPE1 | -1620.3 | 1176.52 | -4.577640005 | -1580.01 | 1274.26 | 200.0
ESPE2 | -1580.01 | 1025.98 | -6.103520005 | -1499.89 | 1274.26 | 200.0
ESPE3 | -1499.89 | 578.396 | -79.6152 | -1339.89 | 1274.26 | 20.3848
ANGPI | -2324.94 | -2584.29 | -6.103520005 | -1964.22 | -2212.11 | 200.0
SHACA | -1632.83 | -2263.44 | -3.051760005 | -1601.33 | -2231.79 | 200.0
BACKO | -1166.97 | -2641.19 | 0.0 | -321.744 | -1856.03 | 200.0
LEAFY | -1166.97 | -1856.03 | 0.0 | -815.624 | -1602.07 | 200.0
FLINTR | -594.191 | -1648.55 | 0.0 | -187.7 | -1276.6 | 200.0
HAUL | -792.254 | -698.555 | -5.340580005 | -452.404 | -380.043 | 200.0
FARM | -1209.67 | -1317.1 | 114.981 | -908.161 | -787.391 | 251.981
ELQUE | -1645.23 | 2498.52 | 0.0 | -1372.14 | 2777.85 | 200.0
ALDEA | -1372.14 | 2498.52 | 0.0 | -1277.59 | 2615.35 | 200.0
DAM | -968.772 | 1929.41 | -3.051760005 | -481.126 | 2155.26 | 200.0
BARRA | -926.13 | 1398.73 | -3.051760005 | -719.234 | 1634.69 | 200.0
CARSO | -376.233 | 826.326 | -3.051760005 | 123.717 | 1220.44 | 200.0
QUARY | 337.244 | 710.84 | -115.239 | 860.554 | 1031.71 | 203.761
OCTAN | 338.658 | 1228.51 | 0.0 | 664.308 | 1655.05 | 200.0
PALMS | 176.581 | 1305.45 | -3.051760005 | 338.658 | 1520.72 | 200.0
TOM | -405.77 | 1712.86 | -3.051760005 | -276.719 | 1892.75 | 200.0
BRUJA | -365.167 | 2123.01 | -3.051760005 | -208.57 | 2217.68 | 200.0
MEAD | 37.0325 | 2337.18 | -3.051760005 | 435.988 | 2677.9 | 200.0
PAYAS | -354.332 | 2580.36 | 2.098080005 | -133.625 | 2816.82 | 200.0
ARCO | -901.129 | 2221.86 | 0.0 | -592.09 | 2571.97 | 200.0
SFAIR1 | -1794.92 | -730.118 | -3.051760005 | -1213.91 | -50.0963 | 200.0
HANKY | 2576.92 | 62.1579 | 0.0 | 2759.25 | 385.503 | 200.0
PALO | 2160.22 | -149.004 | 0.0 | 2576.92 | 228.322 | 200.0
NROCK | 2285.37 | -768.027 | 0.0 | 2770.59 | -269.74 | 200.0
MONT | 1119.51 | 119.526 | -3.051760005 | 1451.4 | 493.323 | 200.0
MONT1 | 1451.4 | 347.457 | -6.103520005 | 1582.44 | 420.802 | 200.0
HBARN | 603.035 | 264.312 | 0.0 | 761.994 | 366.572 | 200.0
FERN | 508.189 | -139.259 | 0.0 | 1306.66 | 119.526 | 200.0
DILLI | 580.794 | -674.885 | -9.536740006 | 861.085 | -404.79 | 200.0
TOPFA | 967.383 | -450.39 | -3.051760005 | 1176.78 | -217.9 | 200.0
BLUEB1 | 104.534 | -220.137 | 2.384190007 | 349.607 | 152.236 | 200.0
BLUEB | 19.6074 | -404.136 | 3.81470006 | 349.607 | -220.137 | 200.0
PANOP | -947.98 | -304.32 | -1.144410005 | 319.676 | 327.071 | 200.0
FRED | 2759.25 | 296.501 | 0.0 | 2774.25 | 594.757 | 200.0
MAKO | 1664.62 | 401.75 | 0.0 | 1785.14 | 567.203 | 200.0
BLUAC | -319.676 | -220.137 | 0.0 | 104.534 | 293.324 | 200.0
MART | -222.179 | 293.324 | 0.0 | -122.126 | 476.465 | 200.0
FALLO | 434.341 | 366.572 | 0.0 | 603.035 | 555.68 | 200.0
CREEK | -1820.64 | -2643.68 | -8.010860005 | -1226.78 | -1771.66 | 200.0
CREEK1 | -2030.12 | -2174.89 | -6.103520005 | -1820.64 | -1771.66 | 200.0
WESTP1 | -2533.04 | 458.411 | 0.0 | -2329.31 | 578.396 | 200.0
WESTP2 | -2593.44 | 54.722 | 0.0 | -2411.22 | 458.411 | 200.0
WESTP3 | -2411.22 | 373.539 | 0.0 | -2253.54 | 458.411 | 200.0
LA | 44.6147 | -2892.97 | -242.99 | 2997.06 | -768.027 | 900.0
VE | 869.461 | 596.349 | -242.99 | 2997.06 | 2993.87 | 900.0
BONE | -480.539 | 596.349 | -242.99 | 869.461 | 2993.87 | 900.0
ROBAD | -2997.47 | 1659.68 | -242.99 | -480.539 | 2993.87 | 900.0
GANTB | -2741.45 | 1659.68 | -6.103520005 | -2616.4 | 2175.15 | 200.0
GANTB1 | -2741.07 | 1490.47 | -6.103520005 | -2616.4 | 1659.68 | 200.0
SF | -2997.47 | -1115.58 | -242.99 | -1213.91 | 1659.68 | 900.0
ROBAD1 | -1213.91 | 596.349 | -242.99 | -480.539 | 1659.68 | 900.0
RED | -1213.91 | -768.027 | -242.99 | 2997.06 | 596.349 | 900.0
FLINTC | -1213.91 | -2892.97 | -242.99 | 44.6147 | -768.027 | 900.0
EBAY | -1132.82 | -768.027 | 0.0 | -956.476 | -578.118 | 200.0
EBAY2 | -1132.82 | -787.391 | 0.0 | -956.476 | -768.027 | 200.0
SFAIR4 | -1213.91 | -730.118 | 0.0 | -1132.82 | -50.0963 | 200.0
SILLY1 | -2178.69 | -1115.58 | 0.0 | -1794.92 | -599.884 | 200.0
SILLY2 | -2178.69 | -1250.97 | 0.0 | -1794.92 | -1115.58 | 200.0
SFAIR2 | -1242.98 | -50.0963 | 0.0 | -1213.91 | 578.396 | 200.0
SFAIR5 | -1213.91 | -50.096 | -4.577640005 | -947.98 | 578.396 | 200.0
WHET | -2997.47 | -2892.97 | -242.99 | -1213.91 | -1115.58 | 900.0
LAIR1 | 1249.62 | -2394.33 | -89.0839 | 1852.0 | -2179.25 | 110.916
LAIR2a | 1852.0 | -2394.33 | -89.0839 | 2089.0 | -2179.25 | 110.916
BLUF1a | 930.221 | -2488.42 | -89.0839 | 1249.62 | -2006.78 | 110.916
ELCO2 | 1812.62 | -2179.25 | -89.0839 | 1970.62 | -1852.87 | 110.916
LIND1a | 1970.62 | -2179.25 | -89.0839 | 2089.0 | -1852.87 | 110.916
LIND1b | 2089.0 | -2235.84 | -89.0839 | 2201.82 | -1989.9 | 110.916
LIND2a | 2089.0 | -1989.9 | -89.0839 | 2324.0 | -1852.87 | 110.916
LIND2b | 2201.82 | -2095.0 | -89.0839 | 2324.0 | -1989.9 | 110.916
LDOC4 | 2373.77 | -2697.09 | -89.0837 | 2809.22 | -2330.46 | 110.916
LDOC1b | 2201.82 | -2418.33 | -89.0837 | 2324.0 | -2095.0 | 110.916
MAR3 | 647.712 | -1804.21 | -89.0839 | 851.449 | -1577.59 | 110.916
VERO4a | 647.712 | -2173.29 | -89.0839 | 930.221 | -1804.21 | 110.916
VERO4b | 930.221 | -2006.78 | -89.0839 | 1073.22 | -1804.21 | 110.916
BLUF1b | 1073.22 | -2006.78 | -89.0839 | 1249.62 | -1842.27 | 110.916
BLUF2 | 1249.62 | -2179.25 | -89.0839 | 1692.62 | -1842.27 | 110.916
ELCO1 | 1692.62 | -2179.25 | -89.0839 | 1812.62 | -1842.27 | 110.916
VERO1 | 851.449 | -1804.21 | -89.0839 | 1046.15 | -1577.59 | 110.916
MAR1 | 647.712 | -1577.59 | -89.0838 | 807.922 | -1416.25 | 110.916
MAR2 | 807.922 | -1577.59 | -89.0839 | 926.922 | -1416.25 | 110.916
VERO3 | 1161.52 | -1722.26 | -89.0839 | 1323.9 | -1577.59 | 110.916
VERO2 | 1046.15 | -1722.26 | -89.0839 | 1161.52 | -1577.59 | 110.916
CONF1b | 1046.15 | -1804.21 | -89.0839 | 1323.9 | -1722.26 | 110.916
CONF1a | 1073.22 | -1842.27 | -89.0839 | 1323.9 | -1804.21 | 110.916
THALL1 | 1323.9 | -1842.27 | -89.0839 | 1701.9 | -1722.26 | 110.916
COM1a | 1323.9 | -1722.26 | -89.0839 | 1440.9 | -1577.59 | 110.916
COM1b | 1370.85 | -1577.59 | -89.084 | 1463.9 | -1384.95 | 110.916
COM2 | 1463.9 | -1577.59 | -89.0839 | 1667.96 | -1430.87 | 110.916
PER1 | 1440.9 | -1722.26 | -89.0839 | 1583.5 | -1577.59 | 110.916
COM4 | 1583.5 | -1722.26 | -89.0839 | 1758.9 | -1577.59 | 110.916
LMEX1a | 1701.9 | -1842.27 | -89.0839 | 1812.62 | -1722.26 | 110.916
LMEX1b | 1758.9 | -1722.26 | -89.0839 | 1812.62 | -1577.59 | 110.916
COM3 | 1667.96 | -1577.59 | -89.0839 | 1812.62 | -1430.87 | 110.916
IWD3a | 1812.62 | -1852.87 | -89.0839 | 1971.66 | -1742.31 | 110.916
IWD3b | 1812.62 | -1742.31 | -89.0839 | 1951.66 | -1602.31 | 110.916
IWD4 | 1951.66 | -1742.31 | -89.0839 | 2124.66 | -1602.31 | 110.916
IWD1 | 1812.62 | -1602.31 | -89.0839 | 2124.66 | -1449.67 | 110.916
IWD2 | 2124.66 | -1742.31 | -89.0839 | 2222.56 | -1494.03 | 110.916
GLN2a | 1812.62 | -1449.67 | -89.0839 | 1996.91 | -1350.72 | 110.916
GLN1b | 1812.62 | -1100.82 | -89.0839 | 1994.33 | -973.38 | 110.916
JEF3a | 1996.91 | -1449.67 | -89.0839 | 2056.86 | -1350.72 | 110.916
JEF3c | 2124.66 | -1494.03 | -89.0839 | 2266.21 | -1449.67 | 110.916
JEF2 | 2056.86 | -1372.04 | -89.0839 | 2281.45 | -1210.74 | 110.916
JEF1b | 2056.86 | -1210.74 | -89.0839 | 2185.33 | -1126.32 | 110.916
JEF1a | 2185.33 | -1210.74 | -89.0839 | 2281.45 | -1154.59 | 110.916
CHC1a | 1994.33 | -1100.82 | -89.0839 | 2056.86 | -920.815 | 110.916
CHC1b | 2056.86 | -1126.32 | -89.0839 | 2126.86 | -920.815 | 110.916
CHC2b | 2185.33 | -1154.59 | -89.0839 | 2281.45 | -934.489 | 110.916
CHC2a | 2126.86 | -1126.32 | -89.0839 | 2185.33 | -934.489 | 110.916
IWD5 | 1971.66 | -1852.87 | -89.0839 | 2222.56 | -1742.31 | 110.916
GAN2 | 2222.56 | -1852.87 | -89.0839 | 2632.83 | -1722.33 | 110.916
GAN1 | 2222.56 | -1722.33 | -89.0839 | 2632.83 | -1628.53 | 110.916
LIND4c | 2541.7 | -1941.4 | -89.0839 | 2703.58 | -1852.87 | 110.916
EBE3c | 2632.83 | -1852.87 | -89.0839 | 2959.35 | -1668.13 | 110.916
EBE2a | 2632.83 | -1668.13 | -89.0839 | 2747.74 | -1393.42 | 110.916
EBE2b | 2747.74 | -1668.13 | -89.0839 | 2959.35 | -1498.62 | 110.916
ELS4 | 2421.03 | -1628.53 | -89.0839 | 2632.83 | -1454.35 | 110.916
ELS3a | 2222.56 | -1628.53 | -89.0839 | 2421.03 | -1494.03 | 110.916
JEF3b | 2056.86 | -1449.67 | -89.0839 | 2266.21 | -1372.04 | 110.916
ELS3b | 2266.26 | -1494.03 | -89.0839 | 2381.68 | -1372.04 | 110.916
ELS3c | 2381.68 | -1494.03 | -89.0839 | 2421.03 | -1454.35 | 110.916
ELS1a | 2281.45 | -1372.04 | -89.084 | 2381.68 | -1135.04 | 110.916
ELS1b | 2381.68 | -1454.35 | -89.0839 | 2462.13 | -1135.04 | 110.916
ELS2 | 2462.13 | -1454.35 | -89.0839 | 2581.73 | -1135.04 | 110.916
LFL1a | 2581.73 | -1454.35 | -89.0839 | 2632.83 | -1393.42 | 110.916
LFL1b | 2581.73 | -1393.42 | -89.0839 | 2747.74 | -1135.04 | 110.916
EBE1 | 2747.74 | -1498.62 | -89.0839 | 2959.35 | -1120.04 | 110.916
CHC4a | 2747.74 | -1120.04 | -89.0839 | 2959.35 | -945.035 | 110.916
CHC4b | 2632.74 | -1135.04 | -89.0839 | 2747.74 | -945.035 | 110.916
CHC3 | 2281.45 | -1135.04 | -89.0839 | 2632.74 | -945.035 | 110.916
LDT5 | 1463.9 | -1430.87 | -89.084 | 1724.76 | -1290.87 | 110.916
LDT7 | 1724.76 | -1430.87 | -89.0839 | 1812.62 | -1250.9 | 110.916
LDT4 | 1463.9 | -1290.87 | -89.084 | 1724.76 | -1150.87 | 110.916
LDT3 | 1370.85 | -1384.95 | -89.0839 | 1463.9 | -1170.87 | 110.916
LDT6 | 1724.76 | -1250.9 | -89.0839 | 1812.62 | -1150.87 | 110.916
MULINT | 1463.9 | -1150.87 | -89.0839 | 1812.62 | -768.027 | 110.916
MUL3 | 1414.07 | -768.027 | -89.0839 | 1667.61 | -452.425 | 110.916
MUL2a | 1281.13 | -452.425 | -89.0839 | 1641.13 | -290.913 | 110.916
MUL2b | 1269.13 | -768.027 | -89.0839 | 1414.07 | -452.425 | 110.916
MKT3 | 787.461 | -1416.25 | -89.0838 | 1072.66 | -1310.21 | 110.916
VIN3 | 787.461 | -1310.21 | -89.0838 | 952.663 | -1130.84 | 110.916
MKT4 | 952.663 | -1310.21 | -89.0839 | 1072.66 | -1130.85 | 110.916
LDT1a | 1370.85 | -1170.87 | -89.0839 | 1463.9 | -1130.85 | 110.916
LDT1b | 1378.33 | -1130.85 | -89.0838 | 1463.9 | -1026.33 | 110.916
LDT1c | 1391.05 | -1026.33 | -89.0839 | 1463.9 | -926.999 | 110.916
SUN3a | 1252.33 | -1130.85 | -89.0839 | 1378.33 | -1026.33 | 110.916
SUN3b | 1252.33 | -1026.33 | -89.0839 | 1391.05 | -926.999 | 110.916
SUN3c | 1252.33 | -926.999 | -89.0839 | 1357.0 | -910.17 | 110.916
MUL7a | 1357.0 | -926.999 | -89.0838 | 1463.9 | -768.027 | 110.916
MUL7b | 1318.13 | -910.17 | -89.0839 | 1357.0 | -768.027 | 110.916
MUL6 | 1169.13 | -910.17 | -89.0838 | 1318.13 | -768.027 | 110.916
VIN2 | 787.461 | -1130.84 | -89.0839 | 952.604 | -954.662 | 110.916
SUN1 | 952.663 | -1130.84 | -89.084 | 1096.47 | -937.184 | 110.916
SUN4 | 1096.47 | -1130.84 | -89.0838 | 1252.33 | -1026.33 | 110.916
SUN2 | 1096.47 | -1026.33 | -89.0839 | 1252.33 | -910.17 | 110.916
MUL4 | 768.694 | -954.662 | -89.0838 | 952.604 | -860.619 | 110.916
MUL1a | 687.802 | -860.619 | -89.0839 | 911.802 | -768.027 | 110.916
MUL1b | 737.573 | -768.027 | -89.0838 | 1142.29 | -674.885 | 110.916
MUL5a | 1096.47 | -910.17 | -89.0838 | 1169.13 | -768.027 | 110.916
MUL5b | 952.604 | -937.184 | -89.0839 | 1096.47 | -860.619 | 110.916
MUL5c | 911.802 | -860.619 | -89.0838 | 1096.47 | -768.027 | 110.916
MUL1c | 861.085 | -674.885 | -89.0839 | 1156.55 | -600.896 | 110.916
SMB1 | 342.648 | -2173.29 | -89.0838 | 647.712 | -1684.65 | 110.916
SMB2 | 72.6481 | -2173.29 | -89.0839 | 342.648 | -1684.65 | 110.916
ROD5b | 72.6481 | -1684.65 | -89.084 | 225.165 | -1544.17 | 110.916
ROD5a | 72.6481 | -1544.17 | -89.0839 | 225.165 | -1404.97 | 110.916
ROD1a | 225.165 | -1684.65 | -89.0839 | 312.803 | -1501.95 | 110.916
ROD1b | 225.165 | -1501.95 | -89.0839 | 334.503 | -1369.62 | 110.916
ROD1c | 334.503 | -1501.95 | -89.0839 | 422.68 | -1406.05 | 110.916
ROD3a | 312.803 | -1684.65 | -89.0839 | 422.68 | -1501.95 | 110.916
ROD3b | 422.68 | -1684.65 | -89.0839 | 558.099 | -1570.2 | 110.916
ROD4a | 558.099 | -1684.65 | -89.0839 | 647.522 | -1384.93 | 110.916
ROD4b | 466.223 | -1570.2 | -89.0839 | 558.099 | -1385.07 | 110.916
ROD4c | 422.68 | -1570.2 | -89.0839 | 466.223 | -1406.05 | 110.916
VIN1b | 647.557 | -1227.28 | -89.0839 | 787.461 | -1118.28 | 110.916
RIH5a | 647.557 | -1118.28 | -89.0839 | 787.461 | -954.662 | 110.916
RIH5b | 647.557 | -954.662 | -89.0839 | 768.694 | -860.619 | 110.916
ROD2b | 466.223 | -1385.07 | -89.0839 | 647.522 | -1235.07 | 110.916
ROD2a | 334.503 | -1406.05 | -89.0839 | 466.223 | -1292.07 | 110.916
RIH6a | 225.165 | -1369.62 | -89.0839 | 334.503 | -1292.07 | 110.916
RIH6b | 225.165 | -1292.07 | -89.084 | 466.223 | -1235.07 | 110.916
RIH3a | 72.6481 | -1404.97 | -89.0839 | 225.165 | -1235.07 | 110.916
RIH3b | 72.6481 | -1235.07 | -89.0839 | 321.356 | -1008.15 | 110.916
RIH4 | 321.356 | -1235.07 | -89.0839 | 647.522 | -1044.07 | 110.916
RIH2 | 321.356 | -1044.07 | -89.0839 | 647.557 | -860.619 | 110.916
RIH1a | 321.356 | -860.619 | -89.0839 | 687.802 | -768.027 | 110.916
RIH1b | 321.356 | -768.027 | -89.0839 | 700.794 | -674.885 | 110.916
STRIP1 | 2027.4 | 863.229 | -89.0839 | 2087.39 | 1703.23 | 110.916
STRIP2 | 2106.7 | 1863.23 | -89.0839 | 2162.39 | 2202.76 | 110.916
DRAG | 1817.39 | 863.232 | -89.084 | 2027.39 | 1083.23 | 110.916
PINK | 1817.39 | 1083.23 | -89.0839 | 2027.39 | 1283.23 | 110.916
HIGH | 1817.39 | 1283.23 | -89.0839 | 2027.39 | 1469.23 | 110.916
PIRA | 1817.39 | 1469.23 | -89.084 | 2027.4 | 1703.23 | 110.916
VISA1 | 1817.39 | 1863.23 | -89.0839 | 2106.7 | 2011.83 | 110.916
VISA2 | 1817.39 | 1703.23 | -89.0839 | 2027.4 | 1863.23 | 110.916
JTS1 | 1457.39 | 823.228 | -89.0839 | 2377.39 | 863.229 | 110.916
JTW1 | 1197.39 | 1163.39 | -89.0839 | 1236.63 | 2243.23 | 110.916
JTS2 | 2377.39 | 788.894 | -89.0839 | 2537.39 | 897.901 | 110.916
RSE | 2537.39 | 676.549 | -89.0839 | 2902.35 | 943.235 | 110.916
LOT | 2087.39 | 943.235 | -89.0839 | 2623.18 | 1203.23 | 110.916
CAM | 2087.39 | 1203.23 | -89.0839 | 2640.4 | 1383.23 | 110.916
ROY | 2087.39 | 1383.23 | -89.0839 | 2437.39 | 1543.23 | 110.916
CALI1 | 2087.39 | 1543.23 | -89.0839 | 2437.39 | 1703.23 | 110.916
CALI2 | 2137.4 | 1703.23 | -89.0839 | 2437.39 | 1783.23 | 110.916
PILL1 | 2437.39 | 1383.23 | -89.0839 | 2624.4 | 1783.23 | 110.916
STAR2 | 2437.39 | 1783.23 | -89.0839 | 2685.16 | 2012.18 | 110.916
STRIP3 | 2027.4 | 1783.23 | -89.084 | 2162.39 | 1863.23 | 110.916
STRIP4 | 2027.4 | 1703.23 | -89.0839 | 2137.4 | 1783.23 | 110.916
ISLE | 2011.94 | 2202.76 | -89.0839 | 2237.4 | 2508.23 | 110.916
OVS | 2162.39 | 2012.18 | -89.0839 | 2685.16 | 2202.76 | 110.916
KACC | 2498.21 | 2626.55 | -89.0839 | 2749.9 | 2861.55 | 110.916
CREE | 2749.9 | 1937.25 | -89.0839 | 2921.62 | 2669.79 | 110.916
SRY | 2749.9 | 1548.99 | -89.0839 | 2923.39 | 1937.25 | 110.916
LST | 2749.9 | 1198.99 | -89.0839 | 2923.39 | 1548.99 | 110.916
JTE2 | 2623.18 | 943.235 | -89.0839 | 2749.9 | 1055.96 | 110.916
LDS | 2749.9 | 943.235 | -89.0839 | 2923.39 | 1198.99 | 110.916
JTE1 | 2685.16 | 1055.96 | -89.0839 | 2749.9 | 2626.55 | 110.916
JTN1 | 2498.21 | 2542.55 | -89.0839 | 2685.16 | 2626.55 | 110.916
JTE4 | 2536.43 | 2442.55 | -89.0839 | 2685.16 | 2542.55 | 110.916
JTE3 | 2625.16 | 2202.76 | -89.0839 | 2685.16 | 2442.55 | 110.916
JTN2 | 2237.4 | 2542.55 | -89.0839 | 2498.21 | 2663.17 | 110.916
JTN3 | 2121.4 | 2508.23 | -89.0839 | 2237.4 | 2663.17 | 110.916
JTN4 | 1938.8 | 2508.23 | -89.0839 | 2121.4 | 2624.23 | 110.916
JTN5 | 1534.56 | 2433.23 | -89.0839 | 1848.4 | 2583.23 | 110.916
JTW2 | 1236.63 | 2142.86 | -89.084 | 1297.47 | 2243.23 | 110.916
JTN6 | 1848.4 | 2478.49 | -89.0839 | 1938.8 | 2553.49 | 110.916
HGP | 1777.39 | 863.232 | -89.0839 | 1817.39 | 2342.83 | 110.916
REDE1 | 1817.39 | 2011.83 | -89.0839 | 2106.7 | 2202.76 | 110.916
REDE2 | 1817.39 | 2202.76 | -89.0839 | 2011.94 | 2342.83 | 110.916
REDE3 | 1848.4 | 2342.83 | -89.084 | 2011.94 | 2478.49 | 110.916
JTN8 | 1704.59 | 2342.83 | -89.0839 | 1848.4 | 2433.23 | 110.916
REDW2 | 1236.63 | 1883.11 | -89.0839 | 1777.39 | 2142.86 | 110.916
REDW1 | 1297.47 | 2142.86 | -89.084 | 1777.39 | 2243.23 | 110.916
REDW3 | 1377.39 | 2243.23 | -89.0839 | 1704.59 | 2433.23 | 110.916
REDW4 | 1704.59 | 2243.23 | -89.0839 | 1777.39 | 2342.83 | 110.916
VAIR1 | 1236.63 | 1203.28 | -89.0839 | 1457.37 | 1883.11 | 110.916
VAIR2 | 1457.37 | 1203.28 | -89.0839 | 1777.39 | 1883.11 | 110.916
VAIR3 | 1457.37 | 1143.21 | -89.0839 | 1777.4 | 1203.28 | 110.916
LVA1 | 1457.39 | 863.229 | -89.0839 | 1777.4 | 1143.21 | 110.916
BINT2 | 1197.39 | 1044.69 | -89.0839 | 1277.05 | 1163.39 | 110.916
BINT1 | 1166.53 | 795.01 | -89.0839 | 1375.6 | 1044.69 | 110.916
BINT3 | 1277.05 | 1044.69 | -89.0839 | 1315.35 | 1087.63 | 110.916
BINT4 | 1375.6 | 823.228 | -89.084 | 1457.39 | 919.447 | 110.916
LVA2 | 1375.6 | 919.447 | -89.0839 | 1457.37 | 1203.28 | 110.916
LVA3 | 1277.05 | 1087.63 | -89.0839 | 1375.6 | 1203.28 | 110.916
LVA4 | 1315.35 | 1044.69 | -89.0839 | 1375.6 | 1087.63 | 110.916
LVA5 | 1236.63 | 1163.41 | -89.0839 | 1277.05 | 1203.28 | 110.916
GGC1 | 964.391 | 1044.69 | -89.0839 | 1197.39 | 1203.22 | 110.916
GGC2 | 964.391 | 930.89 | -89.0839 | 1166.53 | 1044.69 | 110.916
BFLD1 | 964.391 | 1203.22 | -89.084 | 1197.39 | 1403.22 | 110.916
BFLD2 | 964.391 | 1403.22 | -89.084 | 1197.39 | 1726.22 | 110.916
ROCE1 | 2237.4 | 2202.76 | -89.0839 | 2536.43 | 2542.55 | 110.916
ROCE2 | 2536.43 | 2202.76 | -89.0839 | 2625.16 | 2442.55 | 110.916
LDM | 1823.08 | 596.349 | -89.0839 | 1997.22 | 823.228 | 110.916
RSW1 | 1997.22 | 596.349 | -89.0839 | 2377.39 | 823.228 | 110.916
RSW2 | 2377.39 | 596.349 | -89.084 | 2537.39 | 788.894 | 110.916
RIE | 1558.09 | 596.349 | -89.084 | 1823.08 | 823.235 | 110.916
BFC1 | 1375.6 | 596.349 | -89.084 | 1558.09 | 823.228 | 110.916
BFC2 | 1325.6 | 596.349 | -89.084 | 1375.6 | 795.01 | 110.916
JTN7 | 1377.39 | 2433.23 | -89.0839 | 1534.56 | 2507.23 | 110.916
PINT | 1098.39 | 2243.23 | -89.0839 | 1377.39 | 2507.23 | 110.916
WWE | 883.308 | 1726.22 | -89.0839 | 1098.31 | 2507.23 | 110.916
PRP1 | 1534.56 | 2583.23 | -89.0839 | 1848.4 | 2863.23 | 110.916
PRP2 | 1117.4 | 2507.23 | -89.0839 | 1534.56 | 2723.23 | 110.916
PRP3 | 1848.4 | 2553.49 | -89.0839 | 1938.8 | 2863.23 | 110.916
SPIN | 2121.4 | 2663.17 | -89.0839 | 2498.21 | 2861.55 | 110.916
PRP4 | 1938.8 | 2624.23 | -89.0839 | 2121.4 | 2861.55 | 110.916
PILL2 | 2624.4 | 1383.23 | -89.084 | 2685.16 | 1783.23 | 110.916
SASO | 2450.39 | 385.503 | -100.0 | 2759.25 | 562.349 | 200.0
FISH | 1916.99 | -233.323 | -100.0 | 2131.72 | 13.8002 | 200.0
GARV | -1339.89 | 828.129 | -89.0839 | -1213.91 | 1057.04 | 110.916
GARV1 | -1213.91 | 950.022 | -89.0839 | -1087.93 | 1178.93 | 110.916
GARV2 | -1499.89 | 696.442 | -179.615 | -1339.89 | 925.353 | 20.3848
KINC | -1339.89 | 599.218 | -89.0839 | -1213.91 | 828.129 | 110.916
KINC1 | -1213.91 | 721.111 | -89.0839 | -1087.93 | 950.022 | 110.916
KINC2 | -1087.93 | 855.37 | -89.0839 | -961.95 | 986.281 | 110.916
LSINL | -321.744 | -2224.43 | -89.0839 | 44.6147 | -1724.43 | 110.916
SHERR | -789.737 | 1659.68 | -89.084 | -599.505 | 1929.41 | 110.916
FLINW | -314.426 | -753.874 | -89.0839 | -106.339 | -463.073 | 110.916
ETUNN | -1709.71 | -833.034 | -1.525880005 | -1446.01 | -730.118 | 200.0
BYTUN | -2290.19 | 2548.29 | -89.084 | -1950.19 | 2723.29 | 110.916
BIGE | -410.02 | 1403.34 | -3.051760005 | -137.969 | 1681.23 | 200.0
PROBE | -90.2183 | 1286.85 | -3.051760005 | 153.859 | 1554.12 | 200.0
VALLE | -936.668 | 2611.44 | 2.098080005 | -715.961 | 2847.9 | 200.0
GLN1 | 1812.62 | -1350.72 | -89.0839 | 2056.86 | -1100.82 | 110.916
LDOC3a | 2324.0 | -2302.33 | -89.0839 | 2703.58 | -2145.1 | 110.916
LINDEN | 2811.25 | 1229.59 | -39.594 | 2861.25 | 1407.59 | 60.406
UNITY | 1692.62 | -1971.8 | -20.4921 | 1812.62 | -1932.8 | 79.5079
VIN1a | 647.712 | -1416.25 | -89.0839 | 787.461 | -1227.28 | 110.916
MARKST | 787.461 | -1410.93 | -34.1263 | 866.009 | -1310.21 | 65.8737
CRANB | -2007.83 | 56.3063 | 0.0 | -1922.0 | 224.782 | 100.0
YELLOW | 1377.48 | 2600.43 | -21.9263 | 1492.45 | 2687.36 | 78.0737
SANB1 | -2616.4 | 1501.21 | -3.051760005 | -1996.66 | 1659.68 | 200.0
SANB2 | -2616.4 | 1659.68 | -3.051760005 | -1996.66 | 2175.15 | 200.0
ELCA | -464.515 | 2217.68 | 0.0 | -208.57 | 2580.36 | 200.0
ELCA1 | -208.57 | 2123.01 | -7.629390006 | 114.033 | 2337.18 | 200.0
ELCA2 | -208.57 | 2337.18 | 0.0 | 8.42999 | 2487.18 | 200.0
REST | -91.586 | 1655.05 | -50.0 | 421.234 | 2123.01 | 250.0
MONINT | 1546.65 | 208.164 | 0.0 | 1745.83 | 347.457 | 200.0
MONINT | 1582.44 | 347.457 | 0.0 | 1664.62 | 401.75 | 200.0
ROBINT | -1119.01 | 1178.93 | -89.084 | -862.025 | 1351.45 | 110.916
FLINTI | -187.7 | -1596.76 | -89.0839 | 17.0632 | -1276.6 | 110.916
SFBAG2 | -1315.42 | -405.388 | 15.4061 | -1264.4 | -209.543 | 25.4061
SFBAG3 | -1354.39 | -287.398 | 15.4061 | -1315.42 | -209.543 | 25.4061
SFBAG1 | -1490.33 | -209.543 | 15.4061 | -1264.4 | -148.388 | 25.4061
MKT1 | 1072.66 | -1416.25 | -89.084 | 1370.85 | -1130.85 | 110.916
MKT2 | 926.922 | -1577.59 | -89.0839 | 1370.85 | -1416.25 | 110.916
SFGLF4 | -2646.4 | -355.493 | 0.0 | -2270.04 | -222.589 | 200.0
CUNTC2 | -2831.89 | -430.276 | -6.103520005 | -2646.4 | -222.589 | 200.0
HILLP | -2994.49 | -811.276 | 0.0 | -2178.69 | -430.276 | 200.0
MTCHI2 | -2178.69 | -1771.66 | -47.9166 | -1936.12 | -1250.97 | 576.083
MTCHI3 | -2997.47 | -1115.58 | -47.9166 | -2178.69 | -971.913 | 576.083
MTCHI1 | -2994.49 | -2189.91 | -47.9166 | -2178.69 | -1115.58 | 576.083
MTCHI4 | -2178.69 | -2189.91 | -47.9166 | -2030.12 | -1771.66 | 576.083
YBELL1 | 1117.4 | 2723.23 | -89.0839 | 1457.46 | 2863.23 | 110.916
YBELL2 | 1457.46 | 2723.23 | -89.0839 | 1534.56 | 2863.23 | 110.916
LVBAG | 1515.81 | 1586.4 | -12.5 | 1729.95 | 1714.56 | 87.5
LDOC1a | 2089.0 | -2394.33 | -89.0839 | 2201.82 | -2235.84 | 110.916
LAIR2b | 1382.73 | -2730.88 | -89.0839 | 2201.82 | -2394.33 | 110.916
LDOC3b | 2201.82 | -2730.88 | -89.0839 | 2324.0 | -2418.33 | 110.916
LBAG1 | 1974.63 | -2394.33 | -39.0839 | 2089.0 | -2256.59 | 60.9161
LBAG2 | 1400.97 | -2669.26 | -39.0839 | 2189.82 | -2597.26 | 60.9161
LBAG3 | 2051.63 | -2597.26 | -39.0839 | 2152.45 | -2394.33 | 60.9161
CONST1 | 2437.39 | 1858.1 | -39.0839 | 2495.09 | 1970.85 | 60.9161
BEACO | -399.633 | -1075.52 | -1.48904 | -319.033 | -977.516 | 198.511
SFGLF1 | -2361.51 | -417.199 | 0.0 | -2270.04 | -355.493 | 200.0
SFGLF2 | -2667.81 | -302.135 | -28.8305 | -2646.4 | -262.32 | 71.1695
SFGLF3 | -2395.14 | -222.589 | -5.340580005 | -2354.09 | -204.792 | 200.0
CUNTC1 | -2470.04 | -355.493 | 0.0 | -2270.04 | -318.493 | 46.1
CUNTC3 | -2550.04 | -355.493 | 0.0 | -2470.04 | -318.493 | 39.7
PLS | 2703.58 | -2126.9 | -89.0839 | 2959.35 | -1852.87 | 110.916
LDOC3c | 2703.58 | -2302.33 | -89.0839 | 2959.35 | -2126.9 | 110.916
STAR1 | 2162.39 | 1883.23 | -89.0839 | 2437.39 | 2012.18 | 110.916
RING | 2162.39 | 1783.23 | -89.0839 | 2437.39 | 1883.23 | 110.916
LDOC2 | 2324.0 | -2145.1 | -89.084 | 2703.58 | -2059.23 | 110.916
LIND3 | 2324.0 | -2059.23 | -89.0839 | 2541.7 | -1852.87 | 110.916
LIND4a | 2541.7 | -2059.23 | -89.0839 | 2703.58 | -1941.4 | 110.916
WWE1 | 1098.31 | 1726.22 | -89.0839 | 1197.39 | 2243.23 | 110.916
LDT8 | 1507.51 | -1385.21 | 110.916 | 1582.55 | -1325.31 | 335.916

NAME | GXT VALUE | GXT ENTRY
Los Santos
LA | Los Santos | LA
RIH1a | Richman | RIH
RIH1b | Richman | RIH
RIH2 | Richman | RIH
RIH3a | Richman | RIH
RIH3b | Richman | RIH
RIH4 | Richman | RIH
RIH5a | Richman | RIH
RIH5b | Richman | RIH
RIH6a | Richman | RIH
RIH6b | Richman | RIH
MUL1a | Mulholland | MUL
MUL1b | Mulholland | MUL
MUL1c | Mulholland | MUL
MUL2a | Mulholland | MUL
MUL2b | Mulholland | MUL
MUL3 | Mulholland | MUL
MUL4 | Mulholland | MUL
MUL5a | Mulholland | MUL
MUL5b | Mulholland | MUL
MUL5c | Mulholland | MUL
MUL6 | Mulholland | MUL
MUL7a | Mulholland | MUL
MUL7b | Mulholland | MUL
MULINT | Mulholland Intersection | MULINT
SUN1 | Temple | SUN
SUN2 | Temple | SUN
SUN3a | Temple | SUN
SUN3b | Temple | SUN
SUN3c | Temple | SUN
SUN4 | Temple | SUN
CHC1a | Las Colinas | CHC
CHC1b | Las Colinas | CHC
CHC2a | Las Colinas | CHC
CHC2b | Las Colinas | CHC
CHC3 | Las Colinas | CHC
CHC4a | Las Colinas | CHC
CHC4b | Las Colinas | CHC
VIN1a | Vinewood | VIN
VIN1b | Vinewood | VIN
VIN2 | Vinewood | VIN
VIN3 | Vinewood | VIN
LDT1a | Downtown Los Santos | LDT
LDT1b | Downtown Los Santos | LDT
LDT1c | Downtown Los Santos | LDT
LDT3 | Downtown Los Santos | LDT
LDT4 | Downtown Los Santos | LDT
LDT5 | Downtown Los Santos | LDT
LDT6 | Downtown Los Santos | LDT
LDT7 | Downtown Los Santos | LDT
LDT8 | Downtown Los Santos | LDT
GLN1 | Glen Park | GLN
GLN1b | Glen Park | GLN
GLN2a | Glen Park | GLN
LFL1a | Los Flores | LFL
LFL1b | Los Flores | LFL
MKT1 | Market | MKT
MKT2 | Market | MKT
MKT3 | Market | MKT
MKT4 | Market | MKT
MARKST | Market Station | MARKST
JEF1a | Jefferson | JEF
JEF1b | Jefferson | JEF
JEF2 | Jefferson | JEF
JEF3a | Jefferson | JEF
JEF3b | Jefferson | JEF
JEF3c | Jefferson | JEF
ROD1a | Rodeo | ROD
ROD1b | Rodeo | ROD
ROD1c | Rodeo | ROD
ROD2a | Rodeo | ROD
ROD2b | Rodeo | ROD
ROD3a | Rodeo | ROD
ROD3b | Rodeo | ROD
ROD4a | Rodeo | ROD
ROD4b | Rodeo | ROD
ROD4c | Rodeo | ROD
ROD5a | Rodeo | ROD
ROD5b | Rodeo | ROD
MAR1 | Marina | MAR
MAR2 | Marina | MAR
MAR3 | Marina | MAR
THALL1 | Commerce | COM
COM1a | Commerce | COM
COM1b | Commerce | COM
COM2 | Commerce | COM
COM3 | Commerce | COM
COM4 | Commerce | COM
ELS1a | East Los Santos | ELS
ELS1b | East Los Santos | ELS
ELS2 | East Los Santos | ELS
ELS3a | East Los Santos | ELS
ELS3b | East Los Santos | ELS
ELS3c | East Los Santos | ELS
ELS4 | East Los Santos | ELS
EBE1 | East Beach | EBE
EBE2a | East Beach | EBE
EBE2b | East Beach | EBE
EBE3c | East Beach | EBE
PER1 | Pershing Square | PER1
IWD1 | Idlewood | IWD
IWD2 | Idlewood | IWD
IWD3a | Idlewood | IWD
IWD3b | Idlewood | IWD
IWD4 | Idlewood | IWD
IWD5 | Idlewood | IWD
GAN1 | Ganton | GAN
GAN2 | Ganton | GAN
CONF1a | Conference Center | CONF
CONF1b | Conference Center | CONF
CITYS | City Hall | CITYS
LMEX1a | Little Mexico | LMEX
LMEX1b | Little Mexico | LMEX
UNITY | Unity Station | UNITY
SMB1 | Santa Maria Beach | SMB
SMB2 | Santa Maria Beach | SMB
VERO1 | Verona Beach | VERO
VERO2 | Verona Beach | VERO
VERO3 | Verona Beach | VERO
VERO4a | Verona Beach | VERO
VERO4b | Verona Beach | VERO
LIND1a | Willowfield | LIND
LIND1b | Willowfield | LIND
LIND2a | Willowfield | LIND
LIND2b | Willowfield | LIND
LIND3 | Willowfield | LIND
LIND4a | Willowfield | LIND
LIND4c | Willowfield | LIND
ELCO1 | El Corona | ELCO
ELCO2 | El Corona | ELCO
PLS | Playa del Seville | PLS
BLUF1a | Verdant Bluffs | BLUF
BLUF1b | Verdant Bluffs | BLUF
BLUF2 | Verdant Bluffs | BLUF
LAIR1 | Los Santos International | LAIR
LAIR2a | Los Santos International | LAIR
LAIR2b | Los Santos International | LAIR
LBAG1 | Los Santos International | LAIR
LBAG2 | Los Santos International | LAIR
LBAG3 | Los Santos International | LAIR
LDOC1a | Ocean Docks | LDOC
LDOC1b | Ocean Docks | LDOC
LDOC2 | Ocean Docks | LDOC
LDOC3a | Ocean Docks | LDOC
LDOC3b | Ocean Docks | LDOC
LDOC3c | Ocean Docks | LDOC
LDOC4 | Ocean Docks | LDOC
Red County
RED | Red County | RED
MONT | Montgomery | MONT
MONT1 | Montgomery | MONT
MONINT | Montgomery Intersection | MONINT
HBARNS | Hampton Barns | HBARNS
HANKY | Hankypanky Point | HANKY
BLUAC | Blueberry Acres | BLUAC
FERN | Fern Ridge | FERN
PANOP | The Panopticon | PANOP
PALO | Palomino Creek | PALO
BLUEB | Blueberry | BLUEB
BLUEB1 | Blueberry | BLUEB
TOPFA | Hilltop Farm | TOPFA
NROCK | North Rock | NROCK
DILLI | Dillimore | DILLI
San Fierro
SF | San Fierro | SF
BATTP | Battery Point | BATTP
ESPN1 | Esplanade North | ESPN
ESPN2 | Esplanade North | ESPN
ESPN3 | Esplanade North | ESPN
ESPE1 | Esplanade East | ESPE
ESPE2 | Esplanade East | ESPE
ESPE3 | Esplanade East | ESPE
JUNIHO | Juniper Hollow | JUNIHO
SFDWT1 | Downtown | SFDWT
SFDWT2 | Downtown | SFDWT
SFDWT3 | Downtown | SFDWT
SFDWT4 | Downtown | SFDWT
SFDWT5 | Downtown | SFDWT
SFDWT6 | Downtown | SFDWT
PARA | Paradiso | PARA
CALT | Calton Heights | CALT
FINA | Financial | FINA
BAYV | Palisades | BAYV
JUNIHI | Juniper Hill | JUNIHI
CHINA | Chinatown | CHINA
CIVI | Santa Flora | CIVI
WESTP1 | Queens | WESTP
WESTP2 | Queens | WESTP
WESTP3 | Queens | WESTP
CITYS | City Hall | CITYS
THEA1 | King's | THEA
THEA2 | King's | THEA
THEA3 | King's | THEA
EASB1 | Easter Basin | EASB
EASB2 | Easter Basin | EASB
GARC | Garcia | GARC
SFGLF3 | Garcia | GARC
CRANB | Cranberry Station | CRANB
OCEAF1 | Ocean Flats | OCEAF
OCEAF2 | Ocean Flats | OCEAF
OCEAF3 | Ocean Flats | OCEAF
HASH | Hashbury | HASH
DOH1 | Doherty | DOH
DOH2 | Doherty | DOH
SFBAG2 | Easter Bay Airport (English) | SFAIR
SFBAG3 | Easter Bay Airport (English) | SFAIR
SFBAG1 | Easter Bay Airport (English) | SFAIR
SFAIR1 | Easter Bay Airport (English) | SFAIR
SFAIR2 | Easter Bay Airport (English) | SFAIR
SFAIR3 | Easter Bay Airport (English) | SFAIR
SFAIR4 | Easter Bay Airport (English) | SFAIR
SFAIR5 | Easter Bay Airport (English) | SFAIR
Flint County
FLINTC | Flint County | FLINTC
CUNTC1 | Avispa Country Club | CUNTC
CUNTC2 | Avispa Country Club | CUNTC
CUNTC3 | Avispa Country Club | CUNTC
SFGLF1 | Avispa Country Club | CUNTC
SFGLF2 | Avispa Country Club | CUNTC
SFGLF4 | Avispa Country Club | CUNTC
HAUL | Fallen Tree | HAUL
HILLP | Missionary Hill | HILLP
EBAY | Easter Bay Chemical | EBAY
EBAY2 | Easter Bay Chemical | EBAY
ETUNN | Easter Tunnel | ETUNN
SILLY1 | Foster Valley | SILLY
SILLY2 | Foster Valley | SILLY
SILLY3 | Foster Valley | SILLY
SILLY4 | Foster Valley | SILLY
FARM | The Farm | FARM
BEACO | Beacon Hill | BEACO
FLINTI | Flint Intersection | FLINTI
FLINTR | Flint Range | FLINTR
LEAFY | Leafy Hollow | LEAFY
BACKO | Back o Beyond | BACKO
Whetstone
WHET | Whetstone | WHET
MTCHI1 | Mount Chiliad | MTCHI
MTCHI2 | Mount Chiliad | MTCHI
MTCHI3 | Mount Chiliad | MTCHI
MTCHI4 | Mount Chiliad | MTCHI
CREEK | Shady Creeks | CREEK
CREEK1 | Shady Creeks | CREEK
SHACA | Shady Cabin | SHACA
ANGPI | Angel Pine | ANGPI
Las Venturas
VE | Las Venturas | VE
YBELL1 | Yellow Bell Golf Course | YBELL
YBELL2 | Yellow Bell Golf Course | YBELL
SPIN | Spinybed | SPIN
KACC | K.A.C.C. Military Fuels | KACC
PRP1 | Prickle Pine | PRP
PRP2 | Prickle Pine | PRP
PRP3 | Prickle Pine | PRP
PRP4 | Prickle Pine | PRP
YELLOW | Yellow Bell Station | YELLOW
JTN1 | Julius Thruway North | JTN
JTN2 | Julius Thruway North | JTN
JTN3 | Julius Thruway North | JTN
JTN4 | Julius Thruway North | JTN
JTN5 | Julius Thruway North | JTN
JTN6 | Julius Thruway North | JTN
JTN7 | Julius Thruway North | JTN
JTN8 | Julius Thruway North | JTN
PINT | Pilson Intersection | PINT
ISLE | The Emerald Isle | ISLE
ROCE1 | Roca Escalante | ROCE
ROCE2 | Roca Escalante | ROCE
WWE | Whitewood Estates | WWE
WWE1 | Whitewood Estates | WWE
OVS | Old Venturas Strip | OVS
CREE | Creek | CREE
REDE1 | Redsands East | REDE
REDE2 | Redsands East | REDE
REDE3 | Redsands East | REDE
REDW1 | Redsands West | REDW
REDW2 | Redsands West | REDW
REDW3 | Redsands West | REDW
REDW4 | Redsands West | REDW
HGP | Harry Gold Parkway | HGP
STRIP1 | The Strip | STRIP
STRIP2 | The Strip | STRIP
JTW1 | Julius Thruway West | JTW
JTW2 | Julius Thruway West | JTW
VISA1 | The Visage | VISA
VISA2 | The Visage | VISA
STAR1 | Starfish Casino | STAR
STAR2 | Starfish Casino | STAR
CONST1 | Starfish Casino | STAR
RING | The Clown's Pocket | RING
SRY | Sobell Rail Yards | SRY
JTE1 | Julius Thruway East | JTE
JTE2 | Julius Thruway East | JTE
JTE3 | Julius Thruway East | JTE
JTE4 | Julius Thruway East | JTE
BFLD1 | Blackfield | BFLD
BFLD2 | Blackfield | BFLD
CALI1 | Caligula's Palace | CALI
CALI2 | Caligula's Palace | CALI
VAIR1 | Las Venturas Airport (English) | VAIR
VAIR2 | Las Venturas Airport (English) | VAIR
VAIR3 | Las Venturas Airport (English) | VAIR
LVBAG | Las Venturas Airport (English) | VAIR
PIRA | Pirates in Men's Pants | PIRA
ROY | Royal Casino | ROY
PILL1 | Pilgrim | PILL
PILL2 | Pilgrim | PILL
LST | Linden Station | LST
LINDEN | Linden Station | LINDEN
HIGH | The High Roller | HIGH
STRIP3 | The Strip | STRIP
STRIP4 | The Strip | STRIP
PINK | The Pink Swan | PINK
CAM | The Camel's Toe | CAM
GGC1 | Greenglass College | GGC
GGC2 | Greenglass College | GGC
LDS | Linden Side | LDS
LVA1 | LVA Freight Depot | LVA
LVA2 | LVA Freight Depot | LVA
LVA3 | LVA Freight Depot | LVA
LVA4 | LVA Freight Depot | LVA
LVA5 | LVA Freight Depot | LVA
DRAG | The Four Dragons Casino | DRAG
LOT | Come-A-Lot | LOT
BINT1 | Blackfield Intersection | BINT
BINT2 | Blackfield Intersection | BINT
BINT3 | Blackfield Intersection | BINT
BINT4 | Blackfield Intersection | BINT
JTS1 | Julius Thruway South | JTS
JTS2 | Julius Thruway South | JTS
BFC1 | Blackfield Chapel | BFC
BFC2 | Blackfield Chapel | BFC
RIE | Randolph Industrial Estate | RIE
LDM | Last Dime Motel | LDM
RSE | Rockshore East | RSE
RSW1 | Rockshore West | RSW
Tierra Robada
ROBAD | Tierra Robada | ROBAD
ROBAD1 | Tierra Robada | ROBAD
ELQUE | El Quebrados | ELQUE
SUNNN | Bayside | SUNNN
BYTUN | Bayside Tunnel | BYTUN
ALDEA | Aldea Malvada | ALDEA
SUNMA | Bayside Marina | SUNMA
BARRA | Las Barrancas | BARRA
ROBINT | Robada Intersection | ROBINT
Bone County
BONE | Bone County | BONE
PAYAS | Las Payasadas | PAYAS
VALLE | Valle Ocultado | VALLE
ELCA | El Castillo del Diablo | ELCA
ELCA1 | El Castillo del Diablo | ELCA
ELCA2 | El Castillo del Diablo | ELCA
ARCO | Arco del Oeste | ARCO
MEAD | Verdant Meadows | MEAD
BRUJA | Las Brujas | BRUJA
TOM | Regular Tom | TOM
REST | Restricted Area | REST
BIGE | 'The Big Ear' (English) | BIGE
PALMS | Green Palms | PALMS
OCTAN | Octane Springs | OCTAN
PROBE | Lil' Probe Inn | PROBE
CARSO | Fort Carson | CARSO
QUARY | Hunter Quarry | QUARY
Lakes
LSINL | Los Santos Inlet | LSINL
FLINW | Flint Water | FLINW
FISH | Fisher's Lagoon | FISH
SANB1 | San Fierro Bay | SANB
SANB2 | San Fierro Bay | SANB
SHERR | Sherman Reservoir | SHERR
SASO | San Andreas Sound | SASO
Bridges
GANTB | Gant Bridge | GANTB
GANTB1 | Gant Bridge | GANTB
*DAM | The Sherman Dam | DAM
GARV | Garver Bridge | GARV
GARV1 | Garver Bridge | GARV
GARV2 | Garver Bridge | GARV
KINC | Kincaid Bridge | KINC
KINC1 | Kincaid Bridge | KINC
KINC2 | Kincaid Bridge | KINC
FALLO | Fallow Bridge | FALLO
MART | Martin Bridge | MART
MAKO | The Mako Span | MAKO
FRED | Frederick Bridge | FRED


GTA SA Типы пешеходов

Типы пешеходов

Вот перечень типов пешеходов, которые есть в игре:

009A: $Actor = create_actor INT(pedtype) #MODEL at X Y Z

0 | Игрок 1
1 | Игрок 2
2 | Игрок 3
3 | не используется
4 | мужчина
5 | женщина
6 | полицейский
7 | гангстер 1 (Ballas)
8 | гангстер 2 (Grove Street Families)
9 | гангстер 3 (Los Santos Vagos)
10 | гангстер 4 (San Fierro Rifa)
11 | гангстер 5 (Da Nang Boys)
12 | гангстер 6 (Mafia)
13 | гангстер 7 (Mountain Cloud Triad)
14 | гангстер 8 (Varrio Los Aztecas)
15 | гангстер 9 (unused)
16 | гангстер 10 (unused)
17 | чувак, который продаёт наркоту
18 | врач
19 | пожарник
20 | криминал
21 | не нашёл
22 | проститутка
23 | специальный, как Смоук, Свит, Райдер и другие, которые используются в миссиях.
24 | миссия 1
25 | миссия 2
26 | миссия 3
27 | миссия 4
28 | миссия 5
29 | миссия 6
30 | миссия 7
31 | миссия 8

Актёры - это все люди, которых вы видели в игре, кстати игрок тоже явл. полноправным актёром. Чтобы создать актёра, надо сначало загрузить его модель в память, делается это вот этой командой:

model.load(#модель)

Этой командой мы только объявили нужную для загрузки модель,а вот загружаются все модели вот этой командой:

038B: load_requested_models

Эта команда пишется после объявки уже всех используемых в вашем потоке объектов. Вот как будет выглядить то, что я только-что описал:

model.load(#модель1)
model.load(#модель2)
model.load(#модель3)
model.load(#модельN)
038B: load_requested_models

Теперь нужно проверить, загрузились ли все модели в память, а то если не загрузились, а мы с ними что-то делаем,то игра естественно вылетит. Проверка делается следующим способом:

:Check
wait 0
if and
model.available(#модель1)
model.available(#модель2)
model.available(#модель3)
model.available(#модельN)
jf @Check

Полная загрузка делается соединением этих двух вышеописанных выражений:

:MyThread // Первый label потока.Не забудьте, что поток тоже надо создать.
wait 0 // Ждём 0 миллисекунд,если не напишем, то игра вылетит.
model.load(#модель1)// Тут объявляем нужные для потока модели.
model.load(#модель2)
model.load(#модель3)
model.load(#модельN)
038B: load_requested_models
// А вот тут уже загружаем нужные для потока модели.

:Check // Создаём другой label.
wait 0 // Ждём 0 миллисекунд, если не напишем, то игра вылетит.
if and // Пишем условие с выполнением всех подусловий (проверок).
model.available(#модель1)// Подусловие на загруженность модели в память.
model.available(#модель2)
model.available(#модель3)
model.available(#модельN)
jf @Check // Если в условии не выполнились подусловия, то перходим в
//начало проверки, если же все выполнились, то выполнение скрипта идёт дальше.

Актёр создаётся следующей командой:
actor.create(name,type,model,x,y,z)
name - имя актёра, должно обязательно начинаться на $(глобальная переменная) или заканчиваться на @ (переменная, действующая только в том потоке, в котором вы её объявили), а вобщем-то всё по поводу типов данных написано в главе "Типы данных".
type - это тип актёра, тип актёра - целое число, типы приведены ниже .
model - это модель актёра, все модели обыкновенных актёров написаны во втором столбике файла
"Peds.ide", который находится в папке "data" вашего GTA San Andreas. Откройте его любым текстовым редактором. Перед именем модели всегда надо ставить знак "#", кавычек не надо.
x - координата по оси X
y - координата по оси Y
z - координата по оси Z
Вот например:

actor.create($MyAct,4,#FAM1,-2400.0,500.8,24.2)

заметьте, что координата всегда число с точкой, всё по поводу чисел в главе "Типы данных".

Давайте создадим актёра возле дома CJ'я:
Я создал поток с именем MAN,как создавать потоки писалось в первой главе,вот этой командой:

create_thread @MAN

Затем нашёл строчку -Mission 0- и выше неё написал:

Copy to Clipboard
:MAN //имя нашего потока
wait 0 // поставил нулевую задержку, если не поставить, то игра вылетит
model.load(#FAM1) // объявил нужную для загрузки модель актёра
038B: load_requested_models // загрузил ранее объявленые модели

:MAN_2 // создал второй label нашего потока
wait 0 // поставил нулевую задержку, если не поставить, то игра вылетит
if // Пишем условие для одной проверки
model.available(#FAM1) // проверяем загрузилась ли наша модель
jf @MAN_2
// если ещё не загрузилась, то выполнение скрипта переходит на label "MAN_2"
  // если уже загрузилась, то выполнение скрипта пойдёт дальше.
actor.create($MyAct,4,#FAM1,2494.4622,-1680.92,13.3385)
// написал вот эту команду,затем нашёл
  //координаты Coords Manager'oм,как это делать писалось в первой главе,
  // и подставил их в команду, не забудьте про запятые между параметрами!
  // И вот такой чувачок возле входа в дом CJ'я получился.
Model.Destroy(#FAM1) // удаляем модель из памяти
end_thread // И заканчиваем наш поток.

Потренеруйтесь, меняя координаты актёра, меняя его модель, увеличиваяя кол-во актёров.

Тут я описал то, что можно делать с актёрами и игроком, проверки потом.
1) То, что применяется только к игроку($PLAYER_CHAR):
052C: set_player $PLAYER_CHAR drunk_visuals 100 - экран шатается, как-будто CJ пьяный.
player.CanMove($PLAYER_CHAR) = false - игрок не может двигаться (true - может, false - не может).
player.ClearWantedLevel($PLAYER_CHAR) - убрать игроку звёзды розыска.
player.Money($PLAYER_CHAR) += 1000000 - добавить игроку деньги.
0998: add respect 5 - добавляет респект (только для игрока).
0992: set_player $PLAYER_CHAR weapons_scrollable 1 - даёт игроку возможность менять оружее, которое у него в руках (0 - не даёт, 1 - даёт).
0221: set_player $PLAYER_CHAR trapped_in_car 1 - закрепляет игрока в машине, не давая возможности выйти оттуда (если 0, то можно).

2) То, что применяется ко всем актёрам и игроку $PLAYER_ACTOR:
0503: create_rappel 27 #MODEL at 2223.5601 -1168.05 32.28 with_actor $Act -
создаёт верёвку длинной 27 с актёром $Act (#MODEL-модель актёра) в заданных кооринатах.
Actor.Health($Actor) = 1000 - устанавливает кол-во жизи у актёра.
Actor.Armour($Actor) = 150 - устанавливает кол-во брони актёра.
Actor.Angle($Actor) = 250.24 - устанавливает угол поворота актёра.
01B2: give_actor $Actor weapon 38 ammo 2000 - даёт актёру оружее, сначало загрузите модель.
Цифра 38-это номер оружия, номера можно посмотреть в главе "Пикапы (Pickups)", модели там же.
0555: remove_weapon 38 from_actor $Actor - забирает у актёра оружее (#MINIGUN).
actor.DestroyInstantly($Actor) - уничтожает актёра.
0819: $Dist = actor $PLAYER_ACTOR distance_from_ground - записывает в переменную $Dist расстояние между актёром и землёй
054A: set_actor $Actor immune_to_car_headshots 1 // устанавливает актёру иммунитет от выстрелов в голову из машины.
$Car = Actor.Car($Actor) - заносит в переменную $Car имя машины актёра $Actor.
actor.PutAt($Actor,1234.0,-189.0,36.0) - перемещает актёра $Actor в заданные координаты.
05D1: AS_actor $Actor drive_car $Car to 1234.0 -189.0 36.0 speed 15.0 0 0 0 - актёр $Actor
садится в машину $Car и едет в заданную точку(X, Y, Z) с заданной скоростью ($Speed).
05D4: AS_actor $Actor rotate_angle 175.8 - актёр поворачивается на угол.
069B: attach_object $Obj to_actor $Actor at_offset 0.0 0.0 0.0 rotation 0.0 0.0 0.0 -
прицепляет к актёру объект на опред. расстоянии от цетра актёра и под опред. углом.
0672: AS_actor $Actor attack_car $Car - актёр атакует машину.
0850: (unknown) $Act1 $Act2 - актёр один следует за актёром два.
04EB: AS_actor $Actor crouch 1 - актёр приседает, если 1, то присел, 0 - встал.
0332: set_actor $Actor bleeding_to 1 - актёр истекает кровью (1 - истекает, 0 - не истекает).
06BA: unknown_action_sequence $Actor 1234.0,-189.0,36.0 - актёр смотроит в точку .
04C4: create_coordinate $1 $2 $3 from_actor $Actor offset 10.0 12.6 3.0 - создаёт точку с координатами $1 $2 $3 от актёра на заданном расстоянии по координатным осям.
actor.StorePos($Actor,$1,$2,$3) - записывает координаты актёра в переменные $1, $2, $3.
011A: set actor $Actor flags 64 - задаёт актёру флаги.
03FE: set actor $Actor money 0 - устанавливает кол-во денег актёру.
05CD: AS_actor $Actor exit_car $Car - актёр выходит из машины.
054A: set_actor $Actor immune_to_car_headshots 0 - устанавливает иммунитет к headshot'у.
0631: put_actor $Actor in_group $PLAYER_GROUP - устанавливает актёру принадлежность к группе игрока.
Actor.WeaponAccuracy($Actor) = 95 - устанавливает точность стрельбы (проценты).
089E: $X $Y $Z radius 5.0 $Actor - выбрать произвольного актёра из точки с радиусом
091C: $Actor = get_random_actor_from $X $Y $Z radius 9.5 model #FAM1 anim "BOMBER" - получить любого актёра из точки с радиусом, с определённой моделью и анимацией.
0432: $Act = get actor handle from car $Car passenger 0 - записывает в переменную $Act актёра, который сидит на месте пассажира № 0(0 - около водителя, 1 и 2 - на заднем сидении).
05CA: AS_actor $Actor enter_car $Car passenger_seat 0 10000 ms - актёр садится в машину на место возле водителя за 10000 миллисекунд (10 секунд).
09B8: create_blood_gush_at $X_1 $Y_1 $Z_1 offset 1.0 1.0 0.2 density 20 on_actor $Actor - создание кровавого пятна на актёре .
07A5: unknown_action_sequence $Act1 $Act2 1500 - актёр 1 атакует актёра 2 опред.время.
05E2: actor $act1 kill_actor $act2 - актёр 1 убивает актёра 2.
0639: AS_actor $act1 rotate_to_actor $act2 - актёр 1 поворачивается и смотрит на актёра 2.
0967: actor $Actor move_mouth 40000 ms - актёр разговаривает (шевелит губами) опр. время.
0968: actor $Actor stop_mouth - актёр перестаёт разговаривать.
08E5: $Actor = get_created_actor_from_point $X $Y $Z radius 24.0 - получить актёра, который только что появился в точке с заданным радиусом.
06A9: AS_actor $Actor look_at_point -1464.3199 1556.6899 1051.75 6000 ms - заставляет актёра смотреть в определённую точку.
0464: put_actor $Actor into_turret_on_car $Car at_car_offset -1.0 0.1 0.7 position 0 shooting_angle 270.0 with_weapon 38 - помещает актёра в машину, давая возможность стрелять из неё.-1.0 0.1 0.7-это координаты, относительно геом. центра машины, в которые будет помещён актёр, 270.0 - это угол обзора актёра, 38 - оружее, с которым он будет сидеть, не забудьте загрузить модель оружия.
marker.CreateAboveActor($mark,$Act) - создаёт маркер с названием $mark над актёром $Act.
05BB: AS_actor $Actor fall_down 0 time_on_ground -1 - актёр падает на землю,как-будто его прибили и практически сразу встаёт (от изменения параметров ничего не будет).
0729: AS_actor $Actor hold_cellphone 1 - анимация телефона (1 - прикладывает, 0 - убирает), но сначало надо загрузить модель #CELLPHONE, иначе актёр к уху приложит только руку.
062A: change_stat 24 to 1000 - изменяет статистику игрока. О статистиках написано в главе "Статистики".
0376: $Actor = create_random_actor -2107.7 155.1 8.0 - создёт случайного игрока.
087E: set_actor $Actor weapon_droppable 0 - актёр оставляет (не оставляет) оружее после смерти.
0321: kill_actor $Actor - убивает актёра.
05BC: AS_actor $Actor jump 0 - актёр прыгает, 0-стиль прыжка, есть и 1, но особого отличия не видно.
actor.SetImmunities($Actor,1 , 1, 1, 1, 1) - устанавливает актёру определённые имунитеты, тут первая цифра - защита от пуль, вторая - от огня, третья - от взрывов, четвертая - от оружия ближнего боя, а вот пятая наверно от падения.
07FE: set_actor $Actor fighting_style_to 5 6 - устанавливает актёру стиль борьбы, по идее в игре много стилей,но в оригинальном main'e встречаются только 5-6, 6-6 и 7-6.
08C6: set_actor $Actor stay_on_bike 1 - актёр не может упасть с байка никаким образом, если поставить 0 , то может.
05C9: AS_actor $Actor on_guard -1 ms - заставляет актёра быть охранником, типа как в казино.
081A: $Actor 2 - даёт актёру возможность ходить с двумя оружиями сразу.
06B0: AS_actor $Actor sit_down 99999999 ms - актёр сидит опред. время.
05C5: AS_actor $Actor cower 10000 ms - актёр пятиться назад опред. время.
06E3: AS_actor $Actor roll_sideways 1 - актёр идёт в бок или что-то типа этого.
0672: AS_actor $Actor attack_car $Car - актёр атакует машину.
0677: AS_actor $Act1 chat_with_actor $Act2 1 1 - актёр1 разговаривает с актёром2
0467: clear_actor $Actor last_weapon_damage - убирает повреждения, нанесённые актёру в последний раз.
05BA: AS_actor $Actor chew_gum 40000 ms - актёр жуёт жвачку опред.время(временами не жуёт).
0638: AS_actor $Actor stay_put 1 - актёр остаётся на месте,чтобы ему не приказали.
0245: set_actor $Actor walk_style_to "FATMAN" - стиль походки актёра, в оригинальном main'e есть следующие стили походки:
"FATMAN" - толстяк
"GANG1" - гангстер 1
"GANG2" - гангстер 2
"MAN" - мужчина
"WOMAN" - женщина
"BLINDMAN" - слепой мужчина
"SEXYWOMAN" - сексуальная женщина
"DRUNKMAN" - алкаш

Рассмотрим проверки, которые можно применять к актёрам и игроку, т.е. к CJ'ю:

Игрок ($PLAYER_CAHR):

Player.Defined($PLAYER_CAHR) - игрок найден или уже создан.
player.PressingHorn($PLAYER_CAHR) - игрок бибикает,сидя в машине.
wasted_or_busted - игрок арестован или убит.
Player.Controllable($PLAYER_CHAR) - игрок контролируем.
0457: player $PLAYER_CHAR aiming_at_actor $Act - игрок целится в актёра c именем $Act.
Player.WantedLevel($PLAYER_CHAR) > 0 - проверяет уровень розыска у игрока.
Player.Money($PLAYER_CHAR) > $money - cравнивает ваши деньги с целым числом $money.

Игрок ($PLAYER_ACTOR) и актёры:

Actor.Animation($PLAYER_ACTOR) == "FIGHTC_SPAR" - является ли анимация актёра данной.
0965: actor $PLAYER_ACTOR swimming_in_water - актёр плавает в воде.
06EE: actor $PLAYER_ACTOR in_group 260@ - актёр в определённой группе актёров.
actor.InCar($PLAYER_ACTOR,$Car) - $PLAYER_ACTOR в машине $Car.
actor.Driving($PLAYER_ACTOR) - актёр $PLAYER_ACTOR за рулём.
actor.DrivingPoliceVehicle($PLAYER_ACTOR) - актёр $PLAYER_ACTOR за рулём ментовской тачки.
actor.DrivingTaxiVehicle($PLAYER_ACTOR) - актёр $PLAYER_ACTOR за рулём такси.
04A7: actor $PLAYER_ACTOR driving_boat - актёр $PLAYER_ACTOR плывёт на лодке.
actor.DrivingVehicleType($ACTOR,#CAR_MODEl) - актёр $ACTOR в маш. типа #CAR_MODEl.
actor.Dead($PLAYER_ACTOR) - актёр $PLAYER_ACTOR умер.
actor.HasWeapon($ACTOR,Number) - актёр $ACTOR имеет оружее с номером Number, номера
можно посмотреть в главе "ПикАпы (PickUps)".
actor.Stopped($PLAYER_ACTOR) - актёр $PLAYER_ACTOR остановился.
actor.Dead($PLAYER_ACTOR) - актёр $PLAYER_ACTOR умер.
04AD: actor $PLAYER_ACTOR touching_water - актёр $PLAYER_ACTOR касается воды.
04C5: actor $PLAYER_ACTOR photographed - актёр фотографирует.
051A: actor $Act1 damaged_by_actor $Act2 - получил ли актёр1 к-л повреждения от актёра2
031D: actor $Act hit_by_weapon 23 - получил ли актёр к-л повреждения от опред. оружия

Ещё актёрам можно присваивать сложные анимации, о них в главе "Анимации для актёров".

На основе нескольких из написанных мною команд давайте теперь создадим телохранителя с
шестистволкой,который будет охранять вас от нападающих и будет атаковать тех,на кого нападаете вы. Для этого нам понадобятся ещё 3 команды, что они точно означают я не знаю, но их надо ставить для эффективности охранника. Вот они:
0568: (unknown) $Actor 1
08AF: (unknown) $Actor 1000
077A: (unknown) $Actor 4 25
А вот и сам код охранника:

Copy to Clipboard
create_thread @MyGuarder

:MyGuarder
wait 0
model.load(#FAM1)
model.load(#MINIGUN)
038B: load_requested_models

:MyGuarder_2
wait 100
if and
model.Available(#FAM1)
model.Available(#MINIGUN)
jf @MyGuarder_2
wait 5000
04C4: create_coordinate $X1 $Y1 $Z1 from_actor $PLAYER_ACTOR offset 0.0 5.0 0.0
actor.Create(1@,4,#FAM1,$X1,$Y1,$Z1)
0568: (unknown) 1@ 1
0446: set_actor 1@ immune_to_headshots 0
08AF: (unknown) 1@ 1000
077A: (unknown) 1@ 4 25
0631: put_actor 1@ in_group $PLAYER_GROUP
01B2: give_actor 1@ weapon 38 ammo 6000
Actor.WeaponAccuracy(1@) = 90
Actor.Health(1@) = 2000

:MyGuarder_3
wait 0
if or
wasted_or_busted
actor.dead(1@)
jf @MyGuarder_3
actor.DestroyInstantly(1@)
model.destroy(#FAM1)
model.destroy(#MINIGUN)
wait 10000
jump @MyGuarder

Вот Вам ещё полезная вещь - данным кодом можно заставить актёра из туррета атаковать игрока и всю его команду из туррета машины:

Copy to Clipboard
060A: unknown_create_entity 2 1@
$Actor = Actor.Create(Mission4, #SWAT, 2161.8401, -1154.26, 25.09
077A: (unknown) $Actor 4 23
077A: (unknown) $Actor 4 0
060B: unknown_actor_use_entity $Actor 1@
0464: put_actor $Actor into_turret_on_car $Car at_car_offset 1.4 1.3 -0.1 position 3 shooting_angle 190.0 with_weapon 29
07DD: (unknown) $Actor 70

Думаю,что тут разберётесь...

Вы можете посмотреть пример небольшого поединка здесь.


GTA SA Типы поездов

Типы поездов

06D8: 1@ = create_train_at 2278.1771 -1144.8823 27.5108 TYPE 0 direction 1

См. также SA Memory Handling

Типы поездов:

 | Train | Carriage1 | Carriage2 | Carriage3 | Carriage4 | Carriage5
0: | #FREIGHT | #FREIFLAT | #FREIFLAT | #FREIFLAT | #FREIFLAT | o
1,2,4,7,11: | #STREAK | #STREAKC | #STREAKC | o | o | o
3: | #FREIGHT | #FREIFLAT | #FREIFLAT | #FREIFLAT | o | o
5: | #STREAK | #STREAKC | #STREAKC | #STREAKC | o | o
6: | #FREIGHT | #FREIFLAT | #FREIFLAT | o | o | o
8: | #TRAM | #TRAM | o | o | o | o
9,14: | #TRAM | o | o | o | o | o
10: | #FREIGHT | #FREIFLAT | o | o | o | o
12: | #FREIGHT | #FREIFLAT | #FREIFLAT | #FREIFLAT | #FREIGHT | o
13: | #FREIGHT | #FREIFLAT | #FREIFLAT | #FREIFLAT | #FREIFLAT | #FREIFLAT
15: | #STREAK | o | o | o | o | o


GTA SA Части тела игрока

Части тела игрока

087B: set_player $PLAYER_CHAR texture "VEST" model "VEST" body_part 0
Player.SetClothes($PLAYER_CHAR, "VEST", "VEST", Torso)

Player.SetClothes($PLAYER_CHAR, "tshirterisyell", "tshirt", 0)

$PLAYER_CHAR - переменная, обозначающая игрока
tshirterisyell - имя текстуры
tshirt - имя модели
0 - тип места на теле игрока, куда надо цеплять вещь,можно использовать вместо типа имя части.

Учтите, что каждая примочка предназначена только для своей части тела и после изменения к-л примочки надо переделывать модель игрока командой Player.Build($PLAYER_CHAR).

Copy to Clipboard
create_thread @ClothesTest // создаём поток

:ClothesTest // начинаем поток
wait 3000 // ждём 3 секунды
Player.SetClothes($PLAYER_CHAR,"bballjackrstar","bbjack",0) // нацепляем куртку
Player.SetClothes($PLAYER_CHAR,"jeansdenim","jeans",2)  // теперь джинсы
Player.SetClothes($PLAYER_CHAR,"sneakerbincgang","sneaker",3) // кросовки
Player.SetClothes($PLAYER_CHAR,"glasses04dark","glasses04",15)	// чёрные очки
Player.SetClothes($PLAYER_CHAR,"bandblack","bandana",16) // бандану тоже надо
player.Build($PLAYER_CHAR) // и перестраиваем модель игрока
end_thread // заканчиваем поток

Вот таблица номеров и имён частей тела:

 | BODY_PART
0 | Torso | торс
1 | Head (haircuts) | голова
2 | Legs | ноги
3 | Shoes | ступня (обувь)
4 | Lower left arm | верхняя часть левой руки
5 | Upper left arm | нижняя часть левой руки
6 | Upper right arm | верхняя часть правой руки
7 | Lower right arm | нижняя часть правой руки
8 | Back top | спина
9 | Left chest | левая часть груди
10 | Right chest | правая часть груди
11 | Stomach | живот
12 | Lower back | поясница(низ спины)
13 | Necklace | ожерелье
14 | Bracelet/Watch | часы или браслет
15 | Glasses | очки
16 | Hats | головной убор
17 | Special clothes as Valet, Gimp suit | специальная одежда(крупье...)


GTA SA Эффекты частицы

Эффекты частицы

Particle эффект является тоже своеобразной анимацией, но его не надо загружать, он создаётся вот этой командой:

064B: $PaLe = create_particle "EXPLOSION_SMALL" at 2048.0 1600.0 32.0 1

$PaLe - имя нашего эффекта
"EXPLOSION_SMALL" - сам эффект, их описал ниже
2048.0 - координата эффекта по оси X
1600.0 - координата эффекта по оси Y
32.0 - координата эффекта по оси Z
1 - этот параметр, стоящий в самом конце команды, всегда в игре равен 1, так его и оставляйте.

Particle эффект можно также прицеплять к актёрам вот этой командой:

0669: $Atch = attach_particle "EXPLOSION_SMALL" to_actor $Actor offset 0.05 0.12 0.01 1

$Atch - имя нашего эффекта
"EXPLOSION_SMALL" - сам эффект, их описал ниже.
$Actor - актёр, к которому прицепляем эффект
0.05 - координата эффекта по оси X относительно геометрического центра актёра
0.12 - координата эффекта по оси Y относительно геометрического центра актёра
0.01 - координата эффекта по оси Z относительно геометрического центра актёра
1 - этот параметр, стоящий в самом конце команды,всегда в игре равен 1, так его и оставляйте.

Прицепление эффекта к любому транспортному средству осуществляется вот этой командой:

066C: $A = attach_particle "CEMENT" to_vehicle $C offset 0.0 -4.4 0.0 rotation 0.0 1.0 0.0 1

$Atch - имя нашего эффекта
"CEMENT" - сам эффект, их описал ниже.
$Actor - актёр, к которому прицепляем эффект
После "offset" идут координаты пложения эффекта,относительно машины:
0.0 - координата эффекта по оси X относительно геометрического центра актёра
-4.4 - координата эффекта по оси Y относительно геометрического центра актёра
0.0 - координата эффекта по оси Z относительно геометрического центра актёра
1 - этот параметр, стоящий в самом конце команды,всегда в игре равен 1, так его и оставляйте.
После "rotation" идут координаты поворота эффекта по всем коорд. осям:
0.0 - по оси X
1.0 - по оси Y
0.0 - по оси Z
1 - этот параметр, стоящий в самом конце команды,всегда в игре равен 1, так его и оставляйте.

Можно прицепить эффект конкретно к машине,но тогда его нельзя будет вращать:

066B: $Atch = attach_particle "PRT_SPARK" to_car $Car offset -1.69 3.607 -0.271 1

$Atch - имя нашего эффекта
"PRT_SPARK" - сам эффект, их описал ниже.
$Car - машина, к которой прицепляем эффект
0.05 - координата эффекта по оси X относительно геометрического центра машины
0.12 - координата эффекта по оси Y относительно геометрического центра машины
0.01 - координата эффекта по оси Z относительно геометрического центра машины
1 - этот параметр, стоящий в самом конце команды,всегда в игре равен 1, так его и оставляйте.

Эфффекты можно и к объектам цеплять, цепляется вот этой командой:

066D: $Atch = attach_particle "SMOKE_FLARE" to_object $Obj offset 0.1 0.2 0.3 1

$Atch - имя нашего прицепления
"SMOKE_FLARE" - сам эффект, их описал ниже
$Obj - имя объекта.
0.1 - координата эффекта по оси X относительно геометрического центра объекта
0.2 - координата эффекта по оси Y относительно геометрического центра объекта
0.3 - координата эффекта по оси Z относительно геометрического центра объекта
1 - этот параметр, стоящий в самом конце команды,всегда в игре равен 1, так его и оставляйте.

Вот список particle эффектов, которые существуют в игре:

"blood_heli" | Кровавый взрыв
"boat_prop" | прибой
"camflash" | Маленькая вспышка
"carwashspray" | Пар, как на автомойке.
"cement" | цемент
"cloudfast" | Летающие облака
"coke_puff" | Затяжка коксом
"coke_trail" | Выливающаяся вода
"cigarette_smoke" | Дым от сигареты
"explosion_barrel" | Взрыв и осколки ящика
"explosion_crate" | Взрыв и осколки большого ящика
"explosion_door" | Дым с искрами
"exhale" | Маленький дым
"explosion_fuel_car" | Взрыв, как от машины
"explosion_large" | Большой взрыв
"explosion_medium" | Средний взрыв
"explosion_molotov" | Взрыв, как от коктейля Молотова
"explosion_small" | Небольшой взрыв
"explosion_tiny" | Маленький взрыв
"extinguisher" | Пена огнетушителя
"flame" | Небольшой огонек
"fire" | огонь
"fire_med" | Средний огонь
"fire_large" | Большой огонь
"flamethrower" | Огонь огнемета
"fire_bike" | Огонь, как от горящего мотоцикла
"fire_car" | Огонь, как от горящей машины
"gunflash" | Как вылетает пуля из ствола
"gunsmoke" | Дым от вылетевшей пули
"insects" | насекомые
"heli_dust" | Пыль, как от вертолета
"jetpack" | Огонь, как из сопел джетпака
"jetthrust" | Огонь из глушителя машины, как во время использования азота
"nitro" | нитро
"molotov_flame" | Огонь от коктейля Молотова
"overheat_car" | Дымящаяся машина
"overheat_car_electric" | Поврежденная электро-машина
"prt_boatsplash" | пена
"prt_cardebris" | Осколки от коробки
"prt_collisionsmoke" | Плотный белый дым
"prt_glass" | Разбивающееся стекло
"prt_gunshell" | Гильзы
"prt_sand" | Песок, который рассыпался
"prt_sand2" | Немного меньше песка чем в предыдущей анимации
"prt_smokeII_3_expand" | Серый дым
"prt_smoke_huge" | Много серого дыма
"prt_spark" | Искры
"prt_spark_2" | Большие искры
"prt_splash" | Всплеск
"prt_wake" | Волна
"prt_watersplash" | Брызги
"prt_wheeldirt" | Брызги из под колес машины
"petrolcan" | Струя, как писание
"puke" | Рыгачка (блевотина)
"riot_smoke" | Много дыма
"spraycan" | Спрей зеленой краски
"smoke30lit" | Дым
"smoke30m" | Густой дым
"smoke50lit" | Еще более густой дым
"shootlight" | Фейерверк
"smoke_flare" | Тоже фейерверк
"tank_fire" | Огонь от выстрела из танка
"teargas" | Газ, как от дымовой гранаты
"teargasAD" | Газ, как от малой дымовой гранаты
"tree_hit_fir" | Падение листьев
"tree_hit_palm" | Падение пары больших листьев
"vent" | Медленно рассеивающийся дым
"vent2" | Практически тоже самое
"water_hydrant" | Большой поток воды
"water_ripples" | Круги на воде
"water_speed" | Большие брызги от воды
"water_splash" | Маленькие брызги от воды
"water_splash_big" | Средние брызги
"water_splsh_sml" | Брызги, только их почти не видно
"water_swim" | Маленькие брызги при плавании
"waterfall_end" | Много пара
"water_fnt_tme" | Большой поток воды
"water_fountain" | Вода фонтана
"wallbust" | Исчезающая куча пара
"WS_factorysmoke" | Дым как от труб

После создания или прицепления эффекта всегда надо писать команду, которая делает эффект видимым:

064C: make_particle $PaLe visible , $PaLe - имя эффекта.

Чтобы уничтожить эффект надо использовать вот эту команду:

0650: destroy_particle $PaLe , $PaLe - имя эффекта.


Документация по SCM: GTA VC

GTA VC


GTA VC ID банд

ID банд

0236: set_gang 4 car_to #BAGGAGE
0235: set_gang 2 models_to #ARMY #ARMY

Gang0 | Cubans
Gang1 | Haitians
Gang2 | Street wannabees
Gang3 | Columbians (Diaz's)
Gang4 | Renta Cops (PIGs)
Gang5 | Bikers
Gang6 | Vercetti (yours)
Gang7 | Golfers
Gang8 | Army (special gang)


GTA VC Иконки радара

Иконки радара

02A8: create_marker 236?? 28? at 396?? 400?? 404??

236? - маркер ID

Измените 28? на один из ниже перечисленных вариантов иконок.

0 | Small purple dot
1 | Large player type icon
2 | Small arrow
3 | North on the Map
4 | Avery
5 | radar_biker
6 | Colonel Cortez
7 | Diaz
8 | Kent
9 | Ken Rosenberg
10 | Phil
11 | Biker's Bar
12 | Docks
13 | Malibu Club
14 | Cuban missions
15 | P0rn Studios
16 | AmmuNation
17 | Haitian missions
18 | Toolshop
19 | Save Game Icon
20 | Pole Position Club Icon
21 | Cherry Poppers Icon
22 | Kauffman Cabs Icon
23 | lovefist - Love Fist
24 | Printworks Icon
25 | No Icon
26 | Sunshine Autos Icon
27 | Spray 'n' Pay
28 | Clothing pickup
29 | Tommy's Home Icon
30 | The Phone Icon
31 | Wildstyle station logo
32 | Flash station logo
33 | KChat station logo
34 | Fever station logo
35 | VRock station logo
36 | VCPR station logo
37 | Espantoso station logo)
38 | Emotion station logo
39 | Wave station logo


GTA VC Имена гаражей

Имена гаражей
Garage ID - Description
1 | Placeholder, DummyID. (doesn't do anything,
 | initial garages get 1, and change type when
 | a certain asset is bought)
3 | BombShop (8ball)
5 | Pay and Spray
7 | Car Eater, haven't got a clue what this is
 | suppose to be, not sunshine autos anyways...
8 | Sunshines Autos Carshop, List 1
9 | Sunshines Autos Carshop, List 2
10 | Sunshines Autos Carshop, List 3
13 | DO NOT USE, CORRUPTS SAVEGAMES!
16..18 | In use Saving Garages
19 | Garage where you beat the cops up during "Copland"
22 | Sunshines Autos Carshop, List 4
23 | Garage to park the tank in during "Sir, Yes Sir!"
24..31 | In use Saving Garages
32 | Unused Saving Garage


GTA VC Интерьеры

Интерьеры
0 | outside
1 | hotel
2 | mansion
3 | bank
4 | mall
5 | stripclub
6 | lawyers
7 | cafe robina
8 | concert
9 | studio
10 | shooting range
11 | apartment/bikerbar
12 | policeHQ
14 | stadium1
15 | stadium2
16 | stadium3
17 | Malibu club
18 | Print Works


GTA VC Номера клавиш

Номера клавиш

My tested key_press numbers in Vice. Returned by

00E1: key_pressed 0? <number tested>?

with standard controls setup. Made from ghost_master2000's list.

Number | On Foot | In Car
2 | turn left/right | Look left + turret L and Look right + turret
3 |  | turret up/down
4 | action key | Radio
5 | prev. weapon | look left/behind
6 | aim/target | handbrake
7 | next weapon | look right/behind
8 | forward |
9 | backward |
10 | strafe left | turn left
11 | strafe right | turn right
13 | camera | camera
14 | jump | brake/reverse
15 | enter vehicle | exit vehicle
16 | sprint | gas/forward
17 | shoot/attack | shoot
18 | crouch | horn
19 | look behind | sub-mission

With classic setup

Number | On Foot | In Car
3 | Look left and right | turret up/down

In certain situations like when then lock_actor code is used, keypress number 12 is used. I don't know how to set that key up.

Number | On Foot | In Car
12 | Used to exit certain modes


GTA VC Номера oружия

Номера oружия

Tested and confirmed weapon numbers returned by

031D: actor <actor> hit_by_weapon <weapon number>

Number | Group | Name | Model name | Icon
0 |  | Unarmed |  |
1 |  | BrassKnuckle | #brassknuckle |
2 |  | ScrewDriver | #screwdriver |
3 |  | GolfClub | #golfclub |
4 |  | NightStick | #nitestick |
5 |  | Knife | #knifecur |
6 |  | BaseballBat | #bat |
7 |  | Hammer | #hammer |
8 |  | Cleaver | #cleaver |
9 |  | Machete | #machete |
10 |  | Katana | #katana |
11 |  | Chainsaw | #chnsaw |
12 | 2 | Grenade | #grenade |
13 | 2 | DetonateGrenade | #bomb |
14 | 2 | TearGas | #teargas |
15 | 2 | Molotov | #molotov |
16 | 2 | Rocket | #missile |
17 | 3 | Colt45 | #colt45 |
18 | 3 | Python | #python |
19 | 4 | Shotgun | #chromegun |
20 | 4 | Spas12Shotgun | #shotgspa |
21 | 4 | StubbyShotgun | #buddyshot |
22 | 5 | Tec9 | #tec9 |
23 | 5 | Uzi C | #uzi |
24 | 5 | SilencedIngram | #ingramsl |
25 | 5 | Mp5 | #mp5lng |
26 | 6 | m4 | #m4 |
27 | 6 | Ruger | #ruger |
30 | 7 | RocketLauncher | #rocketla |
31 | 7 | FlameThrower | #flame |
32 | 7 | M60 | #M60 |
33 | 7 | Minigun | #minigun |
35 | 7 | HeliCannon |  |
28 | 8 | SniperRifle | #sniper |
29 | 8 | LaserScope | #laser |
34 | 9 | Detonator |  |
36 | 9 | Camera | #camera |


GTA VC Типы пешеходов

Типы пешеходов
0 | player1
1 | player2
2 | player3
3 | player4
4 | civmale
5 | civfemale
6 | cop
7 | gang1
8 | gang2
9 | gang3
10 | gang4
11 | gang5
12 | gang6
13 | gang7
14 | gang8
15 | gang9
16 | emergency
17 | fireman
18 | criminal
19 | special


Документация по SCM: GTA LCS

GTA LCS


GTA LCS Gang IDs

Gang IDs

023B: set_gang 0 car_to 172

GANG0 | Leone
GANG1 | Triad
GANG2 | Diablo
GANG3 | Yakuza
GANG4 | Yardie
GANG5 | Colombian
GANG6 | Hood
GANG7 | Forelli
GANG8 | Sindacco


GTA LCS ID погоды

ID погоды

01BB: set_weather 1

0 | SUNNY
1 | CLOUDY
2 | RAINY
3 | FOGGY
4 | EXTRA SUNNY
5 | HURRICANE
6 | EXTRA COLOURS
7 | SNOW


GTA LCS Weapon numbers

Weapon numbers

!untested, incomplete

01B6: give_player $PLAYER_CHAR weapon 1 ammo 1

Weapon ID | Model ID | Name
0 | - | Unarmed
1 | 259 |
2 | 260 |
3 | 261 |
4 | 262 |
5 | 263 |
6 | 264 |
7 | 265 |
8 | 266 |
9 | 267 |
10 | 268 |
11 | 269 |
12 | 270 | Grenades
13 | 291 |
14 | 271 ? |
15 | 272 |
16 | 273 ? |
17 | 274 | Pistol
18 | 275 | .357
19 | 277 | Shotgun
20 | 278 |
21 | 279 |
22 | 281 |
23 | 282 | Micro-SMG
24 | 283 |
25 | 284 | SMG
26 | 280 | M4
27 | 276 | AK-47
28 | 285 | Sniper Rifle
29 | 286 |
30 | 287 | Rocket Launcher
31 | 288 | Flame-Thrower
32 | 289 |
33 | 290 | Minigun
34 | ? |
35 | ? |
36 | 292 | Name


GTA LCS Одежда игрока

Одежда игрока

0357: set_actor $PLAYER_ACTOR skin_to 'PLR3'

'PLR' | Leone's suit
'PLR2' | Lawyer's suit
'PLR3' | Casual clothes
'PLR4' | Chauffeur's clothes
'PLR5' | Overalls
'PLR6' | Tuxedo
'PLR7' | Avenging Angel's fatigues
'PLR8' | 'The King' jumpsuit
'PLR9' | Cox Mascot suit
'PLR10' | Underwear
'PLR11' | Hero garb
'PLR12' | 'Dragon' jumpsuit
'PLR13' | Antonio
'PLR14' | Sweats
'PLR15' | Wiseguy
'PLR16' | Goodfella


GTA LCS Special Actors

Special Actors

0241: load_special_actor 1 'PLR6'

AVERY | Avery Carrington
BABY | Giovanni Casa (baby)
BIKER1 | Biker Dude 1
BIKER2 | Biker Dude 2
BODYBAG | BODYBAG
CAMP_MAN | Campaign Worker
CAMP_WOM | Campaign Worker 2
CASA | Giovanni Casa
CHAUFF | Chauffeur
DELIASS | Deli Assistant
DONOVAN | O'Donovan
EIGHT | 8Ball
FKENNY | Father Kenny (not used)
FRANFOR | Franco Forelli
GRDANG1 | Avenging Angel
GRDANG2 | Avenging Angel 2
GREASE | Grease Zuko
GUN_ASS | Gun assistant
HOBO_01 | Donald Love 2
HOLEJOG | Mayor RC Hole (Jogging outfit)
HOPPER | Jane Hopper
JD_SHOT | dead JD
JDMADE | JD O'Toole - Made Man
KAS_01 | Toshiko Kasen (kimono)
KAZUKI | Kazuki Kasen
LOVE_01 | Donald Love
M_HOLE | Mayor RC Hole
MAR_01 | Maria
MASTOR | Massimo Torrini (Assassin)
MCAFFRY | Det. Leon McAffrey
MICKEYH | Mickey H
MIGUEL | Miguel
NED_01 | Ned Burner (Reporter)
PAULIE | Paulie Sindacco
PHILC | Phil Cassidy
PLR10 | player (skin: boxer Shorts)
PLR11 | player (skin: bad super hero)
PLR12 | player (skin: dragon)
PLR2 | player (skin: lawyer)
PLR3 | player (skin: travel clothes)
PLR4 | player (skin: chauffeur)
PLR5 | player (skin: hockey mask)
PLR6 | player (skin: tuxedo)
PLR7 | player (skin: avenging angel)
PLR8 | player (skin: the King of Rock'n Roll)
PLR9 | player (skin: cock's mascot)
RAY_01 | Ray (Bad Cop)
SAL_01 | Salvatore (Mob Don)
SAL_CON | Sal CONVICT
THUG_01 | Sicilian Thug 1
THUG_02 | Sicilian Thug 2
TOOL_01 | JD O'Toole
VINC_01 | Vincenzo Cilli
WAYNE | Wayne (Biker Dude)
WKAS_01 | Toshiko Kasen (western)


GTA LCS Типы пешеходов

Типы пешеходов
Model ID | Model Name
0 | PLAYER
1 | COP
2 | SWAT
3 | FBI
4 | ARMY
5 | MEDIC
6 | FIREMAN
7 | MALE01
8 | <unknown>
9 | TAXI_D
10 | PIMP
11 | CRIMINAL01
12 | CRIMINAL02
13 | MALE02
14 | MALE03
15 | FATMALE01
16 | FATMALE02
17 | FEMALE01
18 | FEMALE02
19 | FEMALE03
20 | FATFEMALE01
21 | FATFEMALE02
22 | PROSTITUTE
23 | PROSTITUTE2
24 | P_MAN1
25 | P_MAN2
26 | P_WOM1
27 | P_WOM2
28 | CT_MAN1
29 | CT_MAN2
30 | CT_WOM1
31 | CT_WOM2
32 | LI_MAN1
33 | LI_MAN2
34 | LI_WOM1
35 | LI_WOM2
36 | DOCKER1
37 | DOCKER2
38 | SCUM_MAN
39 | SCUM_WOM
40 | WORKER1
41 | WORKER2
42 | B_MAN1
43 | B_MAN2
44 | B_MAN3
45 | B_WOM1
46 | B_WOM2
47 | B_WOM3
48 | MOD_MAN
49 | MOD_WOM
50 | ST_MAN
51 | ST_WOM
52 | FAN_MAN1
53 | FAN_MAN2
54 | FAN_WOM
55 | HOS_MAN
56 | HOS_WOM
57 | CONST1
58 | CONST2
59 | SHOPPER1
60 | SHOPPER2
61 | SHOPPER3
62 | STUD_MAN
63 | STUD_WOM
64 | CAS_MAN
65 | CAS_WOM
68 | HITMAN
79 | GANG01 LEONE_A
80 | GANG02 LEONE_B
81 | GANG03 TRIAD_A
82 | GANG04 TRIAD_B
83 | GANG05 DIABLO_A
84 | GANG06 DIABLO_B
85 | GANG07 YAKUZA_A
86 | GANG08 YAKUZA_B
87 | GANG09 YARDIE_A
88 | GANG10 YARDIE_B
89 | GANG11 COLOMBIAN_A
90 | GANG12 COLOMBIAN_B
91 | GANG13 HOOD_A
92 | GANG14 HOOD_B
93 | GANG15 Forelli thug1
94 | GANG16 Forelli thug2
95 | GANG17 Sindacco thug1
96 | GANG18 Sindacco


Документация по SCM: GTA VCS

GTA VCS


GTA VCS ID банд

ID банд
Gang0 | Umberto's guys
Gang1 | Cholos
Gang2 | Sharks
Gang3 | Army
Gang4 | Security
Gang5 | Bikers
Gang6 | Vance gang
Gang7 | Golfer
Gang8 | Marty's


GTA VCS ID погоды

ID погоды

0109: set_weather 7

0 | Sunny
1 | Cloudy
2 | Rainy
3 | Foggy
4 | Extra sunny
5 | Hurricane
6 | Extra colours
7 | Ultra sunny


GTA VCS Одежда игрока

Одежда игрока
OUT_F1 | Army Fatigues
OUT_F2 | Casuals
OUT_F3 | Leisure
OUT_F4 | Trailer Trash
OUT_F5 | Cuban Style
OUT_F6 | Pastel Suit
OUT_F7 | Tracksuit
OUT_F8 | Hood
OUT_F9 | Hired Muscle
OUT_F10 | Repo-Man
OUT_F11 | Smuggler
OUT_F12 | Smart Suit
OUT_F13 | Winner
OUT_F14 | Wet Suit


Документация по SCM

Sanny Builder Help: Статьи

Введение в скриптинг

  • Quick Start. Часть 1

  • Quick Start. Часть 2

  • Типы данных

  • Основы скриптинга

  • Условия

  • Условные опкоды

  • Переходы

  • Пикапы

  • Анимации для актеров

  • Текст

  • Панель, или список товаров

  • Панель, или список товаров. Часть II

  • Видео и аудио

  • Специальные актеры

  • Контроль клавиатуры

  • Транспорт

  • Работа со звуками в GTA San Andreas

  • Удалённое управление

  • Разное

  • Создание миссии. Часть 1

  • Создание миссии. Часть 2

  • Создание миссии. Часть 3

  • Создание миссии. Часть 4

  • Миссии
Опытным пользователям
  • External Script – что это такое и как с ним работать?

  • Внешние скрипты

  • События актёров

  • Меняем игровую память через SCM (San Andreas)

  • Таблицы переходов

  • Проверка нажатия клавиш

  • Работа с битами переменной

Статьи по материалам SB Manual2 от Alexander'а и сайтов http://sannybuilder.com и http://yelmi.com


Введение в скриптинг.

Данная статья предназначена для тех, кто в первый раз знакомится со скриптингом. Информация, изложенная ниже, будет полезна и тем, кто не хочет тратить часы свободного времени для того, чтобы только добавить новый скрипт.

Итак, скрипты GTA хранятся в нескольких файлах. Большая часть игровой логики заложена в исполняемом файле (.exe) и неразрывно связана с игровым процессом. Скриптеры работают со скриптами, хранящимися в файле main.scm.

Main.scm представляет собой бинарный файл, в котором хранятся скомпилированные скрипты. Это означает, что вы не можете открыть этот файл в текстовом редакторе и начать его редактировать. Для изменения таких скриптов вам понадобится специальная программа. Одной из таких является Sanny Builder (SB). Он позволяет переводить скомпилированные скрипты в текст (этот процесс именуется декомпиляцией). Полученный текст (исходник) может легко быть изменен. Но для того чтобы изменения вступили в силу, исходник нужно собрать обратно в main.scm (этот процесс именуется компиляцией). Таким образом, процесс скриптинга условно можно изобразить в виде следующей схемы:

main.scm->декомпиляция->изменение исходника->компиляция->main.scm

Процессом декомпиляции и компиляции занимается Sanny Builder. Для декомпиляции файла main.scm вам нужно открыть его нажатием F5, для компиляции исходника нужно нажать F7. Скриптер занимается лишь редактированием исходника.

Предположим, вам нужно добавить в игру новый скрипт, который был опубликован в Интернете в виде исходника. Обычно такие скрипты выполнены в виде отдельного потока. На данном этапе мы не будем разбирать, что такое поток. Я просто опишу последовательность действий, которые нужно выполнить на примере мода «Ограничитель скорости»

Запустите Sanny Builder. Зайдите в Настройки, нажав кнопку F10. Если вы плохо понимаете английский язык, можно переключить язык интерфейса на русский, выбрав его в списке. Поскольку вы новичок, то можете включить опцию ‘Использовать опкоды’. Вам нужно также указать папку, в которой установлена игра.

Нажмите кнопку с тремя точками и укажите путь к игре. После этого закройте Настройки, нажав OK.
На данном этапе рекомендуется перезапустить SB, чтобы были загружены необходимые файлы игры.
Более подробное описание всех настроек можно прочитать здесь.

Теперь декомпилируйте имеющийся у вас main.scm. Он хранится в папке data в директории игры. Нажмите F5 в SB и выберите этот файл. В нижней части окна будет отображаться процесс декомпиляции. Если все прошло успешно, перед вами появится окошко с отчетом. Если вы не хотите, чтобы это окошко появлялось – отключите его в настройках.
Если в ходе декомпиляции возникла ошибка, постарайтесь следовать инструкциям, которые будут показаны в сообщении ошибки. Чаще всего ошибки возникают, если вы не указали путь к игре, либо выбрали неверный режим редактирования. Оригинальный файл main.scm должен декомпилироваться без каких-либо затруднений.

Итак, декомпиляция прошла и вы получили исходный файл. Он будет автоматически сохранен в той же папке, где находится файл main.scm. Вы можете изменить адрес сохранения и формат имени исходника в настройках программы. Не пугайтесь большого размера файла. Со временем вы научитесь ориентироваться в нем не хуже, чем в своей собственной квартире, если, конечно, вы в этом заинтересованы. Подробное описание устройства исходника вы можете прочитать здесь.

Нам нужно добавить скрипт в этот исходник. Вместе со скриптом должен идти комментарий автора об особенностях установки. Если таких комментариев нет, либо в начале скрипта написана команда create_thread, значит вам нужно создать новый поток. Для этого откройте поиск (Ctrl+F), и найдите слово ‘create_thread’ (без кавычек). Если вы работаете с оригинальным файлом, то эта найденная строка должна быть примерно 948-й. Там же должны быть и другие строки, начинающийся с create_thread. Если вы не нашли такой строки (например, если вы работаете с модифицированным файлом), попробуйте найти строку с опкодом 0180:.

После найденной строки добавьте новую с командой create_thread @имя_потока. Имя потока обычно указывается в начале скрипта. Если этого указания нет, то именем потока будет имя первой метки (строка, начинающая со знака двоеточия). В нашем пример имя потока - @ogranichitel. Добавьте строку create_thread @ogranichitel после найденной.

Теперь нужно добавить сам поток (скрипт). Для этого найдите самую первую миссию (mission 0). Там должен стоять комментарий //-------------Mission 0---------------. Добавьте весь (за исключением команды create_thread) код скрипта перед этим комментарием
Если вы не нашли миссию 0, попробуйте добавить скрипт в конец файла.

Итак, исходник теперь выглядит примерно так

// This file was decompiled …
DEFINE OBJECTS
DEFINE OBJECT (noname)
...
0363: create_object_at …
004F: create_thread @ODDVEH
create_thread @ogranichitel
004F: create_thread @R3
…
:MOB_GF_3609
00BE: text_clear_all
0051: return

:ogranichitel
wait 5000

:ogranichitel_2

<скрипт>

jump @ogranichitel_2

//-------------Mission 0---------------
// Originally: Initial 1

…

Теперь вам осталось скомпилировать файл. Для этого нажмите F7. Если во время компиляции возникли ошибка, следуйте ее инструкциям.
После успешной компиляции запускайте игру нажатием F8 и проверяйте скрипт в игре.

Если вам нужно добавить несколько скриптов, необязательно каждый раз декомпилировать main.scm. Просто добавьте скрипты в один исходный файл и скомпилируйте его.


Quick Start. Часть 1
Начнем с того, что, если поначалу вам непривычны новшества в Sanny, то просто включите опцию Write opcodes в настройках и используйте его также как SaMB (а поковыряв прочие настройки, можно вообще сделать два редактора практически одинаковыми внешне). При этом воз и тележка разнообразных фич и удобств проги, а также высокая скорость работы по-прежнему будут в вашем распоряжении.

Вы также откроете для себя очень много полезного, внимательно прочитав readme.txt из комплекта Sanny Builder. Там указаны абсолютно все отличия и новшества Sanny по сравнению с редактором Mission Builder. К сожалению в настоящий момент в ридми практически не рассматриваются основы скриптинга (создание потоков, миссий и т.п.). Однако эти основы являются общими для обеих программ и, если у вас возникают проблемы, вы можете ознакомиться с этим сборником вопросов по Mission Builder'у. Большая часть того, что там написано, действительно и для SB.
SB может использоваться для редактирования скриптов всей линейки GTA3 (GTA3, VC, SA).

Краткий перечень важных отличий между программами:

а) В переходах в SB используется символ @ вместо нечитаемого на многих форумах символа английского фунта (JJ): jump @Label, gosub @Label
Важный момент, что метки, независимо от их положения в коде, записываются одинаково. В SAMB вам приходилось бы писать в миссиях метки с одним знаком J, а в потоках с двумя - JJ.
Локальные переменные, следовательно, записываются с номером переменной в начале (а не в конце как в SAMB). Например:

@1, @2, @3 - формат SAMB
1@, 2@, 3@ - формат SB

б) Множество простых скриптовых команд можно записывать БЕЗ опкодов, таких как wait, end_thread, jump и т.п. Данные слова именуются кейвордами и заменяют собой часто используемые опкоды. Например:

wait 0 - аналог 0001: wait 0 ms
if - аналог 00D6: if 0
if and - аналог 00D6: if 1-7
if or - аналог 00D6: if 21-27
jf @Label - аналог 004D: jump_if_false @Label

и многие другие. Список возможных кейвордов можно вызвать в редакторе нажатием Ctrl+Space.

в) Работа с числами. Все арифметические действия также можно (и нужно) записывать без опкода, например вот так:

$Var = 1
$Var = 45.5
$Var += 5
$Var *= 0.01

Данная возможность полностью перекладывает на компилятор работу по подбору нужного опкода для выражения. Вам лишь нужно указать знаки действий (+, -, >, ==, и т.д.), причем опкоды подбираются как для локальных, так и для глобальных переменных. Sanny Builder поддерживает ВСЕ виды математических знаков, включая <=, <>, <. Последние удобно использовать в негативных условиях (со словом not). Например вместо:

if
not $Var == 1
jf @label

можно написать

if
$Var <> 1
jf @label

В том случае, если в выражении оба параметра - переменные, компилятор не может сразу определить, какого они типа - целые или дробные числа. В этом случае используйте конструкцию VAR..END, т.е вот так:

var
1@: Int
//сообщаем компилятору, что переменная 1@ будет содержать целые числа(integer)
$Var2: Float
//а переменная $Var2 будет содержать дробные числа(floating-point)
end

$Var2 = 45.5
if
$Var = 1@
jf @Label2

Кроме того, существуют такие удобные функции, вроде Inc (аналог $Var = $Var + 1), Random (генерирует случайные числа, заменяет сразу два опкода), и другие, о них подробнее написано в ридми.

г) Комментарии. В SB можно закомментировать строку символом двойного слеша //,
например:

01F0: set_max_wanted_level_to 6
// все что здесь и до конца строки игнорируется компилятором

а также блоками { }, которыми можно закомментировать сразу несколько строк или часть строки.

01F0: set_max_wanted_level_to {эта часть игнорируется} 6

д) Можно не заморачиваться и не писать вообще список DEFINE OBJECTS, поскольку компилятор подсчитывает используемые объекты самостоятельно.

Возможности самого редактора (IDE) можно посмотреть здесь.

Серьезно поэкспериментировав с Sanny, вы поймете, что работать с его многочисленными фишками реально проще, поскольку они избавляют вас от множества рутинной работы.


Quick Start. Часть 2
Рассмотрим подробнее дополнительные нововведения в язык скриптов.

В предыдущей статье мы говорили о том, что все математические и арифметические выражения можно писать без опкодов. Это значительно удобнее и быстрее. Однако в компилятор Sanny встроены команды, позволяющие сократить даже простые выражения.

1. Команда Inc. Эта команда представляет собой альтернативу обычному сложению. Она увеличивает значение первого параметра на число, переданное вторым параметром. Первым может стоять переменная (типа Integer или Float) или свойство класса

$Var += 10
Inc($Var, 10)

К переменной $Var в обоих вариантах будет прибавлено 10.
Напомню, что если второе число целое (Integer), а переменная типа Float, то компилятор автоматически преобразует число в дробное.
Данную команду удобно использовать, если вам нужно лишь прибавить единицу к переменной, поскольку второй параметр по умолчанию равен 1

$Var += 1
Inc($Var)

Оба варианта равнозначны.
В качестве первого параметра может стоять свойство класса. Подробнее о них будет рассказано в отдельной статье, сейчас я лишь приведу пример:

0109: player $PLAYER_CHAR money += 1
Player.Money($PLAYER_CHAR) += 1
Inc(Player.Money($PLAYER_CHAR))

Все три варианта имеют одинаковое значение: количество денег игрока будет увеличено на единицу.
2. Команда Dec. Это замена операции вычитания:

$Var -= 3
Dec($Var, 3)

На нее распространяются все написанное выше, за исключением примера со свойством. Дело в том, что свойство Money у игрока может только увеличиваться (опкод 0109). Опкода для вычитания денег нет. Поэтому выражение типа Player.Money($PLAYER_CHAR) -= 1 работать не будет. Данное ограничение будет преодолено в следующих версиях SB.

3. Команда Mul. Операция умножения. Все тоже самое, за исключением того, что по умолчанию второй параметр равен 2:

$Var *= 2
Mul($Var)

4. Заключительная арифметическая операция - деление. Для нее есть команда Div, которая без второго параметра делит переменную надвое:

$Var /= 2
Div($Var)

Во всех четырех случаях вторым параметром может стоять переменная. Однако тогда типы обоих переменных должны быть определены в блоке var..end.

5. Процедура SQR вычисляет квадрат переменной. Т.е. она является заменой операции умножения переменной саму на себя:

$Var *= $Var
Sqr($Var)

Тип переменной, как вы надеюсь поняли, должен быть известен компилятору.

6. Функция Random возвращает случайное число в интервале между числами, переданными в качестве параметров. Она представляет собой замену сразу двух опкодов:

0208: $Var = random_float 10.0 100.0
0209: $Var = random_int 10 100

Оба варианта могут быть представлены в виде

$Var = Random(10, 100)

Как видите, компилятор сам выбирает опкод в зависимости от типа переменной, в которую записывается результат функции ($Var). Если ее тип неизвестен, либо это не Integer или Float, компилятор сообщит об ошибке.
В качестве параметров, конечно же, могут быть и переменные. Однако их тип не проверяется.
Следующая команда будет, возможно, трудна для восприятия. Для этого необходимо представлять как в main.scm хранятся переменные и что такое DMA. Это выходит за рамки данной статьи, хотя возможно будет впоследствии описано. Итак, команда Alloc. Она устанавливает адрес памяти для переменной с символьным именем:

Alloc($PLAYER_CHAR, 10)

Переменная$PLAYER_CHAR после этого будет компилироваться как $10.
При помощи команды Alloc вы можете выстроить группу переменных в ряд, превратив их таким образом в элементы массива:

Alloc($Array, 40)
Alloc($Value2, 41)
Alloc($Value3, 42)
Alloc($Value4, 43)

Эти переменные представляют теперь собой массив. Теперь вы можете использовать такой код:

Alloc($Array, 40)
Alloc($Value2, 41)
Alloc($Value3, 42)
Alloc($Value4, 43)
var
$Array: array 4 of Integer
$Result: Int
end

$Value3 = 100 // в третий элемент массива записываем 100

$Index = 2
//смещение от начала массива -> $Value3, не забывайте, что счет идет от нуля

$Result = $Array[$Index]
// будет прочитана третья ячейка, начиная с первого элемента

Player.Money($PLAYER_CHAR) += $Result // + 100

Конечно, здесь можно в качестве альтернативы использовать "чистый" DMA, т.е. цифровые имена переменных ($40, $41, $42 и т.д.), но с символьными именами работать приятнее.
Заключительная на сегодня возможность - это замена номеров миссий. Любая миссия запускается командой start_mission . Этот номер определяется в блоке DEFINE MISSION:

DEFINE MISSIONS 135
DEFINE MISSION 0 AT @INITIAL
DEFINE MISSION 1 AT @INITIL2
DEFINE MISSION 2 AT @INTRO

Однако запоминать эти номера не всегда удобно. Поэтому в SB была добавлена возможность заменить номер миссии на ее имя. Имя в данном случае - это имя метки, написанной в этом же блоке. Таким образом, для запуска 2-й миссии достаточно написать

start_mission intro

Для пущего удобства в SB было встроено еще две возможности:
1) замена всех номеров на имена при декомпиляции.
2) можно вызвать список имен нажатием Ctrl+Space. Курсор должен стоять после команды start_mission.


Типы данных

Перед вами переработанное издание статьи, включающее в себя все последнюю информацию о типах данных в SB.

Новички зачастую не сразу понимают, что означают Integer values, что такое String и т.п. Им и посвящена данная статья. Условно, те типы данных (Data Types), которые используются в SB можно разделить на числа и строки. Базовым видом данных являются числа. Они, как известно, бывают двух видов: целые и дробные. Важное замечание: отличие между ними состоит не столько в значении самого числа, сколько в его записи. Так число 5.0 с точки зрения математики есть число целое. Однако в скриптах оно будет именоваться дробным, или числом с плавающей точкой (floating-point value). Все числа, которые имеют в своем написании точку, являются дробными. Пример:

50.001
-10.750
0.0

Для чисел между -1 и 1 можно не писать 0 в начале. Т.е. 0.0 равнозначно .0

Поскольку способ записи числа имеет значение, то возможны ошибки, когда скриптер забывает написать точку. Компилятор в таком случае расценивает число как целое. Не вдаваясь в отдельные подробности, скажу, что значение этого числа будет немного изменено вследствие этого. В игре после этого могут появиться проблемы. Поэтому следите за этим обстоятельством.
Некоторые опкоды в игре требуют именно применения дробных значений. Это касается скорости движения отдельных объектов, здоровья, брони и т.п. Поэтому старайтесь точно узнать, какой именно тип необходимо использовать.

Sanny Builder в данном случае может помочь вам: внутри классов можно вызвать подсказку, о типах параметров. Подсказка появляется автоматически, когда вы ставите скобку после имени члена класса:

Car.PutAt(

Вы увидете, что 2й, 3й, 4й параметры имеют тип Float. Также подсказку для данного члена класса можно вызвать в любое время нажатием Ctrl+Shift+Space.

Car.PutAt($Car, {нажмите Ctrl+Shift+Space здесь} )

Похожий тип данных - это хендл (handle). Строго говоря это простое число, которое представляет собой указатель на какой-либо объект в памяти игры. Опять-таки, опуская подробности, скажу, что хендл - это "имя" объекта (машины, актера и т.п.). По данному имени вы можете обратиться к объекту и производить над ним определенные действия. Хендлы содержатся в переменных целого типа (Integer values). Их содержимое заполняется после использования специального опкода - конструктора. В SB почти в каждом классе есть такой конструктор.
Имеются ввиду классы опкодов для динамических объектов, которые создаются непосредственно в игре. Например актер (actor), игрок (player), объект (object) и т.д. Нединамические объекты (гаражи) или некоторые отдельные виды объектов, которые не создаются в ходе игры (модели), такого конструктора не имеют. Конструктор имеет одинаковое для всех классов имя - Create. После его срабатывания игра создает в памяти указатель на новый объект и записывает его в переменную:

$ActorHandle = Actor.Create(CivMale, #MALE01, 0.0, 0.0, 0.0)

Теперь хендл актера хранится в переменной $ActorHandle, и вы можете, используя ее, делать с ним все, что угодно. Хендл можно получить не только создавая нового актера (или еще что-нибудь). В игре существуют специальные опкоды, позволяющие "захватить" случайного прохожего и превратить его таким образом в актера. Но это тема для отдельного разговора.
Как уже говорилось, хендл суть есть обычное число. Его значение можно легко узнать, и в принципе с хендлом можно проводить любые арифметические и логические операции. Поэтому все математические опкоды, предназначенные для целых чисел действительны и для хендлов. В комментариях к ним это иногда указано:

0084: $IntVar = $ActorHandle // integer values and handles

Ну и наконец заключительный тип – строка (string). Он использовался во всех GTA, но только в SA получил развитие.
String представляет собой строку, т.е. набор символов. каждый из которых имеет свое численное выражение. Существует специальная таблица кодов (ASCII), в которой содержатся значения всех символов. В скриптах SA используются два вида строк: фиксированной и переменной длины. Последний вид НЕ поддерживается в GTA3 и VC.
Строки фиксированной длины (fixed-length string) могут содержать до 15 символов включительно. Если строка меньше этой длины, остаток заполняется пустотой. Данные строки оформляются в одинарные кавычки:

05AA: s$MyString = 'MY_STR'

Обратите внимание, что для работы со строками используется специальный вид переменных. Они обозначаются буквой s: s$GlobalVar, 1@s.
Данный вид строк может использоваться и как хендл. Обратите внимание на команду

thread 'MAIN'

MAIN в данном случае - это имя потока. Используя его, можно прекратить поток из любого места

end_thread_named 'MAIN'

Или другой пример:

07D3: 'HOUSE' = init_external_script_named_handle 23 (BURG_BRAINS)

'HOUSE' - хендл внешнего скрипта.

Строки, кроме функции хендлов, используются как идентификаторы отдельных полей в .GXT-файле.
Например:

00BA: text_styled 'STAD_01' 1000 ms 2

Другой вид строк - строки переменной длины (variable-length string). Они обозначаются двойными кавычками и могут содержать в себе большее по сравнению с предыдущим видом число символов. Точное число определяется самим опкодом.
Данный вид может использоваться для тех же целей, что и предыдущий. Чаще всего в оригинальных скриптах он используется для указания имен анимаций

04ED: load_animation "LOWRIDER"

Переменные, содержащие такие строки, обозначаются символом v: v$GlobalVar, 1@v.

Ограничений по использованию разных видов строк нет. Это значит, что вы можете использовать в опкоде либо первый, либо второй вид, на ваше усмотрение. Однако учитывайте, что лимит на количество символов устанавливается самим опкодом. Например, вы можете использовать код:

03A4: name_thread 'LONGNAME'

Однако данный опкод использует только первые 7 символов строки. Это значит, что поток после этого будет иметь имя LONGNAM, а не LONGNAMЕ, как вам хотелось.

Со строками можно проводить все основные виды операций: присваивание, сравнение, конкатенация (сложение строк).

1. Присваивание

05AA: s$Var = 'IE16' // в переменную записывается строка IE16
06D1: v$Var = "NIL" // в переменную записывается строка NIL

Обратите внимание, справа может быть не только строка, но и стринговая переменная. Например,

05AA: s$Var = s$Var2

2. Сравнение

05AD: s$Var == s$Var2
// проверка срабатывает, если содержимое переменных одинаково
08F9: v$Var == v$Var2
// проверка срабатывает, если содержимое переменных одинаково

Обратите внимание, справа может быть не только стринговая переменная, но и строка.
Например,

08F9: v$Var == "string"

Проверки чувствительны к регистру, но поскольку по умолчанию все строки компилируются в верхнем регистре, данный факт будет иметь значение только при включенной опции регистра букв «Как есть».

Вы также можете проверять пустая ли строка. Для этого есть целых 4 одинаковых опкода:

0844: string s$Var empty
0845: string s$Var empty
0846: string s$Var empty
0847: string s$Var empty

Все эти проверки работают абсолютно одинаково и срабатывают, если строка не содержит символов.

3. Сложение строк

098B: s$result = s$var1 + s$var2
098C: s$result = s$var1 + s$var2

Оба этих опкода одинаковы. Все параметры должны являться стринговыми переменными. Принцип работы таков: берется строка из переменной var1, складывается со строкой из var2 и результат записывается в переменную result.

Перечисленные выше типы данных присущи и элементам массивов. Т.е. массивы могут быть типа Integer, Float, String. Подробнее о массивах см. здесь

22.02.2007


Основы скриптинга

В этом учебнике я (Alexander) расскажу вам о всём, что я знаю про скриптинг в GTA San Andreas.
Итак поехали !!!

В тексте вы можете встретить слова в двойных кавычках, кавычки существуют только для удобства чтения, писать их в контексте билдера не надо !!!
Для скриптинга в SA применяется программа Sanny Builer, дальше просто SB, есть ещё и BW's builder, но про него я ещё не написал учебник. Всё, что Вы прочтёте относится к SB версии не меньше, чем 2.97. Если вы его ещё не закачали, то берите на http://www.sannybuilder.com.
Запустите SB, в меню выберите категорию "Tools", в ней найдите графу "Options", кликните на неё. Появится окно, найдите там опцию "GTA SA directory" и укажите там путь к вашему установленному SA, когда выбрали, то нажмите "OK". Нажмите "F5" и выберите, где находится главный файл скрипта - main.scm. Он лежит в: "Директория GTA SA/data/sript", следом нажмите "Open".
Вот он и раскомпилировался, и вы увидели кучу цифр и слов. Весь скрипт состоит из команд. Вся команда записывается в одну строку. Раньше каждая команда состояла из опкода и параметров.
Например:

009A: $act = create_actor 4 #WMYCR at $x $y $z

009A - это опкод, он показывает, какое действие должно выполнятся
$act - это актёр (или просто чувак),
4 - это тип актёра, типы описал в главе "Актёры",
#WMYCR - это модель актёра,
$x $y $z - это координаты актёра на карте, они должны всегда быть с точкой, т.е. должны быть округлены как минимум до десятых.
009A: $act = 4 #WMYCR $x $y $z - я мог бы написать и так, т.к. только параметры играют роль в команде с опкодом, а в команде без опкода (о них позже) такого делать нельзя.
Весь раскомпилированный main.scm состоит из thread'ов, и миссий, которые в свою очередь, тоже явл. thread'ами. Написание миссий - самое сложное в скриптинге. Thread'ы ещё называют потоками. Все переменные (имена актёров, машин, координаты...) должны начинаться со знака $ (можно использовать во всём тексте Main'a), или они должны оканчиваться знаком @ (можно использовать только в том потоке, где объявили), по поводу типов данных всё написано в главе " типы данных ".
Сейчас (08.2006) в Sanny преимущественно используется новый тип опкодов без команд. Вот тот - же самый опкод, что я описал раньше, но теперь под теперешний SB:

actor.Create($act,4,#WMYCR,$x,$y,$z)

Видите, практически тоже самое, только намного удобнее, вам надо написать только кодовое слово, типа actor, car или object ... , затем поставить точку, и вы увидите небольшое меню, с действиями
которые можно делать с этим типом предмета.
Потоки состоят из label'ов. Label - это как-бы самостоятельная часть потока, label можно определить по такому контексту : он стоит один в строке и начинается всегда с двоеточия, название любого потока определяется по названию его первого label'a.
Чтобы создать поток надо найти строку с текстом create_thread,затем после неё в следующей строке вставить create_thread @"Название вашего потока", кавычек не надо. Следом надо найти строку с текстом -Mission 0- и перед ней написать :
1) Название того скрипта, который вы объявили командой create_thread @.
2) обязательно написать команду wait 0 ,вместо нуля можно написать любое время (в миллисекундах), после которого пойдёт выполнение вашего потока.
3) Каждый поток должен заканчиваться строкой с текстом end_thread .
Например:
Я нашёл строки, частью которых есть выражение create_thread @, после них вставил строку

create_thread @Test

Затем нашёл строку -Mission 0-
Выше неё написал

:Test
wait 0

//---------- Тут надо писать то,что делает поток -------------

end_thread

Чтобы использовать актёров, машины, объекты в своём потоке, надо сначала загрузить их модели.
Это делается с помощью нескольких команд:
1) model.load(#WMYCR) , где #WMYCR - модель актёра, которая нужна.
2) 038B: load_requested_models, эта команда загружает ранее объявленные модели (у нас это модель #WMYCR).
Можно написать сколько угодно model.load(#нужная модель), но после того, как вы объявили нужные модели всегда надо писать команду 038B: load_requested_models, иначе игра вылетит.
Всегда надо писать проверку на загрузку модели, а то если модель ещё не загрузилась, а вы уже с ней что-то делаете, то игра вылетит. Вот пример стандартного содержания потока (начало, загрузка моделей, проверка на загруженность, конец):
Как всегда создаём поток (как это делать писалось раньше), а теперь:

Copy to Clipboard
:Test //название потока или его 1-го label'a
wait 0 //ждём 0 миллисек.(1 сек.=1000 мсек.)
model.load(#нужная модель № 1)
model.load(#нужная модель № 2)
model.load(#нужная модель № n) //записываем нужные для потока модели
038B: load_requested_models //загружаем нужные для потока модели

:Test_2   // Это новый label
wait 0 //ждём 0 миллисек.
if and //if and-команда начала условия, все подусловия которого выполняются.
model.Available(#нужная модель № 1) // Подусловие
model.Available(#нужная модель № 2) // Подусловие
model.Available(#нужная модель № n) // Подусловие
jf @Test_2 // jf означ.,что если эти подусл. не выполнились, то
// выполнение потока переходит к началу проверки

//-- Тут надо писать то, что делает поток --

Model.Destroy(#нужная модель № 1) // в конце каждого потока надо
Model.Destroy(#нужная модель № 2) // выгружать модели из памяти, а то они
Model.Destroy(#нужная модель № n) //там остаются и загрязняют её
end_thread // Конец потока

По поводу условий всё написано в главе "Условия".
Чтобы применить всё, что вы написали надо нажать "F7" (компиляция), затем запустить SA, нажав "F8", каждый раз после новой компиляции надо начинать новую игру, если будете грузить свои сохранения, то игра в конце загрузки просто выдаст ошибку и вылетит.
Чтобы определить координаты в игре используется Coords Manager, это часть SB. Если SA запущен, то по нажатию "F4", когда окно SB явл. активным, появится дополнительное окошко в окне SB, в котором будут написаны координаты игрока, с помощью Coords Manager'a можно устанавливать координаты игрока, просто введите нужные и нажмите "Set", и игрок переместится в заданную точку.


Условия

Сейчас я расскажу вам об операторах перехода. Переходы бывают условные и безусловные. Безусловные переходы бывают двух типов - с возвратом и без возврата. Для перехода с возвратом используется команда gosub @"Туда надо перейти", а для безвозвратного перехода существует jump @"Туда надо перейти". Отличие возвратного перехода от безвозвратного в том, что при возвратном переходе скрипт, дойдя до строчки gosub @"Туда надо перейти" будет выполнять всё после объявления лэйбла "Туда надо перейти" до тех пор, пока скрипт не встретит команду return, после чего выполнение перейдет к строчке после gosub @"Туда надо перейти", а при безвозвратном переходе после строчки jump @"Туда надо перейти" действие перейдет к лэйблу "Туда надо перейти" и все команды после jump будут проигнорированы. Условные переход всегда безвозвратные. О переходах смотреть также здесь.
Условный переход всегда происходит после выполнения какого-либо условия. Все условия состоят из трёх частей:
1 - объявление самого условия
2 - написание подусловий
3 - что делать после (не) выполнения или просто-напросто переход.
Любое условие начинается со строки с текстом "if", если вы хотите, чтобы все подусловия (ещё их называют проверки) вашего условия выполнялись, то после "if" надо ставить "and" (между ними пробел), а если хотите, чтобы была проверка на выполнение хотя бы одного подусловия, то вместо "and" ставьте "or".

Например:

1) Проверка с выполнением всех подусловий:

Copy to Clipboard
create_thread @Test1

:Test1
wait 0
if and
  0102: actor $PLAYER_ACTOR stopped_near_point_on_foot $X $Y $Z radius $X_R $Y_R $Z_R sphere 0
  8184: not actor $PLAYER_ACTOR health >= 99
jf @Test1
actor.health($PLAYER_ACTOR) = 100
end_thread

Принцип таков:
Если игрок(CJ) остановился по заданным координатам $X $Y $Z, точнее в радиусе $X_R $Y_R $Z_R от этих координат, и если его жизни меньше 100, то его жизнь опять станет равной 100. Параметр 0 в конце первого подусловия указывает, что игрок останавливается не в сфере(красный маркер). Если параметр был бы равен 1, то надо было бы создать сначала сферу, но о сферах потом. Опкод"jf @Test1" делает переход на "Test1", если оба наших условия не выполнились.

2) Проверка с выполнением хотя-бы одного подусловия:

Copy to Clipboard
create_thread @Test2

:Test2
wait 0
if or
  0102: actor $PLAYER_ACTOR stopped_near_point_on_foot $X $Y $Z radius $X_R $Y_R $Z_R sphere 0
  8184: not actor $PLAYER_ACTOR health >= 99
jf @Test2
actor.health($PLAYER_ACTOR) = 100
end_thread

Тут описано, что если игрок остановился в заданном радиусе от точки с координатами $X $Y $Z или если жизнь игрока стала меньше 100, то жизнь станет равна 100. Тут при выполнении хотя бы одного подусловия, будет выполнятся наше действие, т.е жизнь CJ'я станет 100.
Жизнь - целое число, а вот координаты и радиусы - дробные. Если даже вам надо использовать радиус равный 10, то надо написать 10.0.
Чтобы поток не был одноразового использования надо в конце вместо "end_thread" поставить "jump на начало", в данном случае - это Jump @Test2.
Вот вам пример первого(Test1) скрипта, но уже с координатами, радиусами... :

Copy to Clipboard
create_thread @Example1

:Example1
wait 0
if and
  0102: actor $PLAYER_ACTOR near_pt 2505.4812 -1687.4213 13.5543 radius 10.0 10.0 10.0 sphere 0
  8184: not actor $PLAYER_ACTOR health >= 99
jf @Example1
actor.health($PLAYER_ACTOR) = 100
jump @Example1

Если жизнь игрока меньше 100, и он стоит около гаража CJ'я, то его жизнь становится равной 100. Заметьте, что этот скрипт зациклен, он работает всегда, потому что есть переход в его конце на его начало.
С самого начала вставляйте "create_thread @Example1" после другого "create_thread", второй можно найти с помощью поиска. Потом ищем "----Mission 0----" и перед ней вставляем всё, что идёт в нашем скрипте начиная с ":Example1" заканчивая "jump @Example1" включительно. Жмём "F7", и ждём, пока пройдёт компиляция. Когда закомпилировалось жмите "F8" - запуск SA и начинайте новую игру.

Внимание! В проверках существует только знак ">", знака "<" не существует, вместо него можно перед всем опкодом написать слово "not", это будет равносильно знаку "<", это применимо к командам без кодовых слов. В проверках-утверждених (в которых нет слова "not") опкод (кодовое слово) нач- ся с "0", а во всех проверках-отрецаниях используется тот же самый опкод, но уже вместо "0" там ставится цифра "8". Поэтому если у вас есть утверждение, то вы можете, поменять первую цифру, т.е. "0" на "8" и после знака ":" поставить "not", и это уже будет проверка-отрецание и наоборот.
Например:
Вот у меня есть проверка "игрок плавает в воде", она имеет следующий вид:

Copy to Clipboard
:Label1
wait 0 ms
if // если у нас только одно подусловие или проверка,
// то не "or" не "and" писать не надо.
0965: actor $PLAYER_ACTOR swimming_in_water
jf @Label1 // если подусловие не выполнилось, то переходим на начало.

Допустим у меня в скрипте должны выполнятся действия, когда игрок не в воде, а у меня в проверке написано, что действие скрипта дальше не пойдёт, если игрок не будет в воде, следовательно надо сделать проверку "игрок не плавает". Заменяем первоначальную проверку проверкой, противоположной по значению. И вот, что получилось:
8965: not actor $PLAYER_ACTOR swimming_in_water
Что я сделал, я заменил первую цифру опкода,т.е. "0" на "8" и после двоеточия поставил слово "not".
А если у вас есть проверка-отрецание и вам надо сделать проверку-утверждение, то ищите первую цифру опкода (она должна быть - 8), затем меняйте её на 0, убирайте слово "not" и получите свою проверку-утверждение.
Это можно делать со всеми проверками, в которых есть кодовые слова.
Максимальное число проверок - 7 штук, если надо больше, то разбейте их на несколько частей,
например:
У нас есть 10 моделей, которые мы должны проверить на загруженность, но макс. кол-во проверок всего лишь 7, поэтому разбиваем проверки на две части, в первой будет 7, а во второй 3, и вот, что получается:

Copy to Clipboard
:Test
wait 0
if and
  model.Available(#1)
  model.Available(#2)
  model.Available(#3)
  model.Available(#4)
  model.Available(#5)
  model.Available(#6)
  model.Available(#7)
jf @Test
if and
  model.Available(#8)
  model.Available(#9)
  model.Available(#10)
jf @Test

Вот такая проверочка вышла. Если что-то не понятно, то заходите на http://gtamaps.net/forum .
Cам игрок тоже явл. актёром, только когда мы работаем с опкодами (командами) в которых есть слово "player" надо использовать "$PLAYER_CHAR", а когда работаем с актёрами, то "$PLAYER_ACTOR".


Условные опкоды

1) Рассмотрим проверки, которые можно применять к актёрам и игроку, т.е. к CJ'ю:

Игрок ($PLAYER_CAHR):

Player.Defined($PLAYER_CAHR) - игрок найден или уже создан.
player.PressingHorn($PLAYER_CAHR) - игрок бибикает, сидя в машине.
wasted_or_busted - игрок арестован или убит.
Player.Controllable($PLAYER_CHAR) - игрок контролируем.
0457: player $PLAYER_CHAR aiming_at_actor $Act - игрок целится в актёра c именем $Act.
Player.WantedLevel($PLAYER_CHAR) > 0 - проверяет уровень розыска у игрока.
Player.Money($PLAYER_CHAR) > $money - cравнивает ваши деньги с целым числом $money.

Игрок ($PLAYER_ACTOR) и актёры:

Actor.Animation($PLAYER_ACTOR) == "FIGHTC_SPAR" - является ли анимация актёра данной.
0965: actor $PLAYER_ACTOR swimming_in_water - актёр плавает в воде.
06EE: actor $PLAYER_ACTOR in_group 260@ - актёр в определённой группе актёров.
actor.InCar($PLAYER_ACTOR,$Car) - $PLAYER_ACTOR в машине $Car.
actor.Driving($PLAYER_ACTOR) - актёр $PLAYER_ACTOR за рулём.
actor.DrivingPoliceVehicle($PLAYER_ACTOR) - актёр $PLAYER_ACTOR за рулём ментовской тачки.
actor.DrivingTaxiVehicle($PLAYER_ACTOR) - актёр $PLAYER_ACTOR за рулём такси.
04A7: actor $PLAYER_ACTOR driving_boat - актёр $PLAYER_ACTOR плывёт на лодке.
actor.DrivingVehicleType($ACTOR,#CAR_MODEl) -актёр $ACTOR в маш. типа #CAR_MODEl.
actor.Dead($PLAYER_ACTOR) - актёр $PLAYER_ACTOR умер.
actor.HasWeapon($ACTOR,Number) - актёр $ACTOR имеет оружие с номером Number, номера можно посмотреть в главе "ПикАпы (PickUps)".
actor.Stopped($PLAYER_ACTOR) - актёр $PLAYER_ACTOR остановился.
actor.Dead($PLAYER_ACTOR) - актёр $PLAYER_ACTOR умер.
04AD: actor $PLAYER_ACTOR touching_water - актёр $PLAYER_ACTOR касается воды.
04C5: actor $PLAYER_ACTOR photographed - актёр фотографирует.
051A: actor $Act1 damaged_by_actor $Act2 - получил ли актёр1 к-л повреждения от актёра2
031D: actor $Act hit_by_weapon 23 - получил ли актёр к-л повреждения от опред. оружия

2) Проверки (условия) для объектов:

03CA: object $Obj exists - объект $Obj существует.
83CA: not object $Obj exists - объект $Obj не существует.
0685: object $Obj attached - объект прицеплен к ч-л.
8685: not object $Obj attached - объект не прицеплен к ч-л.
023B: actor $Act colliding_with_object $Obj - актёр соприкасается с объектом.
823B: not actor $Act colliding_with_object $Obj - актёр не соприкасается с объектом.
0179: actor $Act picked_up_object $Obj - актёр поднял объект (относится к пикапам).
8179: not actor $Act picked_up_object $Obj - актёр не поднял объект (относится к пикапам).
0737: actor $Act lifting_object $Obj - актёр поднимает объект.
8737: not actor $Act lifting_object $Obj - актёр не поднимает объект.
0366: object $Obj blown_up - объект $Obj взорвался.
8366: not object $Obj blown_up - объект $Obj не взорвался.
04E7: object $Obj in water - объект $Obj в воде.
84E7: not object $Obj in water - объект $Obj не в воде.
0471: unknown_actor $Act near_object $Obj radius 50.0 50.0 unknown 0 -
актёр находится в определённом радиусе от объекта.
8471: not unknown_actor $Act near_object $Obj radius 50.0 50.0 unknown 0 -
актёр не находится в определённом радиусе от объекта.

3) Вот проверки, применяющиеся к транспортным средствам :

0185: car $Car health >= 10 - жизни машины $Car больше либо равняется 10
07AB: car $Car_1 attached_to_car $Car_2 - машина 1 прицеплена к машине 2.
0495: car $Car burning - машина горит.
0975: car $Car emergency_vehicle - машина $Car является служебной (пожарная, полиция...)
096F: car $Car street_racing_vehicle - машина $Car является машиной для уличных гонок
02CA: car $Car bounding_sphere_visible - игрок видит авто $Car
02BF: car $Car sunk - машина с именем $Car упало в воду
0981: train $Poezd wrecked - поезд с именем $Poezd уничтожен
01C1: car $Car stopped - машина с именем $Car остановилась
03C9: car $Car damaged - машина с именем $Car повреждена
096E: car $Car lowrider - машина с именем $Car лоурайдер
01C1: car $Car stopped - машина с именем $Car стоит на месте
Car.Id($car) == #HYDRA - модель машины с именем $Car-это #HYDRA
//тут перед всем опкодом можно поставить "not", потому что тут нет кодового слова.
01F3: car $Car airborne - машина с именем $Car находится в воздухе
//я думаю, что вы поняли, что и в эту команду можно вставить "not".
03CE: car $Car stuck - машина с именем $Car перевёрнута
0119: car $Car wrecked - машина с именем $Car уничтожена
01B0: car $Car stopped 0 near_point X Y Z radius 4.0 4.0 4.0 машина с именем $Car остановилась в радиусе 4.0 от точку с координатами X Y Z
01F4: car $Car flipped - машина с именем $Car тонет
056E: $Car - машина $Car существует
0431: car $Car car_passenger_seat_free 0 - место 0 в машине $Car свободно
051D: cars $Car_1 and $Car_2 collided - машина $Car_1 и $Car_2 столкнулись.
0803: car $Car have_hydraulics - у машины $Car есть гидравлика

4)Разные проверки:

model.Available(#MODEl) - модель загружена.
not model.Available(#MODEl) - модель не загружена.
04EE: animation "GANGS" loaded - анимация загружена.
84EE: not animation "GANGS" loaded - анимация не загружена.
00E1: key_pressed 0 19 - нажата клавиша. Про клавиши написано в главе "Клавиши".
80E1: not key_pressed 0 19 - не нажата клавиша.
$ONMISSION == X - миссия не запущена, если X = 0, и миссия запущена, если X = 1.
02D0: fire $Fire extinguished - проверка на потушенность определённого огня.
82D0: not fire $Fire extinguished - проверка на горение определённого огня.
03D0: wav 3@ loaded - звук загружен.
83D0: not wav 3@ loaded - звук не загружен.
03D2: wav 3@ ended - звук закончился.
83D2: not wav 3@ ended - звук не закончился.


Переходы

Существует три варианта переходов:

1. условные - 004d: jump_if_false @label
2. безусловный - jump @label
3. переход с возвратом (вызов процедуры) - gosub @Label

Условные переходы применяются в проверках, например:

if
< -- условие -->
004d: jump_if_false @label
<-- код -->

:label

Принцип работы таков: если условие данной проверки не выполнено, то переходим на метку :label.
Код (<-- код -->), который находится ниже 004d: jump_if_false @label, не выполняется.

Безусловный переход - jump @label, в отличии от условного перехода он выполняется в любом случае.

<-- код -->
jump @label
<-- код1 --> // эта строка игнорируется

такая запись бессмысленна, поскольку <-- код1 --> никогда не будет выполнен.

К примеру, есть необходимость при выполнении условия игнорировать <--код провала-->:

if
< -- условие -->
004d: jump_if_false @label
<-- код -->
jump @label_1

:label
<-- код провала-->
jump @label_3 //выход

:label_1

В случае выполнения условия переходим на метку :label_1, то есть <-- код провала--> (метка :label) не выполняется.

Переход с возвратом (вызов процедуры) - gosub @Label.

gosub – это переход с возвратом на следующую после gosub @Метка строку.
gosub всегда работает в паре с return.

:Lable
gosub @Label_1 // переход на метку Label_1
< -- код -->
// этот код будет выполнен только после того,
// как отработает пара gosub @Label_1 - return
jump @Label_2 // Безусловный переход на метку :Label_2

:Label_1
< -- код 1-->
return //– возврат на следующую после gosub @Label_1 строку

:Label_2

В San Andreas поддерживается до 8 вложенных gosub.

Принцип работы:
:Lable
gosub @Label_1 // (1) – переход на метку Label_1
< -- код --> // последним будет выполнен этот код
jump @Label_4

:Label_1
gosub @Label_2 // (2) – переход на метку Label_2
< -- код -->
return // (1) – возврат на следующую после gosub (1) строку

:Label_2
gosub @Label_3 // (3) – переход на метку Label_3
< -- код -->
return // (2) - возврат на следующую после gosub (2) строку

:Label_3
< -- код -->
return // (3) - возврат на следующую после gosub (3) строку

В примере показана работа трех вложенных gosub. Команда return будет отрабатывать в обратном порятке, то есть сначала отработает пара gosub @Label_3 - return // (3), затем пара gosub @Label_2 - return // (2) и только после этого отработает пара gosub @Label_1 - return // (1)

Говоря проще каждому gosub соответствует свой return.


Пикапы

Тут описано, как сделать пикап, т.е то, что можно подобрать. Можно создавать пикап в главном потоке игры, но это временами не выходит, поэтому я расскажу о создании пикапа в своём собственном потоке.
Все пикапы делятся на пикапы оружия ближнего боя, оружия дальнего боя, просто пикапы (броня, жизнь...) и специальные.
1) Рассмотрим пикапы оружия дальнего боя:
Чтобы создать пикап такого типа надо использовать вот этот опкод:
032B: $Weap = create_weapon_pickup #MODEL type (число) ammo (число) at $X $Y $Z
Теперь рассмотрим этот опкод по параметрам:
032B: - это кодовое слово, явл. основой всей этой команды.
$Weap - имя нашего пикапа, может быть любым, но всегда в начале должно стоять $ или @ в конце.
#MODEL - модель оружия дальнего боя, есть следующие модели данного типа:

модель | описание | Номер (для того, чтобы дать актёру оружее)
#grenade | обыкновенная граната | 16
#teargas | газовая граната | 17
#molotov | граната "Коктейль Молотова" | 18
#satchel | граната на пульте управления | 39
#colt45 | пистолет Кольт45,как у ментов | 22
#silenced | пистолет с глушителем | 23
#desert_eagle | пистолет "пустынный орёл" | 24
#chromegun | однозарядный дробовик | 25
#shotgspa | мощьный дробовик с 7-ми патронами | 27
#sawnoff | двустволка | 26
#micro_uzi | узи | 28
#tec9 | что-то типа узи, только послабее | 32
#mp5lng | автомат MP5,в C.S. 1.6 это "B 3.2" | 29
#ak47 | автомат Калашникова | 30
#m4 | авт. винтовка M4,типа M16 | 31
#cuntgun | винтовка | 33
#sniper | винтовка со снайперским прицелом | 34
#rocketla | базука | 35
#heatseek | базука с самонаводкой | 36
#flame | огнемёт | 37
#minigun | миниган или просто шестистволка | 38
#spraycan | балончик с краской | 41
#fire_ex | огнетушитель | 42
#camera | фотоаппарат | 43
#nvgoggles | ночное видение | 44
#irgoggles | тепловое видение | 45

Type - это тип пикапа, есть следующие типы:
1 - за деньги, регенерируется почти сразу
2 - бесплатно, регенерация за 30 минут игрового времени, надо отойти недалеко
3 - бесплатно, одноразовый
9,11 - бомба
15 - эти регенерируется за 6 часов игрового времени или за 6 минут по-нормальному Ammo - это число патронов, которые будут с оружеем в придачу.
$X - координата по оси X.
$Y - координата по оси Y.
$Z - координата по оси Z.

2) Рассмотрим пикапы оружия ближнего боя:
Чтобы создать пикап такого типа надо использовать вот этот опкод:
$Weap = Pickup.Create(#MODEl, Type, $X, $Y, $Z)
$Weap - имя нашего пикапа,может быть любым, но всегда в начале должно стоять $ или @ в конце.
#MODEL - модель оружия дальнего боя, есть следующие модели данного типа:

модель | описание | номер (для того, чтобы дать актёру оружее)
#brassknuckle | кастет | 1
#golfclub | клюшка для гольфа | 2
#nitestick | ментовская дубинка | 3
#knifecur | нож | 4
#bat | бейсбольная бита | 5
#shovel | лопата | 6
#poolcue | бильярдный кий | 7
#katana | катана | 8
#chnsaw | бензопила | 9
#gun_dildo1 | большой синий фалоиммитатор | 10
#gun_dildo2 | маленький светло-зелёный фалоиммитатор | 11
#gun_vibe1 | большой серый фалоиммитатор | 12
#gun_vibe2 | маленький деревянный фалоиммитатор | 13
#flowera | букет цветов | 14
#gun_cane | трость | 15

Type - это тип пикапа,остальные типы описаны выше.
$X - координата по оси X.
$Y - координата по оси Y.
$Z - координата по оси Z.

3) Рассмотрим обыкновенные пикапы:
Чтобы создать пикап такого типа надо использовать тот же самый опкод, но я отделил тип простые пикапы, чтобы было удобнее.
$Weap = Pickup.Create(#MODEl, Type, $X, $Y, $Z)
$Weap - имя нашего пикапа, может быть любым,но всегда в начале должно стоять $ или @ в конце.
#MODEL - модель пикапа,есть следующие модели простых пикапов:
#HEALTH - жизни
#BODYARMOUR - броня
#GUN_PARA - парашут 46
#JETPACK - джетпак,а по-русски - леталка
#INFO - просто пикап,нет никаких свойств
#PICKUPSAVE - значок сохранения, просто значок не обладающий никакими свойствами
#CLOTHESP - значок одежды,просто значок
#KEYCARD - карточка
Есть наверняка и др. простые пикапы,но они практически нигде не встречаются,поэтому я написал, только те, которые встречаются чаще всех.

4) Специальные пикапы:
Если я не ошибаюсь,то специальных пикапов всего два:
1 - пикап получения денег :
04A6: $Money = create_asset_money_pickup_at $X $Y $Z money $MaxMoney $MaxMoney , где $Money - имя пикапа
$X $Y $Z - координаты пикапа,как их определить написано в первой главе
$MaxMoney - эти два одинаковых параметра указывают на максимальное кол-во денег, которое будет давать пикап.
2 - пикап покупки, можно применять к чему угодно:
0518: $Buy = create_available_asset_pickup 'PROP_3' at $X $Y $Z price $Count
$Buy - имя пикапа
$X $Y $Z - координаты пикапа, как их определить написано в первой главе
$Count - деньги, которые мы платим за покупку,а вот что покупать, это уже надо самим писать.

Чтобы создать стрелку над любым пикапом используем вот этот опкод:
03DC: $mark = create_marker_above_pickup $PickUp
$Mark - имя маркера,
$PickUp - имя пикапа.

Примеры:
1. Давайте создадим несколько пикапов оружия около дома CJ'я :

Copy to Clipboard
create_thread @PickUps // создаём поток

:PickUps
wait 0
model.load(#teargas)  // командой "model.load" описываем нужные для загрузки модели
model.load(#molotov)
model.load(#desert_eagle)
model.load(#sawnoff)
model.load(#micro_uzi)
model.load(#ak47)
model.load(#m4)
model.load(#sniper)
model.load(#heatseek)
model.load(#flame)
model.load(#minigun)
model.load(#nvgoggles)
038B: load_requested_models // загружаем модели,которые были описаны командой "model.load"

:PickUps_2
wait 0 // весь label PickUps_2 представляет собой проверку на загрузку
if and
model.Available(#teargas)
model.Available(#molotov)
model.Available(#desert_eagle)
model.Available(#sawnoff)
model.Available(#micro_uzi)
model.Available(#ak47)
model.Available(#m4)
jf @PickUps_2
if and
model.Available(#sniper)
model.Available(#heatseek)
model.Available(#flame)
model.Available(#minigun)
model.Available(#nvgoggles)
jf @PickUps_2

:PickUps_3 // В label'е PickUps_3 сначало создаются пикапы .
032B: $Weap[0] = create_weapon_pickup #teargas type 15 ammo 999999 at 2504.5488 -1680.08 13.384
032B: $Weap[1] = create_weapon_pickup #molotov type 15 ammo 999999 at 2504.5488 -1678.08 13.384
032B: $Weap[2] = create_weapon_pickup #desert_eagle type 15 ammo 999999 at 2504.55 -1676.1 13.4
032B: $Weap[3] = create_weapon_pickup #sawnoff type 15 ammo 999999 at 2504.5488 -1674.08 13.384
032B: $Weap[4] = create_weapon_pickup #micro_uzi type 15 ammo 999999 at 2504.5488 -1672.08 13.384
032B: $Weap[5] = create_weapon_pickup #ak47 type 15 ammo 999999 at 2504.5488 -1670.08 13.384
032B: $Weap[6] = create_weapon_pickup #m4 type 15 ammo 999999 at 2504.5488 -1668.08 13.384
032B: $Weap[7] = create_weapon_pickup #sniper type 15 ammo 999999 at 2504.5488 -1666.08 13.384
032B: $Weap[8] = create_weapon_pickup #heatseek type 15 ammo 999999 at 2504.5488 -1664.08 13.384
032B: $Weap[9] = create_weapon_pickup #minigun type 15 ammo 999999 at 2504.5488 -1662.08 13.384
032B: $Weap[10] = create_weapon_pickup #nvgoggles type 15 ammo 1 at 2504.5488 -1660.08 13.384
032B: $Weap[11] = create_weapon_pickup #flame type 15 ammo 999999 at 2504.5488 -1658.08 13.384
wait 100 // делаем небольшую задержку,на всякий случай.
Model.Destroy(#teargas)
//командой Model.Destroy(#MODEl) удаляем модель из памяти.
Model.Destroy(#molotov)
//  Если мы не будем писать эту команду,то модели останутся в памяти,
Model.Destroy(#desert_eagle)
// может,если у вас достаточно мощьный компьютер,вы и не заметите
Model.Destroy(#sawnoff type)
// никаких тормозов.Честно говоря,я сам принадлежу к числу
Model.Destroy(#micro_uzi)
// любителей не проверять модели на загруженность и не выгружать их
Model.Destroy(#ak47)
// в конце потока,но я делаю и то и другое,чтобы уже не было того,к чему
Model.Destroy(#m4)
// могут придраться другие и просто на всякий случай,так что - пишите!
Model.Destroy(#sniper)
Model.Destroy(#heatseek)
Model.Destroy(#minigun)
Model.Destroy(#nvgoggles)
Model.Destroy(#flame)
end_thread

Теперь компилируем, запускаем SA, начинаем новую игру и смотрим. Создавайте свои пикапы, т.е. поэксперементируйте с координатами, моделями оружия, только не забывайте их загружать, проверять на загруженность и выгружать из памяти.
Кстати, игру не обязательно перезапускать,после каждой модификации Main'a,можно просто жать " Новая игра " , но если вы работаете с External (внешними) скриптами, про них есть отдельная глава, то перезапуск необходим, потому что Main.scm загружается и потом удаляется с памяти, а script.img - файл внешних скриптов, висит в памяти до тех пор,пока мы не выйдем из игры, а файл, висящий в памяти перезаписать нельзя никак.

Смотрите пример здесь.


Анимации для актеров

0605: actor -1 perform_animation_sequence "Anim" from_file "File" 4.0 loop 0 0 0 1 -1 ms

Вот этой командой задаётся анимация, где "Anim" - само действие, а "File" - файл анимаций, который надо предварительно загрузить командой 04ED: load_animation "File" и потом проверить на загруженность командой (провекрой) 04EE: animation "LOWRIDER" loaded. После слова actor идёт число -1 -это имя неопределённого актёра, если вы не собираетесь использовать последовательность действий, то вместо -1 надо поставить имя актёра, который будет выполнять анимацию. Если надо, чтобы анимация повторялась, то число, стоящее сразу после слова "loop" должно быть равным 1, а если надо, чтобы анимация не повторялась (обязательное условие последовательности), то ставьте 0.
Если надо, чтобы анимация повторялась определённое кол-во времени, то после "loop" ставете 1 и вместо "-1 ms" ставите своё время.
Если надо, чтобы анимация заканчивалась и актёр возвращался в исходное положение, то число,
стоящее перед -1 ms меняйте на 0, если чтоб оставался в последнем движении анимации, то ставьте 1.
Чтобы актёр выполнял действия последовательно используется такое выражение:

0615: define_action_sequences $ActSeq - начало последовательности

-< тут описаваются действия, которые должен выполнять актёр с именем -1 >-

0616: define_action_sequences_end $ActSeq - конец последовательности
0618: assign_actor $PLAYER_ACTOR to_action_sequences $ActSeq - присваивание актёру действий
061B: remove_references_to_action_sequences $ActSeq - удаление сведений о последовательности

Например: Анимация "закладование бомбы" состоит из двух частей, если мы напишем их подряд, т.е. без последовательности,то мы увидим только последнюю. Вот "закладование бомбы" с последов-ю:

Copy to Clipboard
0615: define_action_sequences $ActSeq
0605: actor -1 perform_animation_sequence "BOM_PLANT_IN" from_file "BOMBER" 4.0 loop 0 0 0 1 -1
0605: actor -1 perform_animation_sequence "BOM_PLANT_LOOP" from_file "BOMBER" 4.0 loop 0 0 0 0 -1
0616: define_action_sequences_end $ActSeq
0618: assign_actor $PLAYER_ACTOR to_action_sequences $ActSeq
061B: remove_references_to_action_sequences $ActSeq

Если надо выполнять одно действие, то последовательность можно и не использовать.

Вот список файлов и их анимаций, которые я успел найти:
1)Анимации из файла "LOWRIDER":
Анимации из файла "LOWRIDER" применяются к актёрам,сидящим в машине. Если применить к актёру, который не в машине, то ничего такого не произойдёт, но анимимации будут воспроизводятся на высоте 4.0 - 5.0 от самого актёра, короче криво.
"LRGIRL_IDLE_TO_L0" - актёр как-бы садится на лавку и расставляет руки в разные стороны
"LRGIRL_L345_TO_L1" - актёр садится на предмет, который находится выше его пояса
"LRGIRL_BDBNCE" - актёр левой рукой машет так, как-будто кого-то к себе подзывает .
"LRGIRL_L0_TO_L1" - актёр залазит спиной вперёд на предмет, который находится выше его пояса
"LRGIRL_L1_TO_L2" - поднимает правую руку
"LRGIRL_L2_TO_L3" - встаёт,делая вид, что куда-то смотрит,опираясь руками на что-то
"LRGIRL_L3_TO_L4" - поднимает левую руку
"LRGIRL_L4_TO_L5" - оборачивается назад
"LRGIRL_L0_BNCE" | вот это анимации такие же, как и
" LRGIRL _ L 1_ BNCE " | "LRGIRL_L0_TO_L1" - "LRGIRL_L4_TO_L5"
"LRGIRL_L2_BNCE" | но только во время этих анимаций,
"LRGIRL_L3_BNCE" | актёр постоянно несильно
"LRGIRL_L4_BNCE" | подпрыгивает
"LRGIRL_L5_BNCE" |

"RAP_A_loop" - махает руками и головой, как будто начинает танцевать
"RAP_B_loop" - махает руками и головой, как будто начинает танцевать, но более сильно чем A
"RAP_C_loop" - подтанцовывает и чуть-чуть бьет руками по своим ногам
"LRGIRL_HURRY" - Актёр рукой как-бы подзывает кого-то к себе
"LRGIRL_HAIR" - Актёр сидя потягивается
"LRGIRL_IDLELOOP" - нервно дрыгает левой рукой
"PRTIAL_GNGTLKD" - стоит и махает рукой типа "идите"
"tap_hand" - сидит в машине, положив руку на дверь и махает рукой и головой
"sit_relaxed" - сидит в машине,положив руку на дверь
"F_smklean_loop" - курит сигару,обпёршись об что-то и стряхивает с сигары пепел
"lrgirl_bdbnce" - садится на что-то и приглашает рукой подойти
"M_smklean_loop" - стоит,обпёршись туловищем об стену и установив ногу на стену курит сигару

2)Анимации из файла "BOMBER":
"BOM_PLANT_IN" - актёр присаживается,немного шарит руками по земле и встаёт
"BOM_PLANT_LOOP" - актёр шарит руками по земле и встаёт (способ шарить №1)
"BOM_PLANT_CROUCH_IN" - актёр шарит руками по земле и встаёт (способ шарить №2)
"BOM_PLANT_CROUCH_OUT" - актёр шарит руками по земле и встаёт (способ шарить №3)
"BOM_PLANT_2IDLE" - актёр шарит руками по земле и встаёт (способ шарить №4)

Эти способы шарить практически ни чем не отличаются друг от друга.

3)Анимации из файла "POOL":
"POOL_XLONG_SHOT" - актёр делает вид,что он берёт что-то,что лежит перед ним
"POOL_XLONG_START" - актёр делает вид,что он как-будто что-то ложит перед собой
"POOL_LONG_SHOT" - актёр делает вид,что он берёт что-то,что лежит перед ним,но уже медленнее
"POOL_LONG_START" - актёр делает вид,что он берёт что-то,что лежит перед ним,но уже медленнее
"POOL_MED_START" - как-будто у актёра в правой руке верёвка,которую он вытягивает левой рукой.
"POOL_MED_SHOT" - как-будто актёр бьёт кийом по бильярдному шару,но медленно
"POOL_SHORT_SHOT" - как-будто актёр бьёт кийом по бильярдному шару,но ещё медленнее
"POOL_CHALKCUE" - как в бильярде кий (палку,которой бьют), натирают каким-то веществом, чтобы лучше бить

4)Анимации из файла "ON_LOOKERS":
"LKUP_LOOP" - актёр смотрит в небо,прислоняя руку ко лбу
"POINTUP_IN" - актёр взмахивает рукой,как-будто показывает направление
"SHOUT_01" - актёр прикдадывает ладони ко рту,типа зовёт кого-то

5)Анимаця из файла "PLAYIDLES":
"STRETCH" - актёр потягивается

6)Анимации из файла "GANGS":
"PRTIAL_GNGTLKA" - крутит руками,как-будто что-то объясняет
"PRTIAL_GNGTLKF" - разводит руками
"PRTIAL_GNGTLKD" - поднимает локти вверх
"PRTIAL_GNGTLKE" - сгибает руки в локтях,а потом разгибает

"HNDSHKFA_SWT" "GANGS" - что-то жестикулирует руками
"PRTIAL_GNGTLKH" - разговаривает, махая руками
"HNDSHKFA"
"DRUGS_BUY"
"PRTIAL_GNGTLKC"
"PRTIAL_GNGTLKH"
"PRTIAL_GNGTLKG"
"DRNKBR_PRTL" - пьёт из бутылки
"PRTIAL_GNGTLKB"
"PRTIAL_HNDSHK_01"
"DEALER_DEAL" - что-то связанное с деньгами

7)Анимации из файла "PED":
Внимание !Этот файл анимаций загружен с самого начале, при попытке загрузить его игра повиснет. Делайте проверку на его загруженность,перед его использованием.

"IDLE_CHAT" - разводит руками
"ROADCROSS" - смотрит назад через одно плечо,потом через другое
"ATM" - достаёт что-то из нагрудного кармана и показывает на ладоне
"FLEE_LKAROUND_01" - оглядывается по сторонам
"FUCKU" - актёр поднимает правую руку
"walk_armed" - хотьба военного с оружием
"seat_up" - встает ранее сидевший на лавочке
"run_armed" - бежит военный с оружием
"idle_gang1" - выставляет грудь вперёд
"hit_back" - актёра ударили сзади
"hit_r" - актёра ударили сбоку справа
"hit_wall" - актёра ударили спереди
"hit_l" - актёра ударили сбоку слева
"hita_2" - отходит назад, как от удара во время драки
"climb_pull" - начинает лезть чтобы перепрыгнуть через забор
"bomber" - клацает часами на руке
"floor_hit_f" - актёр лежит на земле и его бьют ногой на животе
"fightshb" - во время драки отходит назад
"fall_fall" - падает с высоты
"drown" - актёр утонул
"floor_hit" - актёр лежит на земле и его бьют ногой на спине
"IDLE_taxi" - махает рукой, как будто останавливает такси
"swim_tread" - в воде держится на одном месте,махая руками и ногами
"XPRESSSCRATCH" - актёр стоит чуть пошатываясь и всё.
"XPRESSSCRATCH" - просто стоит и смотрит по сторонам
"HANDSUP" - поднимает руки, как при аресте.
"KO_SHOT_STOM" - анимация пулевого ранения и смерти после него.
"KO_SKID_FRONT" - как будто актёра сбила машина
"DUCK_COWER" - актёр приседает и хватается руками за голову.
"GETUP" - актор падает на спину, а потом встает и стоит
"SEAT_DOWN" - актёр садится
"ENDCHAT_03" - кому-то махает
"GETUP_FRONT" - как будто с высоты падает на живот, а потом встает.
"GUN_STAND" - стоит, держа в руках снайперку
"KO_SPIN_L" - переварачивается, розмахивая руками, и падает
"KO_SKID_BACK" - как будто актёра сбило авто со стороны спины
"WALK_DRUNK" - идет пьяный
"FALL_SKYDIVE" - актор летит с нераскрытым парашютом с простянутыми руками
"FALL_FRONT" - падает с высоты без парашюта
"RUN_PLAYER" - бежит
"WOMAN_IDLESTANCE" - просто стоит как женщина и всё.
"TAP_HAND" - сидит в машине, положив руку на дверь
"CAR_SIT" - сидит в авто, держась руками за руль
"IDLE_STANCE" - просто стоит и дышит
"COWER" - присел и защищает руками голову
"CROUCH_ROLL_R" - кувыркается в другую сторону
"CROUCH_ROLL_L" - кувыркается актёр
"ENDCHAT_01" - как будто всех успокаивает, двигая рукой типа "всё нормально"
"KO_SHOT_FACE" - актёра ударили по морде и он, прикрывая лицо руками, падает на спину
"PHONE_TALK" - прислонил трубку к уху
"KO_SHOT_FRONT" - быстро падает на землю на живот
"IDLE_ARMED" - как будто держит автомат в руках
"WEAPON_CROUCH" - актёр присел, так как приседает СJ.
"IDLE_TIRED" - одышка у актёра
"SEAT_IDLE" - просто сидит и по сторонам не смотрит
"HANDSCOWER" - отходит назад, защищаясь от чего-то
"FIGHTIDLE"- стоит, подготовленный к драке
"FIGHTA_G" - бьет ногой то, что лежит на полу
"CAR_HOOKERTALK" - стоит, сжав руки в кулаки
"HANDSUP" - поднимает руки при аресте.
"abseil" - как будто садиться на к-л выступ и заслоняет рукой лицо
"FIGHTA_M" - бьет рукой стоящее перед ним
"FIGHTA_block" - руками делает блокировку
"FIGHTA_2" - бьет рукой, чуть пройдя вперёд
"gas_cwr" - отходит как от газа
"ENDCHAT_02" - махает руками типа "нет"

8)Анимации из файла "BIKELEAP":
"BK_RDY_IN" - Приседает,но на высоте 2.0 - 3.0 от себя
"BK_RDY_OUT" - как-будто подпрыгивает на скейте
"BK_JMP" - выпрыжка в право и зависание в позиции 'Я супермен',если надо чтоб не зависал,то 0, который стоит перед -1 ms меняем на 1,это можно применять ко всем анимациям,но в
некоторых возврат идёт автоматически.
"BK_BLNCE_IN" - как-будто какапкается по прицепу грузовика
"TRUCK_GETIN" - если кто проходил игру,то наверняка вы вспомните миссию,в которой вам вместе с Цезарем надо было угнать бензовоз,и вот когда Цезарь карапкался по бензовозу-была вот эта самая анимация, но чтоб она получилисась не как попало,сначало надо поместить актёра,который выполняет анимацию в турель того грузовика вот этой командой:

0464: put_actor $A into_turret_on_car $C at_car_offset -1.0 0.0 0.0 position3 shooting_angle 360.0 with_weapon 0

Тут $A - актёр и $C - грузовик,по которому он лезет.

9)Анимации из файла "CAR":
"TYD2CAR_LOW" - это актёр лежит на капоте
"TYD2CAR_MED" - практически тоже самое,что и первое
"TYD2CAR_HIGH" - практически тоже самое,что и первое
"TYD2CAR_TURNR" - актёр отклоняется вправо,лёжа на капоте
"TYD2CAR_TURNL" - актёр отклоняется влево,лёжа на капоте
"TYD2CAR_BUMP" - лёжа на капоте поднимает ноги
Это анимации из миссии 3-го города,в которой надо было прокатить одного чувака на капоте, чтобы он что-то рассказал. Для того,чтобы их использовать вместе с машиной надо создать машину и поместить актёра в турель этой легковушки вот этой командой:
0464: put_actor $A into_turret_on_car $C at_car_offset 0.0 1.266 0.391 position 0 shooting_angle 0.0 with_weapon 0

Тут $A - актёр и $C - машина,на которой он лежит.
"flag_drop" - держит в руке флаг с высоко поднятой рукой, а потом его бросает и опускает руку
"Fixn_car_out" - как будто лежал под машиной, а потом из под неё вылез
"Fixn_car_loop" - лёжа под машиной, её ремонтирует
"Sit_relaxed" - сидит в машине, положив руку на дверь
"tap_hand" - сидит в машине, положив руку на дверь и махает рукой и головой

10)Анимации из файла "PAULNMAC":
"PISS_IN" - актёр приготавливается к писанию
"PISS_LOOP" - актёр писает, но без струи, то уже particle эффект, о них написано в главе "Эффекты частицы "
"PISS_OUT" - актёр заканчивает писать
"PNM_LOOP_A" - актёр крутит торсом, или может он пьян.
"PNM_ARGUE2_A" - актёра шатает, как пьяного
"PNM_ARGUE1_A" - актёр бухой, ну просто "в стельку"

11)Анимация из файла "CASINO":
"MANWIND" - актёр резко поднимает руку, как-будто он болельшик
"WOF" -

12)Анимация из файла "AIRPORT"
"THRW_BARL_THRW" - как будто открывает дверь товарного вагона (короче в бок)

13)Анимации из файла "SMOKING":
"M_SMKLEAN_LOOP" - актёр курит, опёршись на что-то
"M_SMKSTND_LOOP" - актёр просто курит
Но это только анимация, чтобы была сигарета надо загрузить модель #CIGAR, потом создать объект, соеденить его с актёром, и запустить анимацию. Вот так:

14)Анимации из файла "TRAIN"
"tran_gtup" - вылазит на крышу трамвая и разворачивается
"tran_hng" - не может вылезти на крышу и так и висит, чуть пошатывая руками
"tran_ouch" - сначала вешается и висит, как тряпка на верёвке
"tran_stmb" - едет в поезде держась рукой за что-то, поезд шатает и он падает

15)Анимации из файла "SKATE"
"skate_idle" - стоит на роликах на одном месте, передвигая ногами и руками туда-сюда, чтобы не упасть
"skate_run" - быстро едет на роликах
"skate_sprint" - очень быстро едет на роликах

16)Анимации из файла "FINALE"
"fin_hang_l" - висит на верёвке, держась за что-то, и ногами дёргает влево
"fin_jump_on" - бежит и после прыжка руками хватается за что-то и держится

16)Анимации из файла "BOX"
"boxhipin" - берёт с пола коробку и держит ее под боком, придерживая руками
"bxwlko" - начинает идти, держа под боком коробку
"catch_box" - ловит коробку, а потом ее ложит на пол
"bxshwlk" - держит коробку рукой на плече, и несет ее с трудом
"bxhwlki" - пытается нести коробку
"boxshup" - берёт коробку с пола
"boxhipup" - берёт откуда-то коробку и ложит на пол
"boxshdwn" - коробку, которую держал на плече, ложит на пол
"bxhipwlk" - идёт, держа рукой коробку под боком
"bxshwlki" - начинает идти, держа на плече коробку

17)Анимации из файла "POLICE"
"COPTRAF_COME" - махает рукой типа "едь назад"
"COPTRAF_LEFT" - махает руками типа "проезжай" влево
"PLC_DRGBST_01" - какое-то сложное движение...
"COPTRAF_away" - чего-то делает одной рукой
"COPTRAF_stop" - махает одной рукой типа "стой"
"COP_getoutcar_LHS" - вылазит из машины
"COP_move_FWD" - идет, держа пистолет в обоих руках
"crm_drgbst_01" - заключенный сначала поднимает руки, заключенного ложат на капот авто с поднятыми руками, он смотрит назад в таком положении, поворачивается и падает на пол
"door_kick" - бьёт ногой, как будто по двери
"PLC_DRGBST_02" - стоит, обпёршись животом об что-то, берёт что-то со стола и показывает кому-то

18)Анимации из файла "CAR_CHAT"
"CAR_SC1_BR" - сидит в авто, не держась руками за руль, и на что-то смотрит
"carfone_in" - сидит в авто, трясёт рукой, потом берёт трубку телефона и начинает говорить
"carfone_loopA" - разговаривает по телефону, сидя в машине
"carfone_loopA_to_B" - изменяет своё положение в авто, разговаривая по телефону
"carfone_loopB" - уже сидит в изменённом положении, слушая кого-то через телефон
"carfone_loopB_to_A" - изменяет своё положение от B к A в авто, разговаривая пл телефону
"carfone_out" - ложит трубку телефона и берётся руками за руль
"car_SC1_BL" - пассажир авто что-то делает руками
"car_SC1_BR" - пассажир в авто на что-то смотрит
"car_SC1_FL" - водитель в авто на что-то смотрит по сторонам
"car_SC1_FR" - как будто к окну кто-то подошёл, водитель к нему поворачивается и слушает
"car_SC2_FL" - водитель снимает руки с руля, выглядывает в окно и на что-то вдаль смотрит
"car_SC3_br" - сидящий в авто что-то жестикулирует руками
"car_SC3_fl" - водитель что-то говорит сидящему сзади
"car_SC3_fr" - водитель что-то говорит стоящему возле его окна
"car_SC4_bl" - что-то делает одной рукой, сидя на мотоцикле
"car_SC4_br" - что-то делает, сидя на мотоцикле и недержась за руль
"car_SC4_fl" - водитель сидит в авто и смотрит по сторонам на что-то
"car_SC4_fr" - сидит на мото и что-то делает
"car_talkm_in" - подходит к водителю, ложит руку на машину и другой рукой махает
"car_talkm_loop" - уже что-то говорит водителю, махая рукой
"car_talkm_out" - перестаёт говорить, встаёт и стоит

19)Анимации из файла "PYTHON"
"python_reload" - перезаряжает пистолет и смотрит на него
"python_fire_poor" - стреляет из пистолета вбок
"python_fire" - стреляет из пистолета вбок
"python_crouchreload" - перезаряжает пистолет и смотрит на него в положении присевши
"python_crouchfire" - стреляет из пистолета вперёд в положении присевши

Copy to Clipboard
:ZZZ
wait 0
04ED: load_animation "SMOKING"
model.Load(#CIGAR)
038B: load_requested_models

:ZZZ_2
wait 0
if and
04EE: animation "SMOKING" loaded
model.Available(#CIGAR)
jf @ZZZ_2
$obj = Object.Create(#CIGAR, 0.0, 0.0, 0.0)
070A: unknown_action_sequence $PLAYER_ACTOR $obj 0.04 0.1 -0.02 5 16 "NULL" "NULL" -1
// цепляем объект на актёра
0605: actor $PLAYER_ACTOR perform_animation_sequence "M_SMKSTND_LOOP" from_file "SMOKING" 4.0 loop 1 0 0 1 8000 ms
end_thread

Это мизерная часть всех анимаций, если вам нечего делать, то открывайте Anim.img , экспортируёте оттуда файлы анимаций и просматривайте их любым текстовым редактором, если найдёте слово на английском, отличное от названия к-л части тела, то это и будет анимация...


Текст

Выводить текст в игре можно несколькими способами:
1) Чёрный квадратик в левом верхнем углу выводится вот этой командой:

03E5: text_box 'VAL_GOT'

'VAL_GOT'- это имя записи в файле American.gxt,но увы эту надпись мы увидеть не сможем, нет нормального GXT-Editor'a, там все надписи выражены в виде шестнадцатиричных чисел, а в билдер число не запишишь, только текст, но можно пользоваться и другим способом:

1 - берёте любую запись в American.gxt с помощью GXT-Editor'a
2 - копируете её текст в буфер,нажатием CTRL + С,
3 - запускаете свой Sanny Builder и открываете оригинальный Main,
4 - жмёте CTRL + F (поиск по тексту Sanny Builder'a) и вводите ваш текст из записи GXT-Editor'a нажатием CTRL + V,
5 - если вы всё правильно сделали, то поиск должен найти нужную строку,
6 - в этой строке будет написано имя GXT-записи, теперь вы знаете, какое слово отвечает за выбранную запись в American.gxt,
7 - теперь вы знаете имя записи и можете вставлять текст в свои потоки,если у вас англ. версия SA, то редактируйте текст записи сразу GXT-Editor'ом, а вот если русская,то надо сначало вам закачать "Переводчик", который переводит русский текст в текст русскоязчного SA, качайте на http://www.progta.h16.ru .

03E6: remove_text_box - эта команда убирает чёрный квадратик с экрана.

2) Можно выводить текст под жизнями и звёздачками розыска вот этой командой:

04F7: status_text $Var 0 line 1 'VAL_GOT'

$Var - переменная,которая будет написана в строке,
Число 0, стоящее после переменной, показывает тип текста (0 - обыкновенный текст, 1 - линия),
Число,стоящее после line 0, показывает номер строки (1,2,3),
'VAL_GOT' - наверное вы уже поняли,что это имя GXT-записи,текст которой тоже будет стоять в строке.

0151: remove_status_text $Var - эта команда убирает данный вид текста с экрана,здесь $Var - это имя переменной,которую мы выводили.

3) Также текст можно выводить вот так:

00BA: text_styled 'VAL_GOT' 1000 ms 1

'VAL_GOT' - имя GXT-записи,
1000 - время,за которое текст будет выводиться,понимаете,что если вы напишите 10000, то текст будет выводиться и убираться с экрана,пока не пройдут 10000 миллисекунд,короче поэксперементируйте со временем и поймёте. 1 - это стиль вывода текста, вот все стили:

1 - текст выводится по центру, когда пишет МИССИЯ ВЫПОЛНЕНА используется этот стиль,
2 - выводится в правом нижнем углу, название миссий выводится таким стилем,
3 - огромными белыми буквами на весь экран, этот текст не убирается с экрана сам, но как и самому убрать я не знаю тоже,
4 - средними коричневыми буквами в строчку и по центру экрана,
5 - средними коричневыми буквами в столбик и вверху экрана,
6 - средними белыми буквами в строчку и по центру экрана,
7 - большими белыми буквами в строчку и вверху экрана.

4) Способ вывода текста,который я описал предыдущим,также можно комбинировать с переменными:

01E3: text_1number_styled 'VAL_GOT' $VAR_1 5000 ms 1

'VAL_GOT' - имя GXT-записи,
$VAR_1 - имя переменной,
5000 - время на экране,
1 - стиль вывда,стили описал ранее.
Данную команду мы использовали,чтобы вывести текст вместе с одной переменной, а можно выводить и с несколькими сразу:

01E3: text_1number_styled 'VAL_GOT' $VAR_1 5000 ms 1 - для 1 переменной,
036D: text_2numbers_styled 'TX_SEQ' $VAR_1 $VAR_2 5000 ms 1 - для 2 переменных,
02FF: text_3numbers 'WHEEL12' $VAR_1 $VAR_2 $VAR_3 time 3000 ms 1 - для 3 переменных,
0302: text_4numbers 'WHEEL01' $VAR_1 $VAR_2 $VAR_3 $VAR_4 3000 ms 1 - для 4 переменных.

5) Самый распространённый способ вывода - это способ вывода диалогом:

00BC: text_highpriority 'MTIME3' 5000 ms 1

'MTIME3' - имя GXT-записи,
5000 - время на экране,
1 - стиль вывда,стили описал ранее.

6) Предыдущий способ вывода также можно комбинировать с переменными:

01E5: text_1number_highpriority 'LOW_38' $VAR_1 5000 ms 1 - для 1 переменной,
0303: text_4numbers_highpriority 'QUAR_P6' $VAR_1 $VAR_2 $VAR_3 $VAR_4 10000 ms 1 - для 4 переменных.
Чтобы переменные были не в конце текста,то в GXT Editor'e в самом тексте вставляйте ~1~, там где вы хотите, чтобы стояли переменные в тексте в игре, но ~1~ - это для первой переменной, а для других переменных ~2~,~3~,~4~.

Например:

У меня есть текст, его запись 'VAL_GOT', вот так выглядит сам текст :
YHNVOPMA LAKER 6SLA DOCTABLEHA B BAW WKAV! - это из-за русскоязычного SA такой текст Теперь мне надо вставить туда в текст к-л переменную:
YHNVOPMA ~1~ LAKER 6SLA DOCTABLEHA B BAW WKAV! - видите, я вставил ~1~,это означает, что там будет стоять первая переменная (у меня единственная), но можно и больше вставлять.
Теперь я использую команду для вывода текста с одной переменной (описаны выше):
01E5: text_1number_highpriority 'VAL_GOT' $VAR_1 5000 ms 1 - переменная $VAR_1 теперь стоит не в конце текста, а после слова YHNVOPMA, вот сами проверьте, но сначала присвойте значение этой переменной, по поводу переменных написано в главе "Переменные".


Панель, или список товаров

При покупке одежды, оружия, экспорте транспорта нам предлагается список товаров и услуг, а также их стоимость. Выбрав один из пунктов, мы имеем возможность приобрести этот товар. Как же реализована эта возможность?

В GTA San Andreas для этих целей применяется пара опкодов:

08D4: $Panel = create_panel_with_title 'IE09' position 29.0 170.0 width 180.0 columns 1 interactive 1 background 1 alignment 0
08DB: set_panel $Panel column 0 header 'DUMMY' data 'IE16' 'IE10' 'IE11' 'IE12' 'IE13' 'IE14' 'IE15' 'DUMMY' 'DUMMY' 'DUMMY' 'DUMMY' 'DUMMY'

Опкодом 08D4: создаем панель с названием 'IE09'
в координатах 29.0 170.0, это координаты левого верхнего угла панели
ширина панели - 180.0,
количество столбцов – 1
interactive – 1 можно выбирать из списка, 0 – нет выбора
background – 1 будет черный фон, 0 - прозрачно
alignment 0 выравнивание текста, 0 - по центру , 1 - по левому краю, 2 - по правому

Опкодом 08DB: устанавливаем в панели $Panel для первого столбца название этого столбца 'DUMMY' и названия строк 'IE16' 'IE10' 'IE11' 'IE12' 'IE13' 'IE14' 'IE15' 'DUMMY' 'DUMMY' 'DUMMY' 'DUMMY' 'DUMMY'.
Максимальное количество строк в столбце – 12, если необходимо использовать только 7, как в нашем случае, то остальные неиспользуемые записываются с названием 'DUMMY'.
'DUMMY' – без названия.
'IE09'-'IE15' – GXT текст из GXT таблицы 'MAIN'
Для примера, создадим панель

Copy to Clipboard
:PANEL
thread 'PANEL'

:PANEL_1
wait 0
01B4: toggle_player $PLAYER_CHAR can_move 0 // обездвиживаем игрока
0512: show_permanent_text_box 'IE20' //выводим text_box
0581: toggle_radar 0 // убираем радар
08D4: $PANEL = create_panel_with_title 'IE09' position 29.0 170.0 width 180.0 columns 1 interactive 1 background 1 alignment 0
08DB: set_panel $PANEL column 0 header 'DUMMY' data 'IE16' 'IE10' 'IE11' 'IE12' 'IE13' 'IE14' 'IE15' 'DUMMY' 'DUMMY' 'DUMMY' 'DUMMY' 'DUMMY'

:PANEL_3
wait 0
if
00E1:   player 0 pressed_key 15
jf @PANEL_3
0581: toggle_radar 1 //возвращаем радар
03E6: remove_text_box // убираем text_box
08DA: remove_panel $PANEL //удаляем панель
01B4: toggle_player $PLAYER_CHAR can_move 1 // возвращаем управление игроком
end_thread

Сейчас он демонстрирует только вывод панели и при нажатии на кнопку F или ENTER убираем панель. Теперь необходимо сделать возможность выбора. Нумерация строк и столбцов начинается с 0.
Для того, чтобы определить, какая строка выбрана применяется опкод
08D7: 0@ = panel $Panel active_row
т.е. записываем в переменную 0@ номер строки.
Нам необходимо определиться, что будет происходить при выборе строки.
Сделаем при выборе одного из пунктов меню вывод текста.

Copy to Clipboard
:PANEL
thread 'PANEL'

:PANEL_1
wait 0
01B4: toggle_player $PLAYER_CHAR can_move 0 // обездвиживаем игрока
0512: show_permanent_text_box 'IE20' //выводим text_box
0581: toggle_radar 0 // убираем радар
08D4: $PANEL = create_panel_with_title 'IE09' position 29.0 170.0 width 180.0 columns 1 interactive 1 background 1 alignment 0
08DB: set_panel $PANEL column 0 header 'DUMMY' data 'IE16' 'IE10' 'IE11' 'IE12' 'IE13' 'IE14' 'IE15' 'DUMMY' 'DUMMY' 'DUMMY' 'DUMMY' 'DUMMY'

:PANEL_2
wait 0
if
00E1: player 0 pressed_key 16 // если нажата клавиша «ПРОБЕЛ»
jf @PANEL_9 //если нет, то переходим на метку PANEL_9
08D7: 0@ = panel $Panel active_row  // получаем номер строки
if
 0@ == 0 //если выбрана первая строка
jf @PANEL_3 // если нет, то переходим на метку PANEL_3
00BE: text_clear_all // убираем весь текст
00BA: show_text_styled GXT 'MTG02F' time 3000 style 5
// выводим текс на экран
jump @PANEL_9 // переходим на метку PANEL_9

:PANEL_3
if
 0@ == 1 // если выбрана вторая строка
jf @PANEL_4
00BE: text_clear_all
00BA: show_text_styled GXT 'MTIME1' time 3000 style 5
jump @PANEL_9

:PANEL_4
if
 0@ == 2
jf @PANEL_5
00BE: text_clear_all
00BA: show_text_styled GXT 'MTIME2' time 3000 style 5
jump @PANEL_9

:PANEL_5
if
 0@ == 3
jf @PANEL_6
00BE: text_clear_all
00BA: show_text_styled GXT 'MTIME3' time 3000 style 5
jump @PANEL_9

:PANEL_6
if
 0@ == 4
jf @PANEL_7
00BE: text_clear_all
00BA: show_text_styled GXT 'MTIME4' time 3000 style 5
jump @PANEL_9

:PANEL_7
if
 0@ == 5
jf @PANEL_8
00BE: text_clear_all
00BA: show_text_styled GXT 'MTIME5' time 3000 style 5
jump @PANEL_9

:PANEL_8
if
 0@ == 6  // если выбрана седьмая строка
jf @PANEL_9
00BE: text_clear_all
00BA: show_text_styled GXT 'MTIME6' time 3000 style 5

:PANEL_9
wait 0
if
00E1:   player 0 pressed_key 15
jf @PANEL_2 //если не нажата клавиша F или ENTER
0581: toggle_radar 1 // возвращаем радар
03E6: remove_text_box // убираем text_box
08DA: remove_panel $PANEL // удаляем панель
01B4: toggle_player $PLAYER_CHAR can_move 1
// возвращаем управление игроком
end_thread

В этом примере панель будет на экране до тех пор, пока не будет нажата клавиша F или ENTER и если она будет нажата, то возвращаем игроку управление, и завершаем поток.

Если вы дочитали это статью, то хочу с вами поделиться еще одним немаловажным требованиям к панелям, а именно:
В GTA San Andreas существует ограничение для панелей. Одновременно на экран можно выводить только две панели, если пытаться вывести больше игра вылетает.


Панель, или список товаров. Часть II

[продолжение. начало читайте здесь]

В первой части мы рассмотрели простой вариант панели, теперь добавим зависимость от количества денег у игрока. Ну и соответственно всегда интересно знать, сколько товар стоит, для этого добавим второй столбец.
Воспользуемся опкодом:

08D6: set_panel $Panel column 1 alignment 2

Но этим опкодом мы добавили только столбец, теперь необходимо добавить строки.

08EE: set_panel $Panel column 1 row 0 text_1number GXT 'DOLLAR' number 2@  // $~1~
08EE: set_panel $Panel column 1 row 1 text_1number GXT 'DOLLAR' number 3@  // x ~1~
08EE: set_panel $Panel column 1 row 2 text_1number GXT 'DOLLAR' number 4@  // $~1~

Переделаем наш скрипт так, чтобы сама панель появлялась не с начала игры, а при условии, что игрок находится в определенном месте и у игрока достаточно наличных.

Copy to Clipboard
:PANEL
thread 'PANEL'

:PANEL_1
wait 0
if and
0038:   $ONMISSION == 0
0256:   player $PLAYER_CHAR defined
0102: actor $PLAYER_ACTOR near_point 2486.2712 -1650.4073 13.4805 radius 1.0 1.0 1.0 sphere 1
jf @PANEL_1
if
010A:   player $PLAYER_CHAR money > 100
//Проверяем, есть ли у игрока нужное количество денег
jf @PANEL_5
2@ = 100 // стоимость товара
3@ = 120 // стоимость товара
4@ = 150 // стоимость товара
5@ = 200 // стоимость товара
6@ = 220 // стоимость товара
7@ = 250 // стоимость товара
8@ = 270 // стоимость товара
01B4: toggle_player $PLAYER_CHAR can_move 0
0512: show_permanent_text_box 'AMMU_H'
0581: toggle_radar 0
08D4: $PANEL = create_panel_with_title 'AMMUN' position 29.0 170.0 width 300.0 columns 2 interactive 1 background 1 alignment 1
08DB: set_panel $PANEL column 0 header 'DUMMY' data 'HOTKNIF' 'KATANA' 'BASEBAT' 'CHAINSA' 'GA_12' 'GUN8' 'GUN5' 'DUMMY' 'DUMMY' 'DUMMY' 'DUMMY' 'DUMMY'
08D6: set_panel $PANEL column 1 alignment 1
08EE: set_panel $Panel column 1 row 0 text_1number GXT 'DOLLAR' number 2@  // $~1~
08EE: set_panel $Panel column 1 row 1 text_1number GXT 'DOLLAR' number 3@  // x ~1~
08EE: set_panel $Panel column 1 row 2 text_1number GXT 'DOLLAR' number 4@  // $~1~
08EE: set_panel $Panel column 1 row 3 text_1number GXT 'DOLLAR' number 5@  // $~1~
08EE: set_panel $Panel column 1 row 4 text_1number GXT 'DOLLAR' number 6@  // x ~1~
08EE: set_panel $Panel column 1 row 5 text_1number GXT 'DOLLAR' number 7@  // $~1~
08EE: set_panel $Panel column 1 row 6 text_1number GXT 'DOLLAR' number 8@  // $~1~

:PANEL_3
wait 0
if
00E1:   player 0 pressed_key 15
jf @PANEL_2
0581: toggle_radar 1
03E6: remove_text_box
08DA: remove_panel $PANEL
01B4: toggle_player $PLAYER_CHAR can_move 1
wait 1000
jump @PANEL_1

:PANEL_5
03D6: remove_styled_text 'NOMONEY'
00BC: text_highpriority 'NOMONEY'  3000 ms  1
0002: jump @PANEL_1

Теперь у нас есть перечень товаров и их стоимость. Все хорошо, но сама панель выглядит ужасно.

Это происходит, потому что мы не указали размер столбцов и поэтому первый и второй столбец создаются с шириной равной ширине панели. Поправим это.
09DB: set_panel $Panel column 0 width 230 – установим для первого столбца ширину 230
09DB: set_panel $Panel column 1 width 70 – соответственно для второго – 70.

Теперь нам осталось добавить результат выбора строки, то есть то, что будет происходить при выборе одной из строк в нашей панели. Воспользуемся вариантом, рассмотренным в первой статье. Очень удобно применять для этих целей таблицу переходов, но для простоты эксперимента не будем отвлекаться на сложные материи.
Вот что у нас получилось:

Copy to Clipboard
:PANEL
thread 'PANEL'

:PANEL_1
wait 0
if and
0038:   $ONMISSION == 0
0256:   player $PLAYER_CHAR defined
0102: actor $PLAYER_ACTOR near_point 2486.2712 -1650.4073 13.4805 radius 1.0 1.0 1.0 sphere 1
jf @PANEL_1
if
010A:   player $PLAYER_CHAR money > 100
//Проверяем, есть ли у игрока нужное количество денег
jf @PANEL_5
2@ = 100 // стоимость товара
3@ = 120 // стоимость товара
4@ = 150 // стоимость товара
5@ = 200 // стоимость товара
6@ = 220 // стоимость товара
7@ = 250 // стоимость товара
8@ = 270 // стоимость товара
01B4: toggle_player $PLAYER_CHAR can_move 0
0512: show_permanent_text_box 'AMMU_H'
0581: toggle_radar 0
08D4: $PANEL = create_panel_with_title 'AMMUN' position 29.0 170.0 width 300.0 columns 2 interactive 1 background 1 alignment 1
08DB: set_panel $PANEL column 0 header 'DUMMY' data 'HOTKNIF' 'KATANA' 'BASEBAT' 'CHAINSA' 'GA_12' 'GUN8' 'GUN5' 'DUMMY' 'DUMMY' 'DUMMY' 'DUMMY' 'DUMMY'
08D6: set_panel $PANEL column 1 alignment 1
08EE: set_panel $Panel column 1 row 0 text_1number GXT 'DOLLAR' number 2@  // $~1~
08EE: set_panel $Panel column 1 row 1 text_1number GXT 'DOLLAR' number 3@  // x ~1~
08EE: set_panel $Panel column 1 row 2 text_1number GXT 'DOLLAR' number 4@  // $~1~
08EE: set_panel $Panel column 1 row 3 text_1number GXT 'DOLLAR' number 5@  // $~1~
08EE: set_panel $Panel column 1 row 4 text_1number GXT 'DOLLAR' number 6@  // x ~1~
08EE: set_panel $Panel column 1 row 5 text_1number GXT 'DOLLAR' number 7@  // $~1~
08EE: set_panel $Panel column 1 row 6 text_1number GXT 'DOLLAR' number 8@  // $~1~
09DB: set_panel $Panel column 0 width 230
09DB: set_panel $Panel column 1 width 70

:PANEL_2
wait 0
if
00E1: player 0 pressed_key 16 // если нажата клавиша «ПРОБЕЛ»
jf @PANEL_3
08D7: 0@ = panel $Panel active_row // записываем номер строки
gosub @PANEL_RESULT // переходим на метку PANEL_RESULT

:PANEL_3
wait 0
if
00E1:   player 0 pressed_key 15
jf @PANEL_2
0581: toggle_radar 1
03E6: remove_text_box
08DA: remove_panel $PANEL
01B4: toggle_player $PLAYER_CHAR can_move 1
wait 1000
jump @PANEL_1

:PANEL_5
03D6: remove_styled_text 'NOMONEY'
00BC: text_highpriority 'NOMONEY'  3000 ms  1
0002: jump @PANEL_1

:PANEL_RESULT
010B: 14@ = player $PLAYER_CHAR money // записываем в переменную количество денег игрока
if
 0@ == 0 //если выбрана первая строка
jf @PANEL_RESULT_2
if
002D: 14@ >= 2@ //количество денег у игрока больше или равно стоимости товара
jf @PANEL_RESULT_8
//если нет, то выводим надпись о том, что у игрока не достаточно денег
00BE: text_clear_all //убираем весь текст
00BA: show_text_styled GXT 'MTG02F' time 3000 style 5
1@ = 0 // вводим переменную
0062: 1@ -= 2@ //отнимаем стоимость товара
0109: player $PLAYER_CHAR money += 1@
//устанавливаем игроку общее количество денег с учетом покупки товара
jump @PANEL_RESULT_9 // переходим на метку выхода

:PANEL_RESULT_2
if
 0@ == 1
jf @PANEL_RESULT_3
if
002D: 14@ >= 3@
jf @PANEL_RESULT_8
00BE: text_clear_all
00BA: show_text_styled GXT 'MTIME1' time 3000 style 5
1@ = 0
0062: 1@ -= 3@
0109: player $PLAYER_CHAR money += 1@
jump @PANEL_RESULT_9

:PANEL_RESULT_3
if
 0@ == 2
jf @PANEL_RESULT_4
if
002D: 14@ >= 4@
jf @PANEL_RESULT_8
00BE: text_clear_all
00BA: show_text_styled GXT 'MTIME2' time 3000 style 5
1@ = 0
0062: 1@ -= 4@
0109: player $PLAYER_CHAR money += 1@
jump @PANEL_RESULT_9

:PANEL_RESULT_4
if
 0@ == 3
jf @PANEL_RESULT_5
if
002D: 14@ >= 5@
jf @PANEL_RESULT_8
00BE: text_clear_all
00BA: show_text_styled GXT 'MTIME3' time 3000 style 5
1@ = 0
0062: 1@ -= 5@
0109: player $PLAYER_CHAR money += 1@
jump @PANEL_RESULT_9

:PANEL_RESULT_5
if
 0@ == 4
jf @PANEL_RESULT_6
if
002D: 14@ >= 6@
jf @PANEL_RESULT_8
00BE: text_clear_all
00BA: show_text_styled GXT 'MTIME4' time 3000 style 5
1@ = 0
0062: 1@ -= 6@
0109: player $PLAYER_CHAR money += 1@
jump @PANEL_RESULT_9

:PANEL_RESULT_6
if
 0@ == 5
jf @PANEL_RESULT_7
if
002D: 14@ >= 7@
jf @PANEL_RESULT_8
00BE: text_clear_all
00BA: show_text_styled GXT 'MTIME5' time 3000 style 5
1@ = 0
0062: 1@ -= 7@
0109: player $PLAYER_CHAR money += 1@
jump @PANEL_RESULT_9

:PANEL_RESULT_7
if
 0@ == 6
jf @PANEL_RESULT_9
if
002D: 14@ >= 8@
jf @PANEL_RESULT_8
00BE: text_clear_all
00BA: show_text_styled GXT 'MTIME6' time 3000 style 5
1@ = 0
0062: 1@ -= 8@
0109: player $PLAYER_CHAR money += 1@
jump @PANEL_RESULT_9

:PANEL_RESULT_8 // сообщаем о нехватке наличных
03D6: remove_styled_text 'NOMONEY'
00BC: text_highpriority 'NOMONEY'  3000 ms  1

:PANEL_RESULT_9 // метка выхода
return // возвращаемся на следующую после gosub @PANEL_RESULT строку.

Вот собственно и все что нужно знать о панелях.


Видео и аудио

Давайте начнём с видео эффектов. Сейчас я расскажу об управления камерами и о нескольких эффектах. Я думаю,что объяснять вам,что такое камера,я не буду.
К глубочайшему сожалению сделать что-то толковое и красивое невозможно, потому-что все ролики в игре создаются не только скриптингом, но и всякими анимациями, сделанными в продвинутых графических редакторах.
Вот список команд,которые использубтся во всех роликах игры:

Camera.SetPosition(664.9,-479.6, 16.1,0.0,0.0,0.0) - эта команда помещает камеру в заданную точку карты
664.9 - координата по оси X
-479.6 - координата по оси Y
16.1 - координата по оси Z
0.0, 0.0, 0.0 - вот эти послндние три параметра остаются такими всегда,везде они равны 0.0

Camera.PointAt(665.8948, -479.5685, 16.4175, 2) - эта команда заставляет камеру посмотреть
в заданную точку карты
665.8948 - координата по оси X
-479.5685 - координата по оси Y
16.4175 - координата по оси Z
2 - тип перемещения камеры.
Всего есть два типа:
1 - допустим мы поставили камеру, направили её в какую-то точку, и теперь, если мы меняем точку, в которую смотрит камера, то действие перемены положения точки и камеры происходит
плавно, т.е. не мгновенный переход. Посмотрите пимер и всё поймёте.
2 - тоже самое, что и первое, но камера перемещается мгновенно

Чтобы изменить скорость полёта и поворота камеры используем вот это:
0460: set_camera_pointing_time 0.0 3000
0.0 - не трогайте, этот параметр всегда такой
3000 - время перемещения камеры
Эта команда действует только тогда, когда последний параметр команды Camera.PointAt равен 1

Также можно сделать так, чтобы камера смотрела на актёра,но сначало камеру надо поставить:
Camera.OnPed($PLAYER_ACTOR, 15, 2)
$PLAYER_ACTOR - актёр, на которого смотрит камера
15 - не знаю
2 - тип перемещения камеры, типы описаны выше

Чтобы камера смотрела на машину используем вот это:
Camera.OnVehicle($Car, 15, 2)
$Car - имя машины, на которую смотрит камера
15 - не знаю
2 - тип перемещения камеры, типы описаны выше

Камеру также можно поместить на автомобиль:
0679: put_camera_on_vehicle $Car offset -5.0 -15.0 10.0 rotation 0.0 5.0 1.0 0.0 2
$Car - машина, на которую ставится камера
-5.0 -15.0 10.0 - координаты камеры относительно геом. центра машины
0.0 5.0 1.0 - координаты относительно геом. центра машины, в которые смотрит камера
0.0 - угол наклона камеры
2 - тип перемещения камеры

Можно поставить камеру на автомобиль и заставить камеру смотреть на актёра:
067B: put_camera_on_car $Car offset -1.5 1.5 1.5 point_to_actor $Actor tilt 6.0 2
$Car - машина,на которую ставится камера
-1.5 1.5 1.5 - положение камеры, относительно геометрического места машины
$Actor - имя актёра, на которого будет смотреть камера
6.0 - угол наклона камеры
2 - тип перемещения камеры

Можно поставить камеру на автомобиль и заставить её смотреть на другой автомобиль:
067A: put_camera_on_car $Car_1 offset 0.0 0.0 3.0 point_to_car $Car_2 tilt 0.0 2
$Car_1 - машина,на которую ставится камера
-1.5 1.5 1.5 - положение камеры, относительно геометрического места машины
$Car_2 - имя машины, на которую будет смотреть камера
6.0 - угол наклона камеры
2 - тип перемещения камеры

Есть интересная команда, которая помещает камеру в определённую точку, и в этой точке камеру можно вращать мышкой, вот эта команда:
0930: (unknown) 1
Но она только поместит камеру в точку 0.0 0.0 0.0 , её там можно будет вращать.
Но чтобы поместить камеру в др. точку, то после той команды пишем эту:
0936: set_camera 146.0 1558.4 104.4 position_to 146.0 1558.4 104.4 10 ms 1
146.0 1558.4 104.4 - вот координаты точки, незабудьте, что они повторяются в конце команды.
То есть полная конструкция кода помещения камеры в данную точку выглядит вот так:

0930: (unknown) 1
0936: set_camera 146.0 1558.4 104.4 position_to 146.0 1558.4 104.4 10 ms 1

Чтобы установить камеру позади игрока используем эту команду:
Camera.SetBehindPlayer

Можно сделать так, чтобы камера тряслась:
camera.Shake(400)
400 - если значение небольшое, типа этого, то камера несильно трясётся и небольшое время, как ставишь, например, 2000, то начинается дикая тряска, которая вообще не прекращается

Чтобы вернуть камеру в ёё исходное положение, т.е. к игроку используется вот эта команда:
Camera.Restore_WithJumpCut

Видео эффектов немного:

1) 02A3: toggle_widescreen 1 - включает широкий экран (исчезают радар,жизни... и появляются две чёрные линии внизу и вверху экрана)
02A3: toggle_widescreen 0 - выключает широкий экран

2) fade 0 1500 - это затемнение экрана,наверное видили при начале миссии, как только на маркер заходишь
0 - показывает, что это затемнение, если поставить 1, то это будет просветление
1500 - время в миллисекундах, которой будет происходить затемнение (просветление)

3) 0169: set_fade_color 0 0 0 - устанавливает цвет затемнения

4) 0581: toggle_radar 0 - убирает с экрана радар

5) 0826: toggle_hud 0 - убирает с экрана звёздочки,иконку оружия, жизни,короче всё, кроме радара

Ещё есть полезная команда, которая очищает местность от актёров и машин:
0395: clear_area 1 at 681.8004 -474.1063 15.5363 range 3.0
681.8004 -474.1063 15.5363 - координаты очищения
3.0 - радиус очищения

Не менее полезная команда, которая освежает местность по заданным координатам (X,Y),она применяется когда,мы помещаем камеру в точку, далёкую от игрока,или когда помещаем игрока на большое расстояние, просто текстуры там не успевают прорисоваться, а эта команда их прорисовывает:
04E4: unknown_refresh_game_renderer_at 2488.5623 -1876.8645

Пример:

Copy to Clipboard
create_thread @VideoTest // создаём поток

:VideoTest // начинаем поток
wait 7000 // ждём 7 сек
fade 0 1500 // затемнение
wait 2000 // ждём 2 сек
fade 1 1500 // просветление
wait 1500 // ждём 1.5 сек
camera.SetPosition(2490.7458,-1677.2081,27.4875 ,0.0,0.0,0.0 ) // уставливаем камеру
camera.PointAt(2500.9705,-1689.441,13.5505,2) // направляем на дом Карла
wait 5000 // ждём 5 сек
camera.PointAt(2487.7231,-1652.1099,13.5006,1) // камера плавно направ. к дому OG
0460: set_camera_pointing_time 0.0 3000 // устанавливаем время перемещения
wait 6000 // ждём 6 сек
camera.SetPosition(2542.6858,-1673.5902,43.5122,0.0,0.0,0.0)
 // уст. нов. позицию камеры
camera.PointAt(2464.5034,-1668.6432,13.4745,1)
// уст. нов. точку,на которую смотрит к-ра
0460: set_camera_pointing_time 0.0 3000 // устанавливаем время перемещения
wait 8000 // ждём 8 сек
camera.Restore_WithJumpCut // возвращаем камеру в нормальное состояние
end_thread // заканчиваем поток

Если что непонятно, то на вопросы на форум.

Теперь давайте перейдём к аудио эффектам.
Применять аудио эффекты дело довольно сложное, точнее не применять, а найти нужный звук, в игре их очень-очень много, вот как добавить свой я не знаю, наверное должна быть программа для редактирования аудио в SA, но я её не разу не видел.
Чтобы проиграть звук надо сначало его загрузить, делается это вот этой командой:
03CF: load_wav 43205 as 1
43205 - номер звука, номера и описания написаны в файле AudioEvents.txt из папки Data .
1 - номер,под каким его будете использовать Вы в своём скрипте, можно вместо номера писать
и переменную, например:

03CF: load_wav 43205 as 1@

или
03CF: load_wav 43205 as $MyWav

Чтобы проиграть звук используем вот эту команду:
03D1: play_wav 3
3 - ваш номер, Вы его присвоили звуку в команде "load_wav", вместо номера можно написать и переменную, например:

03D1: play_wav 1@

или

03D1: play_wav $MyWav

В конце потока надо выгружать звуки вот этой командой:
040D: unload_wav 3
3 - ваш номер,Вы его присвоили звуку в команде "load_wav",вместо номера можно написать и переменную, например:

040D: unload_wav 1@

или

040D: unload_wav $MyWav

Вот этой командой можно установить точку на карте, из которой будет исходить звук:
03D7: set_wav 3 location 1600.0 1200.0 32.0
3 - ваш номер,Вы его присвоили звуку в команде "load_wav".
1600.0 1200.0 32.0 - координаты.

Также можно присваивать переменным звуки:
04AF: 1@ = unknown_wav_reference 43200
1@ - ваша переменная
43200 - игровой номер звука

Можно прицепить звук к актёру:
0949: link_wav 3 to_actor $Actor
3 - ваш номер, Вы его присвоили звуку в команде "load_wav", вместо номера можно написать и переменную, например:

link_wav 1@ to_actor $Actor

или

link_wav $MyWav to_actor $Actor

$Actor - имя актёра, к которому прицепляем звук.

0917: audio_zone 'MADDOGL' enable_sound 1 - включить (1)/выключить (0) мелодию к-л зоны, например, как в казино, клубе или, может помнете, в Вайсе в супермаркете.

Проверки к звукам (всего 2):

1. 03D0: wav 3@ loaded - звук загружен
83D0: not wav 3@ loaded - звук не загружен

2. 03D2: wav 3@ ended - звук закончился
83D2: not wav 3@ ended - звук не закончился


Специальные актеры

Ну вот и пришло время рассказать вам о специальных актёрах , таких как смоук , райдер и о прочих из миссий ...

Чтобы создать актёра, для начала, нужно загрузить его модель в переменную , делается это командой : 023c: request_special_actor 'sweet' as 1
1 - это номер актёра , в последствии мы будем использовать номера от 1 до 21 , т.е. до максимума. Потом естественно надо загрузить раннее объявленные модели опкодом 038b: load requested models .
Затем нужно проверить, загрузилась ли модель актёра , делается это командой:
023d: special_actor 1 loaded
1 - это тот номер , который мы присвоили модели актера, когда её загружали
уже затем создаём спецактёра, вот этим опкодом:
actor.create(1@,mission1, #special01, 2449.293, -1490.204, 25.968)
#special01 - это модель нашёго актёра, для каждого случая она разная, чтобы её узнать надо к
слову #special добавить номер , под которым мы грузили актёра , после слова #special всегда
должно стоять 2-х злачное число , поэтому если попалось однозначное , то перед ним надо добавить 0,
т.е. вот мы загрузили специального актёра , как номер 1 , модель будет иметь вид #special01 ...

Давайте теперь создадим 3 специальных актёра :

Copy to Clipboard
:acttest // начало потока
wait 2000  // ждём 2  сек. , бывает если не подождать , то может вылететь ...
023c: request_special_actor 'sweet' as 1 //  объявляем специального актёра , как 1
023c: request_special_actor 'smoke' as 2 //  объявляем специального актёра , как 2
023c: request_special_actor 'ryder' as 3 //  объявляем специального актёра , как 3
038b: load requested models   // загружаем ранее объявленные модели .

:actcheck // проверка на загруженность
wait 0 // ждём 0 мс , если не напишем , может вылететь .
if and //если
  023d:  special_actor 1 loaded //специальный  актёр 1 загружен
  023d:  special_actor 2 loaded //специальный  актёр 2 загружен
  023d:  special_actor 3 loaded //специальный  актёр 3 загружен
jf @actcheck //если нет, идём в начало
actor.create(1@,mission1, #special01, 2252.299, -1260.216,  23.962) // создаём актёра №1
actor.create(2@,mission1, #special02, 2252.295, -1260.204,  23.962) // создаём актёра №2
actor.create(3@,mission1, #special03, 2252.293, -1260.221,  23.962) // создаём актёра №3
end_thread //заканчиваем поток.

В игре очень много специальных актёров, которые используются в катсценах,а вытащить их названия оттуда довольно проблематично, поэтому вот список основных специальных актёров игры :

'andre' | Андрэ
'bbthin' | медведь
'bb' | какой-то толстый нигер
'cat' | Каталина
'cesar' | Цезарь
'copgrl2' | Барбара Штернрварт ('copgrl1', 'copgrl3')
'claude' | Клод - главный герой gta3
'crogrl2' | Милли Перкинс('crogrl1', 'crogrl3')
'dwayne' | Двайн
'emmet' | Эммэт
'forelli' | Форелли
'janitor' | механик в коричневой форме
'jethro' | Джетро
'jizzy' | Джиззи
'hern' | офицер Хернандес
'gangrl2' | Денис Робинсон
'gungrl1' | оголённая китаянка
'gungrl2' | китаянка в трусах окраски американского флага
'kendl' | Кендел
'maccer' | Мачер
'maddogg' | Мэд дог
'mecgrl2' | Мишель
'nurgrl2' | Кати
'ogloc' | Оуджи Лок
'paul' | Кент Пауль
'pulaski' | офицер Поласки
'rose' | Розенберг
'ryder1' | Райдер
'ryder2' | Райдер (тип №1)(в маске)
'ryder3' | Райдер (тип №2)
'sindaco' | Синдако
'smoke' | биг смоук
'smokev' | биг смоук в бронежелете
'suzie' | китаец в очках в чёрном
'sweet' | Свиит
'tbone' | ти боне
'tenpen' | офицер Тенпенери
'torino' | Торено
'truth' | праведник
'wuzimu' | ву зи му
'zero' | зеро

Ну вот и всё , со специальными актёрами закончили , наверняка я эту тему затрагивать в последующих версиях СБ Мануала'а не буду .


Контроль клавиатуры.

Для того, чтобы проверить нажата ли нужная клавиша используется опкод:

00E1: key_pressed 0 №клавиши

параметры:
0 – этот параметр не изменяется
№клавиши – номера клавиш от 0 до 19 (клавиша 12 не используется).

Пример:

:test1
wait 0 ms
if
00E1: key_pressed 0 0
004D: jump_if_false @test1

. . . .

<код>

. . . .

В примере производим проверку нажата ли клавиша и если нажата то происходит выполнение следующего за проверкой кода. Если есть необходимость производить проверку на одновременное нажатие двух и более кнопок то код будет такой:

:test1
wait 0 ms
if and
00E1: key_pressed 0 0
00E1: key_pressed 0 1
00E1: key_pressed 0 2
00E1: key_pressed 0 3
004D: jump_if_false @test1

. . . .

<код>

. . . .

*Замечание. Проверка выполнится только тогда, когда будут одновременно нажаты все клавиши. Поэтому то и нет смысла делать проверку на большое количество клавиш.

Итак с проверками мы разобрались но осталось несколько вопросов.
Как известно клавиша 0 отвечает за перемещение влево/вправо и это означает, что опкод
00E1: key_pressed 0 0
сработает при нажатии как на клавишу влево, так и на клавишу вправо. Как же быть в ситуации если есть необходимость знать какая именно клавиша (левая или правая) нажата? Здесь нам поможет опкод:

0494: get_joystick_data 0 $1213 $1214 $1215 $1216

$1213 – переменная которая отвечает за кнопки влево/вправо (номер клавиши 0)
$1214 – вверх/вниз (вперед / назад) (номер клавиши 1)
$1215 – влево/вправо на цифровой клавиатуре (в автомобиле: влево/вправо - клавиши контроля гидравлики )
$1216 - в автомобиле: вверх/вниз - клавиши контроля гидравлики.

Здесь необходимо небольшое пояснение.
Например при нажатии клавиши:

вправо - $1213 = 128
влево - $1213 = -128

та же ситуация будет и для остальных переменных данного опкода.

Пример:
Copy to Clipboard
:testA
wait 0 ms
0494: get_joystick_data 0 $123 $124 $125 $126

:testA_1
wait 0 ms
if
001B: -100 > $123 //если $123 = -128 то соответственно -100 > -128
jf @testA_2 // если $123 не равно -128
00BA: text_styled 'INTRO_2' 2000 ms 2
jump @testA_3

:testA_2
wait 0 ms
if
0019: $123 > 100
jf @testA_3
00BA: text_styled 'INTRO_1' 2000 ms 1

:testA_3
jump @testA

Для контроля перемещения мышки применяется вот такой опкод:

0A4A: store_joystick_offset_to 21@ 22@

где
21@ - перемещение по оси Х
22@ - перемещение по оси Y

Также существует проверка на управление клавиатурой и мышкой:

0A4B: controls_keyboard_and_mouse

Этот опкод проверяет какое управление установлено в меню настроек.

Пример:

Copy to Clipboard
:testA
054C: use_GXT_table 'CASINO9'
wait 0 ms
if
0A4B: controls_keyboard_and_mouse
 jf @testA_1
0512: permanent_text_box 'CAS9_H2' //если установлено управление джойстиком
jump @testA_2

:testA_1
0512: permanent_text_box 'CAS9_H4' //если установлено управление клавиатурой

:testA_2
wait 8000 ms
jump @testA

ну и на закуску опкод блокирующий действие клавиши 15

07CC: player $PLAYER_CHAR disable_key_15 0

0 – включить блокировку
1 – выключить.

См. также статью " Проверка нажатия клавиш"


Транспорт

В этой главе я расскажу вам о действиях и проверках связанных со всеми видами транспорта в GTA San Andreas.Транспортом являются все самолёты, машины, мотоциклы, велосипеды, катера, вертолёты и поезда. Я разделил эту главу на несколько частей:

  1. Создание припаркованных транспортных средств.Пример.
  2. Общие команды,т.е. команды применимые ко всем видам транспртных средств.
  3. Команды,применимые только для машин,мотоциклов и велосипедов.
  4. Команды,применяемые к самолётам.
  5. Команды,применяемые к вертолётам.
  6. Команды,применяемые к лодкам.
  7. Команды,применяемые к поездам.
  8. Условия(проверки).
  9. Дополнительно.
  10. Примеры.

1) Создание припаркованных транспортных средств.
Чтобы создать припаркованное транспортных средство не надо загружать никаких моделей, надо в первую очередь создать свой поток,потом написать начало, ваит и конец потока:

create_thread @MyCars

:MyCars
wait 0

//-------Тут надо писать создание припаркованного тр. средства.-------

end_thread

Там где написано "-------Тут надо писать ..." описывается создание транспортного средства.
Оно состоит из двух команд:

Copy to Clipboard
014B: $Car = init_parked_car_generator #Model 8 8 0 alarm 50 door_lock 0 0 40000 at X Y Z angle 180.0
014C: set_parked_car_generator $Car cars_to_generate_to 101

Разберём эти две команды поподробнее: 1 команда: $Car - имя тр. средства, не должно повторяться. #Model - показывает, машина какой модели должна быть припаркована, все модели в первой колонке файла "handling.cfg" после вырыжения "- cars -". Файл в папке "data" вашего San Andreas'a. Не забывайте, что там модели написаны без знака # впереди, а в SB этот знак надо обязательно добавлять.
Цифры 8 8 обозначают цвет машины, цвета описаны в файле "Carcols.dat", лежит в папке "data". Цифра 50 показывает установленность сигнализации в машине, это проценты.
Цифра 0 после слова "door_lock" показывает вероятность(в процентах) закрытых дверей.
Цифра 0 после слова "lock 0" указывает будут ли менты реагировать на то, что вы угнали машину,если 0,то будут,а если 1, то им это будет по-барабану.
Цифра 40000 указывает цену машины, правда зачем она нужна, ведь тачку всё равно не продать. X, Y, Z - понятно, что это координаты машины.
Цифра 180.0 указывает на угол поворота машины.
2 команда:
$Car - имя тр. средства, которое мы только-что создали.
101 - частота появления машины, если поставим 0, то вообще никогда тачку не увидим, а вот если 101, то транспортное средство будет появлятся всегда.

Теперь вы знаете,как создать припаркованную машину, давайте создадим припаркованных Урануса и Инфернуса возле дома CJ'я:
Если вы ещё не создали поток с именем MyCars, то создаёи его вот так:

Copy to Clipboard
create_thread @MyCars// Если не поняли,где его создавать,то читайте первую главу.

:MyCars
wait 0
014B: $Car1 = init_parked_car_generator #URANUS 8 8 0 alarm 0 door_lock 0 0 40000 at 2488.74 -1670.0 13.34 angle 120.0
// Команда должна быть написана на одной строке !!!
014C: set_parked_car_generator $Car1 cars_to_generate_to 101
014B: $Car2 = init_parked_car_generator #INFERNUS 8 8 0 alarm 50 door_lock 0 0 40000 at 2479.71 -1671.72 13.4 angle 120.0
// Команда должна быть написана на одной строке !!!
014C: set_parked_car_generator $Car2 cars_to_generate_to 101
end_thread

Если у вас игра начинается не возле дома CJ'я, то едьте к его дому и смотрите на припаркованные машины, а если вы с самого начала там появляетесь, то отъедьте недалеко, потом приедьте обратно и получите своего Урануса и Инфернуса вместе с ним тоже. Теперь эти машины будут появлятся постоянно.
А вот сейчас я расскажу о транспорте, который специально создают для потоков, так называемом - одноразовом транспорте.

2) Общие команды,т.е. команды применимые ко всем видам транспртных средств:

Начнём конечно с команды создания транспртного средства:

car.Create($Car,#MODEL,1024.0,768.0,32.0)

$Car - имя нашей машины.
#MODEL - модель машины,где смотреть все модели написал раньше.
1024.0 - координата по оси X.
768.0 - координата по оси Y.
32.0 - координата по оси Z.
Эта команда создаёт транспорт один раз,потом он там появлятся сам не будет, поэтому её и используют во всех потоках и миссиях.
car.Destroy($Car) - уничтожает машину.
car.PutAt($Car,X,Y,Z) - помещает в заданную точку.
03C0: $Car = actor $PLAYER_ACTOR car - записывает в переменную $Car машину актёра.
02E3: $Speed = car $Car speed - присваевает переменной скорость машины.
04BA: set_car $Car speed_instantly 20.0 - устанавливает скорость машины.
Car.SetMaxSpeed($Car, 10.0) - устанавливает максимальную скорость машины, т.е. ту , до которой машина может сама разогнаться.
car.RemoveReferences($Car) - удалить все свединия о машине $Car.
0229: set_car $Car color_to 11 0 - цвета написаны ниже, т.е в разделе "Дополнительно".
0294: set_car $Car sprayable 0 - машину можно перекрашивать,если 1 и нельзя, если 0.
car.StorePos($Car,$X,$Y,$Z) - записать координаты машины в переменные $X, $Y и $Z.
0622: AS_unknown_remove_actor $Actor from_car $Car - убрать актёра из машины.
05CD: AS_actor $Actor exit_car $Car - актёр выходит из машины,если та стоит и выпрыгивает, если едет.
0407: create_coordinate $X1 $Y1 $Z1 from_car $Car offset 0.0 10.8 3.0
0683: attach_car $Car_1 to_car $Car_2 at_offset 0.0 -4.6 0.65 rotation 0.0 0.0 0.0 -
прицепляет одну машину к другой на опред. расстоянии под опред. углами вращения.
marker.CreateAboveCar($Mark,$Car) - создаёт маркер над транспортным средством.
car.DoorStatus($Car) = 0 - двери у машины открыты,если 2,то закрыты.
Car.LockInCurrentPosition($Car) = true - закрепить машину в конкретной позици.
car.SetImmunities($Car,1,1,1,1,1) - устанавливает машине определённые имунитеты, тут первая цифра - защита от пуль, вторая - от огня, третья - от взрывов, четвертая - от оружия ближнего боя,пятая от столкновений.
066C: $P = attach_particle "CEMENT" to_vehicle $C offset 0.0 -4.4 0.0 rotation 0.0 1.0 0.0 1 -
прицепить Раrticle эффект к машине.Все Раrticle эффекты описаны в главе "Раrticle эффекты".
09E1: get_vehicle_model $Model monetary_value $Money - выбирает машину с опред. моделью и определённой ценой.
053F: set_car $Car tires_vulnerable 0 - устанавливает(убирает) возможность к-л действий над корпусом машины.
03F5: unknown_prepare_car $Car for_explosion flag 0 - устанавливает все иммунитеты машине, если ставить 1 , то убирает иммунитеты.
0713: unknown_action_sequence $Act -1 $Car 0.0 0.0 0.0 100.0 0 0 90 - заставляет актёра $Act сидящего в машине с оружеем,стрелять в машину $Car , чтобы использовать надо дать актёру такое оружее,из которого можно стрелять из окна машины.
02D4: unknown_turn_off_car $Car engine - выключает мотор машины.
07DB: $Car 0.0 0.75 0.0 - поварачивает машину на определённый допустимый угол.
0A26: set_radio_to_favorite_station - устанавливает радио на любимую радиостанцию
041E: set_radio_station 0 - устанавливает радиостанцию.Вот их номера:

0 | PlayBack
1 | K-Rose
2 | K-DST
3 | Bounce FM
4 | SFUR
5 | Radio Los Santos
6 | Radio X
7 | CSR 103.9
8 | K-JAH West Radio
9 | Master Sounds
10 | WCTR Talking Radio
11 | MP3 Player
12 | Выключить радио

3) Машины,мотоциклы и велосипеды:
Подбирайте команды с умом,например на велосипед или мотоцикл гидравлику не поставишь,просто некоторые команды тут только для машин.

car.DriveTo($Car) - машина едет в заданную точку.
car.ToggleTaxiLight($Car) = true - включить значок такси на машине, false - выкл.
067F: set_car $Car headlights 2 - включить у машины фары,если 0,то выключить.
06E9: request_car_component #COMPONENT - загрузить компонент тюнинга
06E7: $Comp = add_car_component #COMPONENT to_car $Car - прицепить машине компонент тюнинга.
01EC: make_car $Car very_heavy 1 - делает машину очень тяжёлой.
0506: vehicle_model #WINDSOR set_next_variation 1 1 - уст. опред. модели след. вариацию.
096D: get_car $Car car_component 7 on_slot $Comp - записывает в переменную компонент машины из определённого места(капот,дверь...)
0689: car $Car break_component 1 visible 0 - делает (не)видимыми повреждения к-л компонента.
Car.SetToNormalDriver($Car) - устанавливает машине нормального водителя.
Car.SetDriverBehaviour($Car,Nowhere) - устанавливает тип езды для машины, 0 или Nowhere - никуда не ехать,1 или FollowRoad - следовать дороге, 2 - ездить за игроком, 4 - ездить за игроком,8 - ехать напрямик,не обращая внимания на дорогу.
07F8: car $Car_1 follow_vehicle $Car_2 radius 27.0 - заставляет одну машину следовать за другой,держась на определённом расстоянии.
car.ToggleHydraulics($Car) = true - устанавливает на машину гидравлику.
0657: car $Car open_component 0 - открывает часть машины.Вот номера частей:

0 | Капот.
1 | Багажник.
2 | Дверь водителя или левого переднего места.
3 | Дверь правого переднего места.
4 | Дверь заднего левого места.
5 | Дверь заднего правого места.

00AE: unknown_set_car 71@ to_ignore_traffic_lights 2 - машина игнорирует светофоры(2-да).
0674: set_car_model #ADMIRAL numberplate "VOVAN" - присваевает модели машины задний номер с текстом VOVAN. Сначало надо написать эту команду,а потом уже создать машину с такой моделью.
0939: attach_car $Car to_object $Obj at_offset 0.0 0.0 -0.8 rotation 0.0 0.0 180.0 - прицепить машину к объекту.
0541: fire_guns_on_vehicle $Car - по идее эта команда должна ставить пулемёты на машину, но она создаёт только звук работающего минигана и не больше.
car.setanimation($Car,anim,time) - анимация машины, вот номера anim (надо чтобы был водила) :
3 - едет задом
5 - поворачивает колёса вправо
6 - едет по кругу против часовой стрелки
8 - едет по кругу по часовой стрелке
9 - едет прямо

4) Команды,применяемые к самолётам:

04D2: unknown_RC_car $Plane race_to 1600.0 1200.0 64.0 0.0 0.0 - заставляет настоящий самолёт лететь к заданной точке, 0.0 0.0 - не трогайте.
070F: (unknown) $Plane 0.0 130.0 130.0 - заставляет самолёт лететь под опред.углом(0.0) на опред. высоте (130.0 130.0). Если рассмотреть карту SA, как плоскость,то легко подсчитать угол полёта.
08E6: plane $Plane change_landing_gear 1 - шасси у самолёта выпушенуо, если 1 и не выпущено, если 0, но временами эти команды проглючивают.
084E: flying_vehicle $SamNeLet use_primary_gun 1 - использование самолётом (ГИДРА) ракет.
0841: flying_vehicle $SamNeLet use_secondary_gun 1 - использование пулемёта (ДИЛЛЕР).
0724: flying_vehicle $SamNeLet follow_and_attack_player $PLAYER_CHAR radius 40.0 - самолёт держится на определённом радиусе от игрока и атакует его.
03A2: $Plane 3 - опускает у самолёта закрылки,если ставить меньше,чем 0,то ничего не будет
0745: $Plane - переключение в режим горизонтального полёта (для Гидры)

5) Команды,применяемые к вертолётам:

04A2: heli $Heli fly_to 640.0 480.0 128.0 speed 60.0 60.0 - указывает вертолёту,куда надо лететь,высотой являются последние два параметра "60.0 60.0".
084E: flying_vehicle $Heli use_primary_gun 1 - использование вертолётом (HUNTER) ракет.
0841: flying_vehicle $Heli use_secondary_gun 1 - исп. вертолётом (HUNTER) пулемёта.
0724: flying_vehicle $Heli follow_and_attack_player $PLAYER_CHAR radius 40.0 -
вертолётом держится на определённом радиусе от игрока и атакует его.
0788: enable_heli $Heli magnet 1 - устанавливает на вертолёт магнит,если 0,то убирает.
0789: unknown_drop_car_from_magnet $Heli - отцепляет машину от магнита ветолёта $Heli

6) Команды применяемые к лодкам:

02D3: boat $Boat drive_to 10000.0 -100.0 0.0 - лодка плывёт в заданную точку.
02DB: set_boat $Boat speed_to 50.0 - установить лодке скорость.

7)Команды применяемые к поездам:

06D8: $Train = create_train_at 2285.1523 -1257.4998 23.0 type 15 direction 1 - создаёт поезд типа 15 и ставит его на рельсы того или иного напрвления(послед. параметр).
06DD: set_train $Train speed 23.0 - устанавливает скорость поезда.
06DC: set_train $Train acc 0.0 - устанавливает скорость разгона поезда.
06D7: toggle_train_traffic 0 - частота появления поездов(0-нет вообще,1+ - как всегда).
09CF: set_train $Train flag 0 - задаёт поезду флаги.
078A: $Car = create_carriage_on_train $Train position 1 - создаёт как-бы отдельную машину на определённом месте в поезде

8) Вот проверки,применяющиеся к транспортным средствам :

0185: car $Car health >= 10 - жизни машины $Car больше либо равняется 10
07AB: car $Car_1 attached_to_car $Car_2 - машина 1 пицеплена к машине 2.
0495: car $Car burning - машина горит.
0975: car $Car emergency_vehicle - машина $Car является служебной (пожарная,полиция...)
096F: car $Car street_racing_vehicle - машина $Car является машиной для уличных гонок
02CA: car $Car bounding_sphere_visible - игрок видит авто $Car
02BF: car $Car sunk - машина с именем $Car упало в воду
0981: train $Poezd wrecked - поезд с именем $Poezd уничтожен
01C1: car $Car stopped - машина с именем $Car остановилась
03C9: car $Car damaged - машина с именем $Car повреждена
096E: car $Car lowrider - машина с именем $Car лоурайдер
01C1: car $Car stopped - машина с именем $Car стоит на месте
Car.Id($car) == #HYDRA - модель машины с именем $Car - это #HYDRA
//тут перед всем опкодом можно поставить "not",потому-что тут нет кодового слова.
01F3: car $Car airborne - машина с именем $Car находится в воздухе
//я думаю,что вы поняли,что и в эту команду можно вставить "not".
03CE: car $Car stuck - машина с именем $Car перевёрнута
0119: car $Car wrecked - машина с именем $Car уничтожена
01B0: car $Car stopped 0 near_point X Y Z radius 4.0 4.0 4.0 машина с именем $Car остановилась в радиусе 4.0 от точку с координатами X Y Z
01F4: car $Car flipped - машина с именем $Car тонет
056E: $Car - машина $Car существует
0431: car $Car car_passenger_seat_free 0 - место 0 в машине $Car свободно
051D: cars $Car_1 and $Car_2 collided - машина $Car_1 и $Car_2 столкнулись.
0803: car $Car have_hydraulics - у машины $Car есть гидравлика

9) Дополнительно:

1. Цвета автомобилей:

Номер | Описание | Основной цвет/оттенок
0 | чёрный | Черный
1 | бёлый | Белый
2 | синий автомобиль полиции | Синий
3 | красно вишнёвый | Красный
4 | полночь | Темный синий
5 | занавеса храма фиолетовый | Фиолетовый
6 | такси желтый | Желтый
7 | поразительно синий | Яркий синий
8 | освещают синий серый | Сини-серый
9 | голубовато-синий | Светлый
10 | темно-голубая краска | Синий
11 | типа предыдущего | Серый
12 | Джаспера, почтово зеленые | Синий
13 | оловянной посуды | Серый
14 | морозный белый | Светлый
15 | серебряных камней | Серый
16 | Рио-де-Жанейро красный | Зеленый
17 | красный жемчуг | Красный
18 | красный | Красный
19 | меда | Светлый
20 | синий, как море | Синий
21 | красный с отблеском | Красным
22 | классически красный | Красный
23 | серебро | Серый
24 | сталь | Серый
25 | тёмного серебра | Темный
26 | серебряных камня почтово | Серый
27 | слюды | Серый
28 | синий | Синий
29 | фарфора | Серый
30 | гнилые фрукты | Тёмный
31 | изящная красная слюда | Красный
32 | смородина | Синий
33 | серый | Серый
34 | Арктически белый | Свет
35 | антрацит | Серый
36 | черный | Темный
37 | темно зеленый | Зеленый
38 | дары моря | Свет
39 | алмаза | Синий
40 | коричневый | Темный
41 | темно-коричневый | Темный
42 | гранат(фрукт такой) | Красный
43 | красный | Красный
44 | зеленый | Зеленый
45 | каберне | Красный
46 | слоновый | Светлый
47 | бежевый | Зеленый
48 | серебряного дыма | Светлый
49 | яркое серебро | Серый
50 | серый | Серый
51 | агаово зеленый | Зеленый
52 | бензин | Зеленый
53 | морской прибой | Синий
54 | навигационный синий | Синий
55 | дерево | Темный
56 | кристалла | Синий
57 | морозный | Свет
58 | смородины | Красный
59 | кристалл | Синий
60 | титановый | Свет
61 | ярко жёлтый | Желтым
62 | красный | Красный
63 | кристаллический мороз | Серый
64 | серебро | Серый
65 | алебастр | Желтый
66 | середина смородины | Тёмный
67 | регат | Тёмный
68 | белый твердый | Желтый
69 | алебастр (твердый ) | Светлый
70 | красный | Красный
71 | синий твердый | Синий
72 | титановый | Серый
73 | что-то светлое | Светлый
74 | med.cabernet твердый | Красный
75 | сумерек | Темный
76 | мороз | Серый
77 | сандаловое дерево | Светлый
78 | дикой земляники | Красный
79 | крайний синий | Синий
80 | ярко-красный (твердый) | Красный
81 | сандаловое дерево | Светлый
82 | красный твердый | Красный
83 | драгоценный камень | Зеленый
84 | тёмно-розовый | Тёмный
85 | красный (твердый) | Красный
86 | зеленый | Зеленый
87 | яркий синий | Синий
88 | яркий красный | Красный
89 | что-то светлое | Светлый
90 | серебра | Серебро
91 | синяя сталь | Синий
92 | средний серый | Серый
93 | арктический жемчуг | Светлый
94 | синий | Синий
95 | сапфир | Синий
96 | серебра | Серебро
97 | синий сапфир | Синий
98 | синий | Синий
99 | лён | Желтый
100 | синий | Синий
101 | синий сапфир | Темный
102 | бежевая медь | Светлый
103 | яркий синий | Синий
104 | светло-жёлтый | Желтый
105 | серый | Серый
106 | яркий синий | Синий
107 | дерево | Свет
108 | синий | Синий
109 | сталь | Серый
110 | дерево | Темный
111 | серый | Серый
112 | синий сапфир | Синий
113 | дерево | Темный
114 | красно-зелёный,как у факела | Зеленый
115 | яркий красный | Красный
116 | синий сапфир | Синий
117 | синий сапфир | Красный
118 | белого алмазного жемчуга | Светлый
119 | мех соболя | Темный
120 | шкура антилопы (бежевый) | Светлый
121 | бриллиант(красный) | Красный
122 | металл оружия | Серый
123 | дерево | Тёмный
124 | бриллиант(красные) | Красный
125 | яркий синий | Синий
126 | розовый | Светлый

10) Примеры:

1. Давайте сделаем так,что когда игрок садится в машину,то она становится неуязвимой,и все двери у неё становятся запертыми,так что менты вас оттуда не смогут вытащить:

Copy to Clipboard
create_thread @SuperCar  //создаём поток.

:SuperCar   // Начинаем поток
wait 5000   // ждём 5 секунд
if and      // условие с выполнением всех подусловий
  player.defined($Player_char)  // подусловие ( игрок существует )
  actor.driving($Player_actor)  // подусловие ( игрок за рулём )
jf @SuperCar  // если эти два подусловия не выполнились, то переходим
03C0: $Car = actor $PLAYER_ACTOR car
//Присваиваем переменной имя машины игрока на начало
car.SetImmunities($Car,1,1,1,1,1) // устанавливаем машине иммунитеты
car.DoorStatus($Car) = 2   // делаем двери закрытыми.
wait 2000
:SuperCar_2  // создаём второй label
wait 0  // не ждём ,но писать всё равно надо
if // просто условие
 not actor.driving($Player_actor)  // актёр не за рулём
jf @SuperCar_2  // если всё таки за рулём,то переходим на начало label'a
car.DoorStatus($Car) = 0  // если он не за рулём,
// то возвращаем машине откр. двери
car.SetImmunities($Car,0,0,0,0,0)  // и делаем машину опять уязвимой
car.RemoveReferences($Car)  // и удаляем все сведения о машине игрока,
// чтобы память
jump @SuperCar   // переходим к началу потока  зря не забивать

Смотрите пример здесь.


Работа со звуками в GTA San Andreas.

Всем наверно известны такие варианты загрузки звуков как:

03CF: load_wav 15863 as 1
03CF: load_wav 15805 as 2
03CF: load_wav 32401 as 3
03CF: load_wav 15863 as 4

при этом

03CF: load_wav 15863 as 1
03CF: load_wav 15805 as 2

чаще всего применяются для загрузки диалогов, а

03CF: load_wav 32401 as 3
03CF: load_wav 15863 as 4

для загрузки игровых звуков.

Для проигрыша звука применяется такая команда:

03D1: play_wav 1 //2 //3 //4

Ну и соответственно выгрузка звука:

040D: unload_wav 1 //2 //3 //4

Выгружать звуки нужно обязательно, после их использования, иначе будут проблемы либо звуки вообще не будут воспроизводиться либо будут проигрываться не те, что нужно.
Пример диалога:

Copy to Clipboard
:ZVUK_5800
054C: use_GXT_table 'WUZI1'
//загружаем GXT раздел, необходим для отображения титров
03CF: load_wav 36600 as 1
03CF: load_wav 36601 as 2
:ZVUK_5802
if and
 83D0: not wav 1 loaded //проверяем загрузку звука
 83D0: not wav 2 loaded
jf @ZVUK_5803
wait 0 ms
jump @ZVUK_5802

:ZVUK_5803
03D1: play_wav 1 //проигрываем звук
00BC: text_highpriority 'STL1_AA' 10000 ms 1 //выводим титры

:ZVUK_5804
if
 03D2: wav 1 ended //проверяем, закончился ли проигрыш звука
jf @ZVUK_5805
wait 0 ms
jump @ZVUK_5804

:ZVUK_5805
wait 4000 ms
03D5: remove_text 'STL1_AA' //удаляем текст
040D: unload_wav 1 //удаляем звук
wait 550 ms
03D1: play_wav 2
00BC: text_highpriority 'STL1_AB' 10000 ms 1

:ZVUK_5806
if
 03D2: wav 2 ended
jf @ZVUK_5807
wait 0 ms
jump @ZVUK_5806

:ZVUK_5807
wait 4000 ms
03D5: remove_text 'STL1_AB'
040D: unload_wav 2

Для того чтобы двери, ворота или любой другой объект в игре «зазвучал» применяют такой опкод:

097B: play_audio_at_object 246@ event 1126
//проиграть возле объекта 246@ звук 1126

где
246@ - переменная объекта
1126 – звук (я так понимаю это код звукового файла, если не прав то знающие люди поправят).
Перечень звуков находится в файле GTA San Andreas\data\AudioEvents.txt.
Но одного этого опкода не достаточно, для того чтобы звук был проигран, необходимо прежде его загрузить. Здесь как раз и применяется 03CF: load_wav 1823 as 3 или as 4.

Пример:

Copy to Clipboard
:ZVUK_3786

029B: 246@ = init_object #WAREHOUSE_DOOR2B at 2774.3611 -2417.8291 14.675
0400: create_coordinate 251@ 252@ 253@ from_object 246@ offset 0.0 0.0 4.0
var
$muve2 : Integer
end //end var
$muve2 = 0
03CF: load_wav 1823 as 3

:ZVUK_3787
0001: wait 0 ms
00D6: if
03CA: object 246@ exists
004D: jump_if_false @ZVUK_3789
097B: play_audio_at_object 246@ event 1035

:ZVUK_3789
0006: 32@ = 0 // integer values

:ZVUK_3790
00D6: if
001A: 20 > $muve2
004D: jump_if_false @ZVUK_3792
034E: move_object 246@ to 251@ 252@ 253@speed 0.0 0.0 0.2 flag 0
097B: play_audio_at_object 246@ event 1035
0001: wait 30 ms
$muve2 +=1
000A: 32@ += 1 // integer values
0001: wait 0 ms
0002: jump @ZVUK_3790

:ZVUK_3792
00D6: if
03CA: object 246@ exists
004D: jump_if_false @ZVUK_3793
097B: play_audio_at_object 246@ event 1036

:ZVUK_3793
040D: unload_wav 3
01C4: remove_references_to_object 246@
// This object will now disappear when the player looks away

Здесь при перемещении ворот проигрывается звук.

Опкод:

097C: attach_wav 4 to_object 6@ //прикрепить звук 4 к объекту 6@

пример:

Copy to Clipboard
:IMPND_3038
03CF: load_wav 36000 as 4 //загружаем звук 36000 как 4

:IMPND_3076
wait 0 ms
if
 03D0: wav 4 loaded
jf @IMPND_3076
097C: attach_wav 4 to_object 6@//прикрепить звук 4 к объекту 6@
03D1: play_wav 4 //проигрываем звук
03D7: set_wav 4 location 1589.0597 -1694.7285 10.4887
//разместить звук 4 в координатах 1589.0597 -1694.7285 10.4887

Так же можно присвоить определенный звук и актеру:

09D6: set_actor 1@ sound 5851 flags 1 1 0
// актер 1@ звук 5851 флаг 1 флаг 1 флаг 0
09F1: play_audio_at_actor $PLAYER_ACTOR event 1190
//воспроизвести актеру $PLAYER_ACTOR звук 1190

Можно проиграть определенный звук в заданных координатах.
018C: play_sound 1052 at 0.0 0.0 0.0 // где 0.0 0.0 0.0 – координаты
097A: play_audio_at 0.0 0.0 0.0 event 1136 //проиграть в координатах 0.0 0.0 0.0 звук 1136

Присвоить звук автомобилю:
0A16: link_wav 3 to_car 59@ // прикрепить звук 3 транспорту 59@
03D1: play_wav 3

09F7: play_audio_at_car $SWEETS_CAR event 1147
// воспроизвести транспорту $SWEETS_CAR звук 1147.

Имеются также такие опкоды:
0717: assign_actor 55@ to_dialogue_mode // присвоить актеру 55@ диалог

0A18: set_dialogue_classA_question_GXT 281@s answer_yes_GXT 283@ answer_no_GXT 285@s question_WAV 291@ answer_yes_WAV 292@ answer_no_WAV 293@
//загрузить текст 281@s текст 283@s текст 285@s звук 291@ звук 292@ звук 293@

0A3C: set_dialogue_classA_end_GXT 285@s WAV 297@ //загрузить текст 285@s звук 297@

0719: toggle_dialogue_mode //воспроизвести диалог

Еще такая тройка опкодов:
0952: load_soundtrack 0 //загрузить мелодию 0
// (0,1, 2, 3…с числами можно поэкспериментировать)
0954: start_playing_loaded_soundtrack // проиграть загруженную мелодию
0955: end_playing_loaded_soundtrack // остановить и выгрузить мелодию

Вот вкратце все то, что мне удалось выяснить.


Удалённое управление

В этой главе я расскажу Вам об удалённом управлении или просто-напросто об RC ...
Для того чтобы поместить игрока в удалённое управление можно использовать два способа :
1) Опкодом 046e: put_player $player_char in_rc_mode at x y z a angle rcmodel #model
x , y , z - координаты
a - угол модели
#model - модель rc машинки
этот опкод создаёт машину и сразу садит в неё игрока на удалённое управление .
2) Создание 2-мя опкодами :
car.create($car, x , y , z )
0715: put player $player_char in rc mode in car $car

Чтобы всё это нормально смотрелось, а у некоторых не то чтобы смотрелось, а чтобы работало
следует предварительно помещать актёра в какую-нибудь машину ... как rc машину можно использовать любое транспортное средство игры (смотрите пример1) .

04db: exit_rc_mode - чтобы выйти из удалённого режима используем этот опкод .
04d6: enable_rc_car_detonation 0 - чтобы машина не взрывалась по нажатию "огонь" .
player.inremotemode($player_char) - проверка на нахождение игрока в rc состоянии .

Вот так мало насчёт этого ...

Теперь примеры:

Пример1:
Просто создадим тачку , и поместим игрока в удалённое управление этой тачки :

Copy to Clipboard
:rctest
wait 3000
model.load(#infernus)
model.load(#manana)
038b: load requested models

:check
wait 100
if and
model.available(#infernus)
model.available(#manana)
jf @check
04c4: create_coordinate $x $y $z from_actor $player_actor offset 0.0 5.0 1.0
car.create(1@,#infernus,$x ,$y ,$z)
actor.storepos($player_actor,$x ,$y ,$z)
car.create(2@,#manana,$x ,$y ,$z)
036a: put_actor $player_actor in_car 2@
wait 2000
0715: put_player $player_char in_rc_mode_in_car 1@
wait 1000
model.destroy(#infernus)
model.destroy(#manana)
wait 1000
end_thread

Пример2:
Наверняка вы могли видеть этот мой скрипт на сайте http://missions.gtamaps.net , но всё же я решил его выложить в примерах тоже :

За домом cj'я появляется топфан фургон,с помощью которого можно ездить на разных rc машинках.
Если вы в фургоне и хотите покататься на радиоуправляемой машинке,то сначала нажмите
"подмиссия",потом нажмите "смотреть влево",чтобы полетать на самолётике,кстати,этот
игрушечный самолётик может стрелять,если нажать "огонь",а также сбрасывать бомбы("гудок").
если вам нужен вертолёт(тоже с бомбами),то нажмите "смотреть вправо" сразу после того,как
нажали "подмиссия".также можно поездить на игрушечном танке,нажав "гудок" после "подмиссия".
танк может стрелять,правда не подряд,одно нажатие "огонь" - один выстрел танка.чтобы выйти
из rc машинки жмите "выход из машины".если вы вышли то опять надо жать "подмиссия" и клавишу
машинки,которая вам нужна.если вы нечайно нажали "подмиссия",то можно нажать "выход из машины", и ездить спокойно,чтобы перейти в нормальный режим езды.

Copy to Clipboard
create_thread @rc

:rc
wait 2000
model.load(#rcbaron)
model.load(#topfun)
model.load(#rcbomb)
model.load(#rcgoblin)
model.load(#rctiger)
038b: load_requested_models

:rc_check
wait 0
if and
model.available(#rcbaron)
model.available(#rcgoblin)
model.available(#topfun)
model.available(#rcbomb)
model.available(#rctiger)
jf @rc_check

:rc_2
wait 0
if and
player.defined($player_char)
not actor.driving($player_actor)
84ad: not actor $player_actor touching_water
jf @rc_2

:rc_3
wait 1000
$car = car.create(#topfun, 2528.3347,-1712.3568,13.5471 )
0229: set_car $car color_to 0 0

:rc_3_1
if
actor.incar($player_actor,$car)
jf @rc_3_2
jump @rc_choose

:rc_3_2
wait 0
if
car.wrecked($car)
jf @rc_3_1
jump @rc_2

:rc_choose
wait 0
if
00e1: key_pressed 0 19
jf @rc_choose_b
jump @rc_choose_2

:rc_choose_b
wait 0
if or
car.wrecked($car)
actor.dead($player_actor)
jf @rc_choose
wait 3000
jump @rc_2

:rc_choose_2
wait 0
if
00e1: key_pressed 0 5
jf @rc_choose_3
04c4: create_coordinate $rc_x $rc_y $rc_z from_actor $player_actoroffset 7.0 0.0 0.0
$car_rc = car.create(#rcbaron, $rc_x, $rc_y, $rc_z)
jump @fin_1_2

:rc_choose_3
wait 0
if
00e1: key_pressed 0 7
jf @rc_boroda
04c4: create_coordinate $rc_x $rc_y $rc_z from_actor $player_actor offset 7.0 0.0 0.0
$car_rc = car.create(#rcgoblin, $rc_x, $rc_y, $rc_z)
jump @fin_1_2

:rc_boroda
wait 0
if or
car.wrecked($car)
actor.dead($player_actor)
jf @rc_choose_4
wait 3000
jump @rc_2

:rc_choose_4
wait 0
if
00e1: key_pressed 0 18
jf @rc_choose_5
04c4: create_coordinate $rc_x $rc_y $rc_z from_actor $player_actor
offset 7.0 0.0 0.0 // все пишется одной строкой
 $car_rc = car.create(#rctiger, $rc_x, $rc_y, $rc_z)
jump @fin_tig

:rc_choose_5
wait 0
if or
not actor.incar($player_actor,$car)
00e1: key_pressed 0 15
jf @rc_choose_2
jump  @rc_3_1

:fin_1_2
wait 0
03a2: (unknown) $car_rc 0
0715: put_player $player_char in_rc_mode_in_car $car_rc
04d6: enable_rc_car_detonation 0
048a: enable_rc_car_detonation 0
01ec: make_car $car_rc very_heavy 1

:rc_vst
wait 0
1@ = object.create(#rcbomb, 0.0,0.0, 130.0)
0681: attach_object 1@ to_car $car_rc at_offset 0.0 0.0 -0.3 rotation 0.0 0.0 0.0
035c: place_object 1@ relative_to_car $car_rc offset 0.0 0.0 0.0
object.collisiondetection(1@) = false
object.toggleinmovinglist(1@) = false

:rc_4
wait 250 ms
if and
00e1: key_pressed 0 18
01f3: car $car_rc airborne
jf @rc_4_2
0682: detach_object 1@ 0.0 0.0 0.0 collision_detection 0
object.toggleinmovinglist(1@) = true
object.collisiondetection(1@) = true
038c: object 1@ scatter 0.0 0.0 0.0
wait 100
04d9: object 1@ set_scripted_collision_check 1

:rc_5
wait 0
if or
04da: has_object 1@ collided
04e7: object 1@ in_water
jf @rc_5
object.storepos(1@, $1x , $1y , $1z )
020c: create_explosion_with_radius 7 at $1x  $1y  $1z
04d9: object 1@ set_scripted_collision_check 0
object.destroy(1@)
jump @rc_vst

:rc_4_2
wait 0
if or
00e1: key_pressed 0 15
car.wrecked($car_rc)
jf @rc_s4
04db: exit_rc_mode
object.destroy(1@)
jump @rc_choose

:rc_s4
wait 0
if or
car.wrecked($car)
actor.dead($player_actor)
jf @rc_4
jump @rc_2

:fin_tig
wait 0
03a2: (unknown) $car_rc 0
0715: put_player $player_char in_rc_mode_in_car $car_rc
01ec: make_car $car_rc very_heavy 1
04d6: enable_rc_car_detonation 0
048a: enable_rc_car_detonation 0

:fin_tig_2
wait 0
if or
00e1: key_pressed 0 15
car.wrecked($car_rc)
jf @fin_tig_21
04db: exit_rc_mode
jump @rc_choose

:fin_tig_21
wait 0
if or
car.wrecked($car)
actor.dead($player_actor)
jf @fin_tig_2
jump @rc_2


Разное

Тут я описал команды, которые не подошли не под одну из категорий.

Перейдём к командам.

020C: create_explosion_with_radius 7 at 1024.0 768.0 16.0 - создаёт взрыв радиусом 7 в заданных координатах, если сделаете большой радиус (начиная от 15 или 20), то взрыва вообще не произойдёт.

014E: set_timer_to $Timer type 1 - устанавливает таймеру тип:
0 - при бавление по секунде единицы,
1 - отнимание по секунде единицы.

048B: unknown_car $Car timer $Timer - устанавливает на машину таймер

03C3: set_timer_with_text_to $Timer type 1 text 'BB_19' - запускает таймер

014F: stop_timer $Timer - останавливает таймер
Вот вам пример:

По истечению времени к деньгам игрока прибавится миллион:

Copy to Clipboard
create_thread @TimerOnly // создаём поток

:TimerOnly // начинаем поток
wait 0 // ждём 0 мс,если не напишем,то вылетит
$Time = 100000 // устанавливаем начальное время таймера
014E: set_timer_to $Time type 1 // устанавливаем тип таймера на "убывающий"

:TimerOnly_2 // создаём второй label нашего потока
wait 0 // ждём о мс (на всякий случай)
if // пишем обыкновенное одиночное условие
$Time < 1 // если время таймера меньше 1
jf @TimerOnly_2 // если время ещё больше,чем один, то переходим на начало
Player.Money($PLAYER_CHAR) += 1000000 // а если всё таки меньше, то прибавляем
// игроку деньги в размере 1000000 $
end_thread // и заканчиваем наш поток

$Model = car.Model($Car) - присваивание переменной $Model названия модели машины $Car
car.Id($Car) == #DOZER - поверка, явл. ли модель машины $Car равной #DOZER

00C0: set_current_time 18 0 - устанавливает игровое время на 18:00

015D: set_gamespeed 1.0 - не менее полезная команда, которая устанавливает скорость игры.
Вот пример:

Copy to Clipboard
create_thread @Prosto // создаём поток с именем Prosto

:Prosto // начинаем поток
wait 10 // ждём 10 мс, чтобы не вылетило
015D: set_gamespeed 1.0 // устанавливаем скорость на нормальную
if and // условие с выполнением всех подусловий (проверок)
player.Defined($PLAYER_CHAR) // проверка(игрок существует), на всякий случай
not actor.Driving($PLAYER_ACTOR) // проверка(игрок не за рулём)
82D8: not actor $PLAYER_ACTOR currentweapon == 34 // у актёра в руках не снайперка
82D8: not actor $PLAYER_ACTOR currentweapon == 35 // у актёра в руках не базука(1)
82D8: not actor $PLAYER_ACTOR currentweapon == 36 // у актёра в руках не базука(2)
jf @Prosto // если чего-нибудь не выполнилось, то переходим на начало

:Prosto_2 // создаём второй label
wait 10 // ждём 10 мс, на всякий случай
if // обыкновенное условие
00E1: key_pressed 0 6 // проверка (нажата клавиша "Прицел")
jf @Prosto
// если это не правда, то перех. на начало, и там скорость становится обыкновенной
015D: set_gamespeed 0.25 // устанавливаем меньшую скорость игры
jump @Prosto_2 // и прыгаем в начало этого же label'a

wait 1000 - задержка выполнения потока на 1000 миллисекунд ( = 1 секунда )
thread 'Alex' - присваивает потоку имя (для удобства после декомпиляции),имя не может привышать 7 букв,пишется сразу после начала потока
end_thread - заканчивает поток
jump @"Туда надо перейти" - переводит выполнение скрипта на label с именем "Туда надо перейти"

Чтобы заставить к-л актёра выполнять к-л действия последовательно используем это выражение:

Copy to Clipboard
0615: define_action_sequences 15@ // начало последовательности
05D3: AS_actor -1 go_to 2494.4622 -1680.92 13.3385 speed 4 3000 ms
// действие послед-ти
05BC: AS_actor -1 jump 0 // действие послед-ти
0616: define_action_sequences_end 15@ // завершение последовательности
0618: assign_actor $Player_actor to_action_sequences 15@
// заставляет актёра $Player_actor делать действия послед-ти, заметьте, что в
//последовательности, действия  применяются к актёру с именем -1 !!!
061B: remove_references_to_action_sequences 15@
// удаляем сведения о последовательности

Пинцип: Актёр идёт к точке,когда он там, то он прыгает. Если бы мы написали это без последовательности, то актёр бы выполнил сразу последнее действие
Есть ещё такая замороченная вещь, как путь или scmpath, кто его как называет, это типа предыдущей последовательности, применяется, чтобы заставить актёра или машину пройтись/проехаться по точкам с заданными координатами. Вот то, что относится к путям:

07C0: load_path 706 - загружает путь, их очень много, сами видите

05D6: clear_scmpath - очищает временный путь, если он существует

05D7: add_point_to_scmpath 2470.1248 -1661.6222 13.3293 - добаваляет точку в путь

05D8: AS_assign_scmpath to_actor $Act flags 4 0 - заставляет актёра следовать по пути

05EB: assign_vehicle $Car to_path 706 - заставляет машину следовать по определённому пути

04E0: car $Car abandon_path_radius 30 - будет считаться, что машина на точке, если она в радиусе 30 от неё

0873: release_path 211 - удаляет путь из памяти

Вот вам пример, думаю, что поймёте:

Copy to Clipboard
create_thread @Test // создаём поток

:Test // начинаем поток
wait 2000 // ждём 2 сек
model.Load(#FAM1) // объявляем,нужную нам, модель
038B: load_requested_models // загружаем ранее обявленые модели

:Test2 // начинаем второй label этого потока
wait 0 // ждём 0 сек, если не напишем, то может вылетить
if // одиночное условие
model.Available(#FAM1) // проверка (модель нашего актёра уже загружена)
jf @Test2 // если проверка не выполнилась, то переходим в начало label'a
wait 3000 // ждём 3 сек.
actor.Create(50@,4,#fam1,2494.9099, -1682.17, 12.32)
 // создаём актёра перед домом CJ'я
05D6: clear_scmpath
 // очищаем путь, если создаёте новый, как сейчас, то писать необходимо
05D7: add_point_to_scmpath 2470.1248 -1661.6222 13.3293 // задаём точку(дом OG)
05D7: add_point_to_scmpath 2494.9099 -1682.17 12.32 // задаём точку (дом CJ'я)
05D7: add_point_to_scmpath 2470.1248 -1661.6222 13.3293 // задаём точку(дом OG)
05D8: AS_assign_scmpath to_actor 50@ flags 4 0 // и вот этой командой заставляем актёра
 // идти по точкам, которые мы написали.
end_thread // заканчиваем поток

06C8: toggle_riot 1 - очень интерестная команда, она включает мочилову в Лос-Сантосе, такую, как перед последней миссией: дома дымятся, пешеходы мочят всех подрят, тачки взрываются...

057E: make_radar_grey 1 - делает радар серым, т.е. на нём не видно ничего, кроме иконок.

0581: toggle_radar 1 - включает радар, если 0, то выключает.

0826: toggle_hud 1 - включает панель оружия, жизни... , если 0, то выключает.

075B: (unknown) 0 - увеличение радара (от 1 до 100)

0A1E: dump_screen 1 - делает скриншот

04FA: reset_interior_colors 1 - освежает интерьер с номером 1

07D0: $WEEKDAY = weekday - записывает в переменную рабочий день.

02D0: fire $Fire extinguished - проверка на потушенность определённого огня.

03DE: set_pedestrians_density_multiplier_to 0.0 - устанавливает частоту появмашин.

0425: $Var meters = $Var feet - переводит метры в шаги, а может даже не метры, а футы.

051E: $Radio = get_current_radio_station - записывает номер текущей радиостанции.

08DD: keep_stuff_after_wasted 0 - даёт возможность оставлять оружее после того, как игрока убили

08DE: keep_stuff_after_busted 0 - оставляет оружее после того, как Карла арестовали

08DF: override_restart_if_wasted_at -2570.5 1139.5 54.85 within_radius 1500.0 angle 160.0 - устанавливает точку появляения игрока, после того как его убили в опред. месте.

08E0: override_restart_if_busted_at -1379.843 2635.74 54.4315 within_radius 1500.0 angle 170.6 - устанавливает точку появления игрока после того, как его арестовали в опред. месте.


Создание миссии. Часть 1
Думаю, многие из вас хотели бы создать свои миссии. В голове куча идей, но как это реализовать? В данном цикле статей мы, шаг за шагом, попробуем написать новую миссию.

Но, прежде чем начать, необходимо выяснить ряд отдельных моментов. Не имеет смысла писать скрипты, если вы не понимаете логики их работы. Поэтому сначала разберемся, как же собственно они работают. Сразу отмечу, что скрипты мы будем разбирать и писать на основе файла stripped.txt, который поставляется вместе с Sanny Builder. Ищите его в папке {SB}\Data\SA.

Теперь откройте данный файл и внимательно посмотрите на его содержимое.

В самом верху вы увидите несколько строк, начинающихся со слова DEFINE

DEFINE OBJECTS 0
DEFINE MISSIONS 0
DEFINE EXTERNAL_SCRIPTS -1 // Use -1 to not write AAA script
DEFINE UNKNOWN_EMPTY_SEGMENT 0
DEFINE UNKNOWN_THREADS_MEMORY 0

Это так называемый заголовок файла Main.SCM. Значения этих элементов напрямую отражают его структуру и содержимое отдельных сегментов. К описанию полей заголовка мы перейдем немного позже.
Ниже заголовка вы увидите несколько закомментированных строк. Напомню, что они игнорируются компилятором, не играют никакой роли и необходимы лишь для ориентации в скриптах.

// --------------------
// THE STRIPPED MAIN THREAD
// contains initial info
// --------------------
thread 'MAIN'
var
$PLAYER_CHAR: Player
end // var
01F0: set_max_wanted_level_to 6
set_wb_check_to 0

Сразу после комментариев следуют первые скриптовые команды. Именно с этих строк и начинается игра. Т.е. при запуске, когда игра подгружает файл main.scm, движок игры начинает последовательно, строка за строкой выполнять скриптовые команды.
Текущую активную команду потока, которая выполняется в данный момент, я бы назвал позицией невидимого курсора в данном потоке, по аналогии с текстовым редактором.
После загрузки заголовка, первой командой, которую он выполнит, будет thread 'MAIN'. И далее игра будет проходить все строки по порядку. Исключением станет ситуация, когда игра встретит переход (условный или безусловный). Например:

$var = 0
jump @label
$var += 1

:label
$var -= 1

Допустим, выполнение скриптов привело игру к команде $var = 0. Следующей командой будет jump @label, а это значит, что игра пропустит все последующие строки и перейдет сразу на метку @label. Это называется безусловный переход. Таким образом, после этого игра выполнит команду $var -= 1. Значение переменной $var станет -1.
Существуют еще другие виды переходов, о них мы будет говорить отдельно. Сейчас важно понять логику работы скриптов.

Вы можете задать вопрос, а как в игре работают сразу множество отдельных игровых блоков: одновременно работают парикмахерские, залы, можно запустить несколько разных миссий и т.д? Неужели игра обрабатывает эти скрипты последовательно друг за другом? Конечно же нет. Такая многозадачность обеспечивается тем, что движок игры способен выполнять параллельно несколько одновременно запущенных потоков (см. Вопрос #17 в MB FAQ). При этом каждый из этих потоков будет выполняться независимо от других. Значения локальных переменных одного потока будут недоступны в другом.

Потоки можно сравнить с двумя (тремя..) одновременно запущенными проигрывателями. Представьте, что у вас запущено два WinAmp'а, в каждом из которых играет песня. Песни в данном случае играются параллельно, независимо друг от друга. Так же работают и потоки.
Потоки запускаются командой create_thread. Это еще один вид безусловного перехода. Однако его отличие от jump состоит в том, что игра продолжает выполнять последующие команды. Поэтому довольно часто встречается такая ошибка:

create_thread @CreateCar

:CreateCar
<создаем машину>
end_thread

После того как игра создала поток CreateCar, появится еще один невидимый "курсор", установленный на позицию метки CreateCar. При этом первый поток будет продолжать последовательно выполняться (потоки же работают параллельно). Получится такая ситуация, когда на одну и ту же команду придут два потока одновременно. В данном примере дважды будет выполняться блок создания машины. Вот почему часто встречаются сообщения неопытных скриптеров о проблеме двух создаваемых актеров, машин.
Чтобы не допустить такой ситуации, достаточно вставить безусловный переход на метку, которая будет лежать за пределами нового потока:

create_thread @CreateCar
jump @SkipThread

:CreateCar
<создаем машину>
end_thread

:SkipThread

Если первый поток вам больше не нужен, его можно совсем завершить:

create_thread @CreateCar
end_thread

:CreateCar
<создаем машину>
end_thread

Команда end_thread моментально останавливает выполнение потока. Игра забывает позицию "курсора" в этом потоке. Однако если он вам понадобится, можно заново запустить его:

:Thread_1
create_thread @CreateCar
end_thread

:CreateCar
<создаем машину>
wait 10000
create_thread @Thread_1
end_thread

Надеюсь, вы понимаете логику работы данного скрипта. Игра пришла на метку Thread_1 и выполнила команду create_thread @CreateCar. Теперь в памяти игры будет два одновременно работающих потока (Thread_1 и CreateCar).
Первый после это завершится командой end_thread, а второй продолжит работу. В нем будет создана машина, после чего игра выполнит команду wait 10000. После задержки в 10 секунд, игра опять создаст новый (старый :)) поток Thread_1, а второй поток завершится.
Таким образом в игре каждые 10 секунд будет создаваться машина.
Потоки можно создавать не только с первой метки. Иногда существует необходимость запуска с определенной позиции:

...
:Thread_1
end_thread

:CreateCar
<создаем машину>

:CreateActor
<создаем актера>

jump @Thread_1
...

...
create_thread @CreateCar

...
create_thread @CreateActor

Когда игра придет на команду end_thread, она завершит какой-то вышележащий поток. Машина и актер, естественно, создаваться не будут. Однако мы может создавать их запуском "субпотока". После create_thread @CreateCar игра создаст и машину и актера. Сам поток после перехода завершится.
Почему? - спросите вы, - ведь команда завершения лежит за пределами потока (выше). После перехода jump @Thread_1 позиция "курсора" (т.е. текущая выполняемая команда в потоке) переместится на команду end_thread. Игра завершит именно тот поток, который дошел сюда. Это означает, что в скриптах может быть всего одна-единственная команда end_thread. Остальные потоки могут заканчиваться переходом на нее.
Запуском "субпотока" @CreateActor можно добиться того, что будет создан только актер, без машины.

Итак, вернемся к нашему файлу. Как видите, в нем нет команд create_thread. Значит будет запущен только один поток, автоматически создаваемый в начале новой игры. В конце файла вы увидите команду завершения. Это значит, что после нее в игре не будет запущено вообще ни одного потока, т.е. выполнение файла main.scm прекратится. Такое в принципе позволительно для урезанного майна.

Говоря о запущенных потоках, стоит сказать, что их текущее состояние запоминается после сохранения. Т.е. при загрузке старой игры, все потоки продолжат выполнение с того момента, где они были в момент сохранения. А это значит, что первые команды майна (thread 'MAIN' и далее) выполняются лишь единожды, при запуске новой игры. Именно поэтому в начале помещаются все одноразовые действия, такие как создание игрока, указание стартовых значений переменных и т.п. После этого первый поток либо переходит в бесконечный цикл (например проверка текущего процента прохождения), либо завершается (как в указанном файле).

Между командами thread 'MAIN' и end_thread в stripped.txt написаны опкоды, смысл которых, думаю, должен быть вам ясен. Их назначение состоит в том, чтобы создать в игре жизненно необходимые объекты и установить важные стартовые значения.

Таково поле наших будущих действий. В следующей статье мы рассмотрим понятие триггера и макета миссии.


Создание миссии. Часть 2
[продолжение. начало читайте здесь ]

Для запуска миссии требуется особый блок кода, именуемый триггером. По своей сути это набор различных условий, который должны выполняться для того, чтобы миссия началась. В оригинальной игре такими условиями чаще всего являются нахождение игрока в определенном месте (там обычно создается маркер), управление определенным типом машины (скорая, пожарка), а также ряд общих условий (проверка состояния игрока).

Триггер представляет собой отдельный поток, активируемый либо после прохождения определенной миссии, либо в начале новой игры.

Для начала необходимо объявить миссию в заголовке файла. Перейдите на строку DEFINE MISSIONS 0 и измените число на 1. После этого на следующей строке напишите:

DEFINE MISSION 0 at @MyMission

Теперь заголовок файла выглядит как

DEFINE OBJECTS 0
DEFINE MISSIONS 1
DEFINE MISSION 0 at @MyMission
DEFINE EXTERNAL_SCRIPTS -1 // Use -1 to not write AAA script
DEFINE UNKNOWN_EMPTY_SEGMENT 0
DEFINE UNKNOWN_THREADS_MEMORY 0

Теперь добавим триггер. Найдите в файле комментарий // put your mission mods here и вставьте после него следующий код:

:MyTrigger

thread "MyTrigger"
$TrigMarker = Marker.CreateIconAndSphere(15, 2489.0591, -1682.2808, 13.3358)
while $MyMission_Passed == 0
wait 250
if Player.Defined($PLAYER_CHAR)
  then
    if $ONMISSION == 0 // integer values
     then
       if 00FF: actor $PLAYER_ACTOR 0 2489.0591 -1682.2808 13.3358 radius 1.0 1.0 2.0
        then
          if Player.Controllable($PLAYER_CHAR)
           then
          $ONMISSION = 1 // integer values
          00BA: text_styled 'INTRO_1' 1000 ms 2 // Big Smoke
          Marker.Disable($TrigMarker)
          start_mission MyMission
          end // if1
       end // if2
     end // if3
  end // if4
end// while
end_thread

Это и есть наш триггер, который запустит миссию.
Как видите в начале создается маркер (рядом с домом CJ'я). После этого запускается цикл While, который проверяет специальную переменную $MyMission_Passed. Она обозначает статус прохождения миссии: когда миссия будет пройдена, мы установим переменную равной 1, цикл перестанет работать и выполнится команда end_thread. Работа триггера будет окончена.
В теле цикла мы последовательно проверяем 4 условия:
1. Игрок должен быть активен (не пойманным, не утонувшим).
2. Не должна быть запущена другая миссия. За это отвечает переменная $ONMISSION. Когда запускается миссия, она становится равной 1, и другие миссии быть запущены не могут.
3. Игрок должен находиться в определенном месте (где мы создали маркер).
4. Игрок должен быть управляемым.

Если все эти условия выполняются, то мы
1. Устанавливаем флаг миссии ($ONMISSION = 1)
2. Выводим текст. Здесь может быть любое значение.
3. Отключаем маркер.
4. Начинаем миссию (start_mission MyMission). Здесь можно написать start_mission 0. Эти варианты равнозначны.

Естественно, что вы можете добавлять свои условия. Например можно сделать проверку, чтобы у игрока было больше 1000 долларов на счету. Для этого нужно добавить следующие строки:

if Player.Defined($PLAYER_CHAR)
  then
    if $ONMISSION == 0 // integer values
     then
       if 00FF: actor $PLAYER_ACTOR 0 2489.0591 -1682.2808 13.3358 radius 1.0 1.0 2.0
        then
          if Player.Controllable($PLAYER_CHAR)
           then
             if Player.Money($PLAYER_CHAR) > 1000
              then
              $ONMISSION = 1 // integer values
              00BA: text_styled 'INTRO_1' 1000 ms 2 // Big Smoke
              Marker.Disable($TrigMarker)
              start_mission MyMission
            end
        end // if1
      end // if2
   end // if3
end // if4

Чтобы триггер заработал, нужно добавить команду create_thread. Найдите комментарий // put your create_thread commands here и вставьте после него строку

create_thread @MyTrigger

Теперь файл stripped.txt должен выглядеть так

DEFINE OBJECTS 0
DEFINE MISSIONS 1
DEFINE MISSION 0 at @MyMission
DEFINE EXTERNAL_SCRIPTS -1 // Use -1 to not write AAA script
DEFINE UNKNOWN_EMPTY_SEGMENT 0
DEFINE UNKNOWN_THREADS_MEMORY 0

// --------------------
// THE STRIPPED MAIN THREAD
// contains initial info
// --------------------
thread 'Main'
var
$PLAYER_CHAR: Player
end // var
01F0: set_max_wanted_level_to 6
set_wb_check_to 0
00C0: set_current_time 8 0
04E4: unknown_refresh_game_renderer_at 2488.5601 -1666.84
Camera.SetAtPos(2488.5601, -1666.84, 13.38)
$PLAYER_CHAR = Player.Create(#NULL, 2488.5601, -1666.84, 13.38)
$PLAYER_ACTOR = Actor.EmulateFromPlayer($PLAYER_CHAR)
Camera.SetBehindPlayer
set_weather 0
wait 0 ms
$PLAYER_CHAR.SetClothes("PLAYER_FACE", "HEAD", Head)
$PLAYER_CHAR.SetClothes("JEANSDENIM", "JEANS", Legs)
$PLAYER_CHAR.SetClothes("SNEAKERBINCBLK", "SNEAKER", Shoes)
$PLAYER_CHAR.SetClothes("VEST", "VEST", Torso)
$PLAYER_CHAR.Build
$PLAYER_CHAR.CanMove = True
fade 1 (out) 0 ms
select_interior 0
0629: change_stat 181 (islands unlocked) to 4
016C: restart_if_wasted at 2027.77 -1420.52 15.99 angle 137.0 unknown 0
016D: restart_if_busted at 1550.68 -1675.49 14.51 angle 90.0 unknown 0
// put your create_thread commands here

create_thread @MyTrigger
end_thread

// put your mission mods here

:MyTrigger
thread "MyTrigger"
$TrigMarker = Marker.CreateIconAndSphere(15, 2489.0591, -1682.2808, 13.3358)
while $MyMission_Passed == 0
wait 250
if Player.Defined($PLAYER_CHAR)
  then
    if $ONMISSION == 0 // integer values
     then
       if 00FF: actor $PLAYER_ACTOR 0 2489.0591 -1682.2808 13.3358 radius 1.0 1.0 2.0
        then
          if Player.Controllable($PLAYER_CHAR)
           then
        $ONMISSION = 1 // integer values
        00BA: text_styled 'INTRO_1' 1000 ms 2 // Big Smoke
        Marker.Disable($TrigMarker)
           start_mission MyMission
          end // if1
       end // if2
    end // if3
  end // if4
end // while
end_thread

Теперь добавим саму миссию. Любая миссия (за отдельными исключениями) имеет определенную структуру. У нее есть блок запуска, блок успешного прохождения, блок провала и блок очистки. Заголовок миссии выглядит так:

thread "MyMission"
gosub @MissionStart
if
wasted_or_busted
then
gosub @MissionFailed
end
gosub @MissionCleanup
end_thread

Как видите, само тело миссии (после метки MissionStart) представляет собой gosub. Поэтому в конце миссии обязательно нужно вставить return, а не end_thread. Блок MissionFailed срабатывает, когда игрок умирает или его ловят. MissionCleanup выполняется всегда в конце миссии, независимо от ее успешности.
Добавим макет миссии в нашу заготовку

:MyMission
thread "MyMission"
gosub @MissionStart
if
wasted_or_busted
then
gosub @MissionFailed
end
gosub @MissionCleanup
end_thread

:MissionStart
<тело миссии>
return

:MissionFailed
00BA: text_styled 'M_FAIL' 5000 ms 1 // ~r~MISSION FAILED!
return

:MissionCleanup
$ONMISSION = 0 // integer values
mission_cleanup
return

Это уже полностью рабочая миссия, которая правда только запускается и сразу же заканчивается, поскольку ее тело состоит из одно команды return.
Давайте добавим блок успешного выполнения миссии. Для этого после строки MissionStart добавьте команду

gosub @MissionPassed

а после слова return следующий код:

:MissionPassed
01E3: text_1number_styled 'M_PASSD' 0 5000 ms 1 // MISSION PASSED!
$MyMission_Passed = 1
return

теперь миссия выглядит так

:MyMission
thread "MyMission"
gosub @MissionStart
if
wasted_or_busted
then
gosub @MissionFailed
end
gosub @MissionCleanup
end_thread

:MissionStart
gosub @MissionPassed
return

:MissionPassed
01E3: text_1number_styled 'M_PASSD' 0 5000 ms 1 // MISSION PASSED!
$MyMission_Passed = 1
return

:MissionFailed
00BA: text_styled 'M_FAIL' 5000 ms 1 // ~r~MISSION FAILED!
return

:MissionCleanup
$ONMISSION = 0 // integer values
mission_cleanup
return

Скомпилируйте файл (F7), начните новую игру. Можете проверить новую миссию на работоспособность.
Казалось бы все хорошо, но нашему коду не хватает еще одной важной детали. Для того чтобы игра могла корректно завершать миссию в случае смерти игрока, одной переменной $ONMISSION недостаточно. Нужно связать эту переменную с флагом состояния миссии, чтобы игра поняла, что от изменения именно этой переменной зависит запуск миссий. Это делается командой

0180: set_on_mission_flag_to $ONMISSION

Вставьте ее в начале файла, перед командой create_thread. Теперь игра будет корректно завершать миссию в случае провала.

Смотрите пример первой миссии здесь.


Создание миссии. Часть 3
[продолжение. начало читайте здесь ]

Ну что ж пришло время подробно рассмотреть устройство кода миссии.
Код миссии состоит из 4 блоков:
1. блок запуска
2. блок успешного прохождения
3. блок провала
4. блок завершения миссии

Блок запуска выглядит следующим образом:

:MISSION
thread 'MISSION'
gosub @MissionStart
if
wasted_or_busted
jf @MissionCleanup
gosub @MissionFailed

Командой thread 'MISSION' - даем имя нашему потоку, о полезности этого действия рассказывать не буду, это отдельная тема. Командой gosub @MissionStart мы и осуществляем переход к коду самой миссии, с последующим возвратом на следующую после gosub стоку. О работе gosub и вариантах переходов смотрите здесь.

Итак

gosub @MissionStart

. . . .

:MissionStart
< тело миссии>
return //– возвращаемся на следующую после gosub @MissionStart строку.

Сам return может быть как из блока успешного прохождения, так и из блока провала.

Блок успешного прохождения

Этот блок выполняется тогда, когда задание миссии выполнено.
Обычно в этом блоке выводится надпись об успешном прохождении миссии, увеличивают количество денег и т.д. Самый простой вариант выглядит так:

:MissionPassed
01E3: text_1number_styled 'M_PASSD' 0 5000 ms 1 // MISSION PASSED!
// выводим надпись об успешном прохождении миссии
0394: play_music 1 // проигрываем музыку
return // возвращаемся на следующую после gosub @MissionStart строку

Блок провала

Если же поставленное задание в миссии не выполнено, то в этом случае и применяется блок провала. А также этот блок выполняется в случае смерти или ареста игрока.

:MissionFailed
00BA: text_styled 'M_FAIL' 5000 ms 1 // ~r~MISSION FAILED!
// выводим надпись о провале миссии
create_thread @START
// запускаем стартер нашей миссии
return // возвращаемся на следующую после gosub @MissionStart строку

Для того чтобы после провала миссии иметь возможность еще раз пройти нашу миссию необходимо в блок провала включить create_thread @START – запуск стартера миссии, при условии, что стартер у нас рассчитан на запуск одной миссии. При последовательном запуске миссий этого делать не нужно. О стартерах миссий смотреть здесь.

Итак, мы выяснили, что при любом варианте (провал или успешное прохождение) все равно возвращаемся на следующую после gosub @MissionStart строку. Где собственно проверяется, убит или арестован игрок

gosub @MissionStart
if
wasted_or_busted // убит или арестован
jf @MissionCleanup // если нет, то переходим на блок завершения миссии
gosub @MissionFailed
// если убит или арестован, то переходим на блок провала с возвратом на
// следующую после gosub @MissionFailed строку

Блок завершения миссии

:MissionCleanup
$ONMISSION = 0 // integer values
mission_cleanup
end_thread

Этот блок необходим для корректного завершения миссии.
Команда mission_cleanup высвобождает память от всего созданного на протяжении миссии, уничтожаем всех актеров, машины и пр.

У нас уже есть рабочая заготовка миссии, но самой миссии, как таковой нет. Напишем простенькую миссию, суть которой успеть доехать до указанного места.
Для начала создаем автомобиль и поместим игрока около этого авто.

:MissionStart
Model.Load(#BFINJECT)
038B: load_requested_models

:MissionStart_27
wait 0
if
Model.Available(#BFINJECT)
jf @MissionStart_27
01EB: set_traffic_density_multiplier_to 0.0
// отключаем трафик
03DE: set_pedestrians_density_multiplier_to 0.0
// убираем появление случайных актеров
Player.CanMove($PLAYER_CHAR) = False
// делаем игрока неподвижным
02A3: toggle_widescreen 1 // включаем широкий экран
$car = Car.Create(#BFINJECT, 2636.431, -1730.885, 10.7281)
Car.Angle($car) = 89.3845
Actor.PutAt($PLAYER_ACTOR, 2634.789, -1722.628, 10.8984)
Actor.Angle($PLAYER_ACTOR) = 179.9178
04E4: unknown_refresh_game_renderer_at 2634.789 -1722.628
//делаем прорисовку местности в указанных координатах
Camera.SetAtPos(2634.789, -1722.628, 11.8984)
// и устанавливаем камеру
Camera.SetBehindPlayer
wait 500
fade 1 500

Поскольку это миссия, то нам необходимо объяснить играющему цель миссии, то есть, то что нужно сделать чтобы ее пройти. Для этого выводим текст на экран, а чтобы во время показа текста нам не мешали ни случайный транспорт ни актеры, мы и отключаем их появление. Нужные нам тексты находятся в разных GXT таблицах поэтому приходится для того чтобы текст отображался на экране загружать разные таблицы для каждого предложения.

:MissionStart_37
wait 0
054C: use_GXT_table 'GARAGE1'
//загружаем таблицу 'GARAGE1'
00BC: show_text_highpriority GXT 'GAR1_22' time 3000 flag 1
wait 3000
03D5: remove_text 'GAR1_22'
054C: use_GXT_table 'BLOOD'
00BC: show_text_highpriority GXT 'BLOD_01' time 5000 flag 1
wait 5000
03D5: remove_text 'BLOD_01'
00BC: show_text_highpriority GXT 'BLOD_02' time 5000 flag 1
wait 5000
03D5: remove_text 'BLOD_02'
Player.CanMove($PLAYER_CHAR) = True
// игроком можно управлять
02A3: toggle_widescreen 0 //отключаем широкий экран

Теперь, когда показ текста закончен нам необходимо проверить находится ли игрок в автомобиле, а затем уже создавать checkpoint и запускать таймер.

:MissionStart_39
wait 0
if
  Actor.InCar($PLAYER_ACTOR, $car)
jf  @MissionStart_39
Car.LockInCurrentPosition($car)  = True
// Блокируем автомобиль
wait 2000
$TIME  = 20000 //миллисекунды
//установим лимит времени в 20 секунд
03C3:  set_timer_to $TIME type 1 GXT 'TIMER'
//будет обратный отсчет времени
06D5:  $r_checkpoint = create_racing_checkpoint_at 2192.036 -1732.899 13.0168  point_to 0.0 0.0 0.0 type 1 radius 6.0
018A:  $checkpoint = create_checkpoint_at 2192.036 -1732.899 13.0168
01EB:  set_traffic_density_multiplier_to 1.0
03DE:  set_pedestrians_density_multiplier_to 1.0
// включаем появление транспорта и пешеходов
Car.LockInCurrentPosition($car) = False

Итак таймер запущен, теперь необходимо проверить находится ли автомобиль в указанных координатах и не закончилось ли время.

:MissionStart_45
wait 0
if
  $TIME > 0
jf @MissionFailed //если время истекло, то миссия провалена
if
  0100:   actor $PLAYER_ACTOR in_sphere 2192.036  -1732.899 13.0168 radius 6.0 6.0 6.0 sphere 0 in_car
jf  @MissionStart_45
wait 50
Car.LockInCurrentPosition($car)  = True
014F:  stop_timer $TIME  // останавливаем таймер
//удаляем модель, маркер, racing_checkpoint
06D6:  disable_racing_checkpoint $r_checkpoint
Marker.Disable($checkpoint)
Model.Destroy(#BFINJECT)
Car.RemoveReferences($car)
//автомобиль переводим в разряд случайного транспорта
Car.LockInCurrentPosition($car)  = False
jump @MissionPassed

:MissionPassed
01E3:  show_text_1number_styled GXT 'M_PASSS' number 2000 time 5000 style 1
// MISSION PASSED!~n~~w~$~1~~n~~w~RESPECT +
0998:  add_respect 3 // увеличим респект
Player.Money($PLAYER_CHAR)  += 2000
// заплатим игроку за труды
0394:  play_music 1
return
// возвращаемся на следующую после gosub @MissionStart строку

:MissionFailed
00BA:  show_text_styled GXT 'M_FAIL' time 5000 style 1   // ~r~MISSION FAILED!
014F:  stop_timer $TIME
// останавливаем таймер
//удаляем модель, маркер, racing_checkpoint
06D6:  disable_racing_checkpoint $r_checkpoint
Marker.Disable($checkpoint)
Model.Destroy(#BFINJECT)
Car.RemoveReferences($car)
Car.LockInCurrentPosition($car)  = False
create_thread  @START

// запуск стартера миссии
return
// возвращаемся на следующую после gosub @MissionStart строку

Теперь у нас уже полноценная простенькая миссия, остается только скомпилировать файл и начать новую игру.
Пример миссии смотрите здесь.


Создание миссии. Часть 4
[продолжение. начало читайте здесь ]

Вы уже знаете как создавать миссии теперь пришло время научиться запускать эти миссии. В GTA по сути есть всего два способа запуска миссий:

  • Запуск миссии при старте новой игры
  • Запуск миссий из триггера.

В GTA SA миссии разделены на три категории:

  1. Технические миссии – это миссии не нуждаются в прохождении и чаще всего запускаются при старте новой игры. Простой пользователь даже не знает о их существовании. Например, миссии INITIAL и INITIL2 содержат в себе все или почти все сведения о пикапах, координатах маркеров, сфер, парковках авто и т.д.
  2. Сюжетные миссии – миссии имеющие отношение к определенному персонажу игры (SWEET, SMOKE, RYDER, и т.д.).
  3. Одиночные миссии – это чаще всего второстепенные (необязательные миссии), например, миссия игры на бильярде или так называемые подмиссии ( пожарного, медика и т.д.). Эти миссии могут запускаться бесконечное количество раз, в отличие от сюжетных миссий. Есть одиночные миссии, так сказать, одноразового использования, например, миссии «INTRO», «INTRO1», «INTRO2». Эти миссии являются обязательными для прохождения. Чаще всего прохождение этих миссий открывает возможность запуска следующего блока сюжетных миссий.

Запуск миссии при старте новой игры.

Обычно производится запуск «технических» миссий «INITIAL» и «INITIL2», а также миссии «INTRO», чаще всего, не требующих вмешательства в игровой процесс пользователя. То есть миссия «INTRO» - это своего рода видео ролик.
Запуск таких миссий производится из главного потока ('MAIN').

:MAIN_177

…

0417: start_mission INITIAL // Initial 1
0001: wait 0 ms
0417: start_mission INITIL2 // Initial 2

…

:MAIN_1969

…

0417: start_mission INTRO // Intro

Предположим у Вас есть миссия и желательно, чтобы она начиналась при старте новой игры, но Вас смущает наличие в этой миссии кода провала. Как быть в этом случае? Делаем, стартер миссии и запускаем его только в том случае, если миссия провалена.

Copy to Clipboard
:START
wait 0
1@ = Marker.CreateIconAndSphere(36, 2490.768, -1669.816, 13.3359) // создаем маркер

:START_1
wait 250
if and
   Player.Defined($PLAYER_CHAR)
0102:   actor $PLAYER_ACTOR in_sphere 2490.7 -1669.8 13.4 radius 2.0 2.0 1.0 sphere 1 stopped_on_foot
//проверяем находится ли игрок в данной точке
jf @START_1
Marker.Disable(1@) // удаляем маркер
start_mission FIRST //Старт миссии
end_thread  // закрываем поток

В код провала вставим create_thread @START

:FIRST_145
00BA: text_styled 'M_FAIL' 5000 ms 1 // ~r~MISSION FAILED!
create_thread @START
return

Пример:

Copy to Clipboard
{
  use macro (Ctrl+J) "headsa"
  to insert a file header
}
DEFINE MISSIONS 1 // общее количество миссий
DEFINE MISSION {ID} 0 AT {LABEL} @FIRST  // Ваша миссия

DEFINE EXTERNAL_SCRIPTS 0 // Use -1 in order not to compile AAA script
//DEFINE SCRIPT {NAME}  AT {LABEL} @
DEFINE UNKNOWN_EMPTY_SEGMENT 0
DEFINE UNKNOWN_THREADS_MEMORY 0

{$VERSION 3.0.0000}
thread 'MAIN'
 var
  $PLAYER_CHAR: Player
 end // var
01F0: set_max_wanted_level_to 6
set_wb_check_to 0
00C0: set_current_time 8 0
04E4: unknown_refresh_game_renderer_at 2488.5601 -1666.84
Camera.SetAtPos(2488.5601, -1666.84, 13.38)
$PLAYER_CHAR = Player.Create(#NULL, 2488.5601, -1666.84, 13.38)
$PLAYER_ACTOR = Actor.EmulateFromPlayer($PLAYER_CHAR)
07AF: $PLAYER_GROUP = player $PLAYER_CHAR group
Camera.SetBehindPlayer
set_weather 0
wait 0 ms
$PLAYER_CHAR.SetClothes("PLAYER_FACE", "HEAD", Head)
$PLAYER_CHAR.SetClothes("JEANSDENIM", "JEANS", Legs)
$PLAYER_CHAR.SetClothes("SNEAKERBINCBLK", "SNEAKER", Shoes)
$PLAYER_CHAR.SetClothes("VEST", "VEST", Torso)
$PLAYER_CHAR.Build
$PLAYER_CHAR.CanMove = True
select_interior 0
0629: change_stat 181 (islands unlocked) to 4
016C: restart_if_wasted at 2027.77 -1420.52 15.99 angle 137.0 for_town_number 0
016D: restart_if_busted at 1550.68 -1675.49 14.51 angle 90.0 for_town_number 0
0180: set_on_mission_flag_to $ONMISSION
// Note: your missions have to use the variable defined here ($ONMISSION)
03E6: remove_text_box
fade 0 500 ms

:MAIN_49
 if
   fading
 jf @MAIN_50
wait 0 ms
00BE: text_clear_all
03E6: remove_text_box
jump @MAIN_49

:MAIN_50
wait 0 ms
start_mission FIRST //Старт миссии
end_thread

// put your mods (threads) here

:START
wait 0
1@ = Marker.CreateIconAndSphere(36, 2490.768, -1669.816, 13.3359)

:START_1
wait 250
if and
Player.Defined($PLAYER_CHAR)
0102:   actor $PLAYER_ACTOR in_sphere 2490.7 -1669.8 13.4 radius 2.0 2.0 1.0
 sphere 1 stopped_on_foot
jf @START_1
Marker.Disable(1@)
start_mission FIRST //Старт миссии
end_thread

//-------------Mission 0---------------

:FIRST
thread 'FIRST'
gosub @FIRST_49  // переход к коду миссии с возвратом на следующую строку
if
wasted_or_busted  // убит или арестован
jf @FIRST_38
 // если условие не выполнено, то переходим на метку FIRST_38,
// т.е.  gosub @FIRST_145 игнорируется.
gosub @FIRST_145 // переход к коду провала с возвратом на следующую строку

:FIRST_38 // завершаем миссию
$ONMISSION = 0
mission_cleanup
end_thread

:FIRST_49
increment_mission_attempts
$ONMISSION = 1
  …
//----- Код миссии-----
  …

:FIRST_100
0318: set_latest_mission_passed 'FIRST'  // 1st
01E3: show_text_1number_styled GXT 'M_PASSS' number 200 time 5000 style 1
 // MISSION PASSED!~n~~w~$~1~~n~~w~RESPECT +
0998: add_respect 3
Player.Money($PLAYER_CHAR) += 200
Player.ClearWantedLevel($PLAYER_CHAR)
0394: play_music 1
return  // возвращаемся на следующую после gosub @FIRST_49 строку

:FIRST_145
00BA: text_styled 'M_FAIL' 5000 ms 1  // ~r~MISSION FAILED!
create_thread @START
return  // возвращаемся на следующую после gosub @FIRST_145 строку

Запуск миссий из триггера.

Такой вариант запуска применяется к сюжетным миссиям. Для этого варианта нам понадобится глобальная переменная в качестве «счетчика» миссий. Назовем ее например: $NEW_TOTAL_PASSED_MISSIONS и присвоим ей значение 0 ($NEW_TOTAL_PASSED_MISSIONS = 0). Запись этой переменной может быть произведена либо в главном потоке, а также в любом другом потоке или миссии, в котором будет вызываться стартер наших миссий.

В коде миссии в блоке удачного прохождения увеличиваем значение переменной на единицу ($NEW_TOTAL_PASSED_MISSIONS += 1), тем самым предотвращаем повторный запуск первой миссии.

:FIRST_100
0318: set_latest_mission_passed 'FIRST'  // 1st
01E3: show_text_1number_styled GXT 'M_PASSS' number 200 time 5000 style 1
// MISSION PASSED!~n~~w~$~1~~n~~w~RESPECT +
0998: add_respect 3
Player.Money($PLAYER_CHAR) += 200
Player.ClearWantedLevel($PLAYER_CHAR)
$NEW_TOTAL_PASSED_MISSIONS += 1
$Marker_Sweet_House = Marker.CreateIconAndSphere(52, 2468.632, -1650.888, 13.4716)
// создаем маркер для второй миссии
0394: play_music 1
return

А теперь напишем стартер для поочередного запуска нескольких миссий.

Copy to Clipboard
:STARTER
thread 'STARTER'
$Marker_Sweet_House = Marker.CreateIconAndSphere(16, 2498.228, -1647.457, 13.5479)
// создаем маркер первой миссии

:STARTER_11
wait 250
if
  $NEW_TOTAL_PASSED_MISSIONS == 2 // 2 – количество миссий
jf @STARTER_36  // если условие не выполнено то переходим на метку STARTER_36
end_thread  // закрываем поток

:STARTER_36 // блок запуска первой миссии
if
   Player.Defined($PLAYER_CHAR)
jf @STARTER_352
if
  $ONMISSION == 0 // не на миссии
jf @STARTER_352
if
   Player.Controllable($PLAYER_CHAR) //игроком можно управлять
jf @STARTER_352
if
  $NEW_TOTAL_PASSED_MISSIONS == 0
jf @STARTER_219 // если условие не выполнено
if
00FF:   actor $PLAYER_ACTOR sphere 0 in_sphere 2498.228 -1647.457 13.5479 radius 1.2
1.2 2.0 on_foot
 //проверяем находится ли игрок в данной точке
jf @STARTER_352
Marker.Disable($Marker_Sweet_House) // удаляем маркер
$ONMISSION = 1 // игрок находится на миссии
00BA: show_text_styled GXT 'SWEET_1' time 1000 style 2  // выводим название миссии
fade 0 500

:STARTER_187
if
fading
jf @STARTER_215
wait 0
00BE: text_clear_all  // убираем весь текст
03E6: remove_text_box
jump @STARTER_187

:STARTER_215
start_mission FIRST // запускаем первую миссию

:STARTER_219 // блок запуска второй миссии
if
  $NEW_TOTAL_PASSED_MISSIONS == 1
jf @STARTER_352
if
00FF:   actor $PLAYER_ACTOR sphere 0 in_sphere 2468.632 -1650.888 13.4716 radius 1.2
1.2 2.0 on_foot
jf @STARTER_352
Marker.Disable($Marker_Sweet_House) // удаляем маркер
$ONMISSION = 1
00BA: show_text_styled GXT 'SWEET1B' time 1000 style 2  // Cleaning the Hood
fade 0 500

:STARTER_320
if
fading
jf @STARTER_348
wait 0
00BE: text_clear_all
03E6: remove_text_box
jump @STARTER_320

:STARTER_348
start_mission SECOND // запускаем вторую миссию

:STARTER_352
jump @STARTER_11 //возвращаемся на метку STARTER_11

И на последок, вызывать этот поток (create_thread @STARTER) можно как из главного потока, так и из любой предыдущей миссии.

Смотрите пример запуска миссий здесь.


Миссии

В этой главе, как Вы уже догадались, я расскажу о создании миссий. Не рассказать о создании гоночных тоже было бы не вежливо с моей стороны, поэтому и о них тоже тут, давайте начнём...

Чтобы создать миссию нам надо:
1) Находим строку " DEFINE MISSIONS " и к числу миссий прибавляем 1, т.е. всего у вас должно получиться число равное количеству миссий минус 1 .
2) Снизу идут строчки с командами объявления label'ов миссий, идём в их конец, и после последней строчки " DEFINE MISSION " добавляем " DEFINE MISSION № @1LabelMissii " .
3) Создаём поток(thread) с любым именем, для удобства давайте возьмём " Mission1Start "
4) Ищем строчку " //-------------Mission 0--------------- " и перед ней пишем наш поток, в потоке должны находиться те или иные проверки, которые приведут к началу миссии, естественно это обыкновенный поток и в него можно всунуть что угодно, ну лично я создаю в нём только маркер, и если игрок на нём останавливается, то маркер убираем и начинаем миссию.
Вот например:

Copy to Clipboard
:Mission1Start
wait 0
if
player.defined($PLAYER_CHAR)
Jf @Mission1Start
wait 3000
Marker.CreateIconAndSphere($Name , $Icon_Number , $X, $Y, $Z )
// номера иконок в гл "Маркеры..."

:Mission1Start_2
wait 0
if and
0101: actor $PLAYER_ACTOR stopped_near_point $X $Y $Z radius 3.0 3.0 3.0 sphere 1
not wasted_or_busted
Jf @Mission1Start _2
00BA: text_styled 'TextString' 1000 ms 2 // ну надо же текст вывести.
start_mission 1
end_thread

5) Так, поток создали, теперь остаётся написать миссию...
Вот основа любой миссии:

Copy to Clipboard
:MISSION1
gosub @KOD_MISSII
if
wasted_or_busted
Jf @PROPUSK_KODA
gosub @KOD_PROVALA

:PROPUSK_KODA
gosub @UDALENIE_KODA
end_thread

:KOD_MISSII
increment_mission_attempts
$ONMISSION = 1
0110: clear_player $PLAYER_CHAR wanted_level

//---------------------------- Тут пишется сама миссия --------------------

:UDACHNO // ------- Сюда надо делать переход(Jump), если миссия удалась ---
wait 0
01E3: text_1number_styled 'M_PASS' 25000 5000 ms 4
Player.Money($PLAYER_CHAR) += 25000
0110: clear_player $PLAYER_CHAR wanted_level
0394: play_music 1
gosub @PROPUSK_KODA
return

:KOD_PROVALA //--- Сюда надо делать переход(Jump), если миссия провалена --
00BA: text_styled 'M_FAIL' 5000 ms 1
$ONMISSION = 0
mission_cleanup
create_thread @Start
return

:UDALENIE_KODA
$ONMISSION = 0
mission_cleanup
return

Вот вам для примера моя небольшая миссия:

Вот это пока только поток запуска миссии:

Copy to Clipboard
:StartMissii1
wait 0
Marker.CreateIconAndSphere(1@,36, 2490.7676, -1669.8162, 13.3359)

:StartMissii1_2
wait 250
if and
Player.Defined($PLAYER_CHAR)
0102: actor $PLAYER_ACTOR stopped_near_point_on_foot 2490.7 -1669.8 13.4 radius 2.0 2.0 1.0 sphere 1
Jf @StartMissii1_2
Marker.Disable(1@)
start_mission 1
end_thread

А вот это уже сама миссия, смысл в том что появляются 3 балласа с М4 и пытаются вас снять:

Copy to Clipboard
:MIS1
gosub @KOD_MISSII
if
wasted_or_busted
Jf @PROPUSK_KODA
gosub @KOD_PROVALA

:PROPUSK_KODA
gosub @UDALENIE_KODA
end_thread

:KOD_MISSII
increment_mission_attempts
$ONMISSION = 1
0110: clear_player $PLAYER_CHAR wanted_level

:LabelMis1_1
wait 0
fade 0 500
model.Load(#BALLAS1)
model.Load(#BALLAS2)
model.Load(#BALLAS3)
model.Load(#M4)
038B: load_requested_models

:LabelMis1_2
wait 0
if and
model.Available(#BALLAS1)
model.Available(#BALLAS2)
model.Available(#BALLAS3)
model.Available(#M4)
Jf @LabelMis1_2
fade 1 500
actor.Create(1@,4,#BALLAS1,2517.8367, -1664.6057, 14.0369)
actor.Create(2@,4,#BALLAS2,2517.1902, -1667.9568, 14.028)
actor.Create(3@,4,#BALLAS3,2516.353, -1671.1974, 13.8478)
01B2: give_actor 1@ weapon 31 ammo 999999
01B2: give_actor 2@ weapon 31 ammo 999999
01B2: give_actor 3@ weapon 31 ammo 999999
wait 500
05E2: AS_actor 1@ kill_actor $PLAYER_ACTOR
05E2: AS_actor 2@ kill_actor $PLAYER_ACTOR
05E2: AS_actor 3@ kill_actor $PLAYER_ACTOR

:LabelMis1_3
wait 0
if
wasted_or_busted
jf @LabelMis1_4
jump @KOD_PROVALA

:LabelMis1_4
wait 0
if and
actor.Dead(1@)
actor.Dead(2@)
actor.Dead(3@)
jf @LabelMis1_3

:UDACHNO
 // ------- Сюда надо делать переход(Jump), если миссия удалась --------
wait 0
01E3: text_1number_styled 'M_PASS' 25000 5000 ms 4
Player.Money($PLAYER_CHAR) += 25000
0110: clear_player $PLAYER_CHAR wanted_level
0394: play_music 1
gosub @PROPUSK_KODA
return

:KOD_PROVALA
 // ------- Сюда надо делать переход(Jump), если миссия провалена --------
00BA: text_styled 'M_FAIL' 5000 ms 1
$ONMISSION = 0
mission_cleanup
model.destroy(#BALLAS1)
model.destroy(#BALLAS2)
model.destroy(#BALLAS3)
model.destroy(#M4)
create_thread @StartMissii1
return
:UDALENIE_KODA
$ONMISSION = 0
mission_cleanup
return

Сейчас я напишу пример простейшей гоночной миссии, будем использовать за стартовый поток тот же, что и в предыдущем примере , вот :

Copy to Clipboard
:StartMissii1
wait 0
Marker.CreateIconAndSphere(1@,36, 2490.7676, -1669.8162, 13.3359)

:StartMissii1_2
wait 250
if and
Player.Defined($PLAYER_CHAR)
0102: actor $PLAYER_ACTOR stopped_near_point_on_foot 2490.7 -1669.8 13.4 radius 2.0 2.0 1.0 sphere 1
Jf @StartMissii1_2
Marker.Disable(1@)
start_mission 1
end_thread

Вот миссия, в ней те же названия label'ов, что и в предыдущей, поэтому удалите или измените ту...
Смотрим :
Copy to Clipboard
:MIS1
gosub @KOD_MISSII
if
wasted_or_busted
Jf @PROPUSK_KODA
gosub @KOD_PROVALA

:PROPUSK_KODA
gosub @UDALENIE_KODA
end_thread
:KOD_MISSII
increment_mission_attempts
$ONMISSION = 1
0110: clear_player $PLAYER_CHAR wanted_level

:LabelMis1_1
wait 0
model.Load(#CHEETAH)
model.Load(#BALLAS1)
038B: load_requested_models

:LabelMis1_2
wait 0
if and
model.Available(#CHEETAH)
model.Available(#BALLAS1)
Jf @LabelMis1_2
car.Create(1@,#CHEETAH,2461.0037, -1657.0515, 13.3047)
car.Angle(1@) = 90.0
wait 100
0129: 2@ = create_actor 4 #BALLAS1 in_car 1@ driverseat
wait 500
marker.CreateIconAndSphere(3@,11,2461.0, -1661.7, 13.3047)

:LabelMis1_3
wait 0
if
0103: actor $PLAYER_ACTOR stopped_near_point_in_car 2461.0 -1661.7 13.3 radius 2.0
2.0 6.0 sphere 1 // все пишется одной строкой
Jf @LabelMis1_3
03C0: 4@ = actor $PLAYER_ACTOR car
car.LockInCurrentPosition(4@) = true
wait 2000
car.DriveTo(1@,2040.131, -1611.939, 13.3828)
car.SetMaxSpeed(1@,40.0)
car.LockInCurrentPosition(4@) = false
00AE: unknown_set_car 1@ to_ignore_traffic_lights 2
03BC: 5@ = create_sphere 2040.131 -1611.939 13.3828 5.0
marker.Disable(3@)

:LabelMis1_4
wait 0
if
0100: actor 2@ near_point_in_car 2040.131 -1611.939 13.3828 radius 6.0 6.0 6.0 sphere 1
jf @LabelMis1_5
jump @KOD_PROVALA

:LabelMis1_5
wait 0
if
0100: actor $PLAYER_ACTOR near_point_in_car 2040.131 -1611.939 13.3828 radius 6.0 6.0 6.0 sphere 1
jf @LabelMis1_4

:UDACHNO
 // ------- Сюда надо делать переход(Jump), если миссия удалась --------
wait 0
01E3: text_1number_styled 'M_PASS' 25000 5000 ms 4
Player.Money($PLAYER_CHAR) += 25000
0110: clear_player $PLAYER_CHAR wanted_level
0394: play_music 1
marker.Disable(5@)
actor.RemoveReferences(2@)
car.RemoveReferences(1@)
car.RemoveReferences(4@)
model.Destroy(#BALLAS1)
model.Destroy(#CHEETAH)
gosub @PROPUSK_KODA
return

:KOD_PROVALA
// ------- Сюда надо делать переход(Jump), если миссия провалена --------
00BA: text_styled 'M_FAIL' 5000 ms 1
$ONMISSION = 0
mission_cleanup
marker.Disable(5@)
actor.RemoveReferences(2@)
car.RemoveReferences(1@)
car.RemoveReferences(4@)
model.Destroy(#BALLAS1)
model.Destroy(#CHEETAH)
create_thread @RADIO
return

:UDALENIE_KODA
$ONMISSION = 0
mission_cleanup
return


External Script – что это такое и как с ним работать?

External Script – внешний скрипт используется только в GTA San Andreas. Он находится отдельно от main.scm, поэтому он и называется «внешний». Внешний скрипт является скомпилированным бинарным файлом, имеющим расширение .scm. В отличии от main.scm внешний скрипт не имеет заголовка. Вся информация о нем находится в заголовке main.scm.

DEFINE EXTERNAL_SCRIPTS 0 // Use -1 in order not to compile AAA script
//DEFINE SCRIPT {NAME} AT {LABEL} @

Внешние скрипты расположены в файле script.img в папке script (data/script). Максимальное количество внешних скриптов - 82. Максимальное количество внешних скриптов, которые могут использоваться одновременно равно 70.

Внешний скрипт, как и миссия нуждается в запуске, т.е. нужен стартер внешнего скрипта. Для примера будем использовать очищенный main.scm (stripped.txt). Найти его можно в папке SannyBuilder\data\sa.

Открываем stripped.txt в SannyBuilder’е и над комментарием

{
use macro (Ctrl+J) "headsa"
to insert a file header
}

или вместо него ставим курсор и нажимаем Ctrl+J. В появившемся списке выбираем "headsa" и нажимаем ENTER. Этой незатейливой операцией мы добавили в наш файл (stripped.txt) заголовок:

DEFINE MISSIONS 0
//DEFINE MISSION {ID} 0 AT {LABEL} @
DEFINE EXTERNAL_SCRIPTS 0 // Use -1 in order not to compile AAA script
//DEFINE SCRIPT {NAME} AT {LABEL} @
DEFINE UNKNOWN_EMPTY_SEGMENT 0
DEFINE UNKNOWN_THREADS_MEMORY 0

В строке DEFINE EXTERNAL_SCRIPTS записывается общее количество внешних скриптов. Изменим 0 на 1, то есть, указываем компилятору, что у нас будет добавлен 1 внешний скрипт.
Следующая строка
DEFINE SCRIPT {NAME} AT {LABEL} @
где NAME – имя внешнего скрипта, назовем его, например, MILITIA и чтобы не путаться с метками назовем ее также @MILITIA. Теперь заголовок у нас получился такой:

DEFINE MISSIONS 0
//DEFINE MISSION {ID} 0 AT {LABEL} @

DEFINE EXTERNAL_SCRIPTS 1 // Use -1 in order not to compile AAA script
DEFINE SCRIPT MILITIA AT @MILITIA // 0

DEFINE UNKNOWN_EMPTY_SEGMENT 0
DEFINE UNKNOWN_THREADS_MEMORY 0

Теперь нам нужно добавить сам внешний скрипт. Его можно написать самому, но в целях экономия времени воспользуемся стандартным. Это скрипт вышибалы (External script 39 (BOUNCER)). Я внес в него небольшие правки и переименовал в MILITIA. Добавим его в наш файл после строки
// put your external scripts here.
Сохраняем файл, компилируем и запускаем игру.

Ну что же половина дела сделано, осталось заставить его работать.

Тут нам понадобится стартер внешнего скрипта. Есть разные варианты запуска внешних скриптов. Рассмотрим усе. :)

Для начала нужно сказать, что существует возможность привязать внешний скрипт к нужному вам объекту. Делается это опкодом:
0929: init_external_script_trigger 7 (ARCADE) with_object_model #CJ_COIN_OP_3 priority 100 radius 4.0 type -1
привязываем к объекту #CJ_COIN_OP_3 (игровой автомат space monkey) внешний скрипт видео игры.
Или
0929: init_external_script_trigger 10 (GATES_SCRIPT) with_object_model #GATE_AUTOL priority 100 radius 80.0 type -1
тут, соответственно, к объекту #GATE_AUTOL (решётка левая) привязываем внешний скрипт открытия Ворот Аэропорта.

Так же можно привязать внешний скрипт к интерьеру:
07D3: 'HOUSE' = init_external_script_named_handle 23 (BURG_BRAINS)
или объявить название внешнего скрипта
0884: 'DANCER' = init_external_script_named_handle 52 (DANCER)
замечу, что принцип работы опкодов 07D3 и 0884 мне не известен, а так же не понятно работают они или нет.

Можно привязать внешний скрипт к модели актера
0928: init_external_script_trigger 19 (DEALER) with_actor_model #BMYDRUG priority 100
В оригинальном майне этот опкод идет в паре с
08E8: assign_external_script_handle 'DEALER' to_model #BMYDRUG

мне кажется, что опкод 08E8 привязывает модель актера #BMYDRUG к потоку с именем (названием) ' DEALER ' ( 03A4: name_thread ' DEALER ').

Ну что же для начала воспользуемся опкодом 0928.
Еще раз запустим игру. Подходим к барышне в светлой кепке и темной футболке с номером 31. Наносим ей удар в челюсть (хук справа :) ) и наблюдаем ее реакцию.

Теперь добавим к нашему майну в поток 'MAIN' над строкой end_thread такую запись:
0928: init_external_script_trigger 0 (MILITIA) with_actor_model #BFYST priority 100
08E8: assign_external_script_handle 'MILITIA' to_model #BFYST
компилируем и запускаем игру.
Подходим к барышне в светлой кепке и темной футболке с номером 31. Наносим ей удар в челюсть (хук справа :) ) и наблюдаем ее реакцию. Заметили, что ее реакция изменилась. Итак, наш внешний скрипт запущен и работает. Убедится в этом можно также и по наличию у данной барышни оружия (model #COLT45). Но стоит получить оду звезду розыска, как барышня будет атаковать игрока. А если игрок начнет стрелять (при наличии звез), то барышня будет атаковать игрока с применением оружия.
Немного поясню принцип работы опкода 0928.
Игра генерирует случайных актеров, опкодом 0928 мы указываем игре привязать к модели актера #BFYST наш внешний скрипт. Теперь при каждом создании случайного актера с моделью #BFYST игра применит к этому актеру внешний скрипт.
При таком запуске внешний скрипт будет работать всегда, вне зависимости от того на миссии игрок или нет. Для нашего случая это не смертельно, поскольку он у нас один. Но для оригинального майна существует лимит количества одновременно запущенных внешних скриптов, и превышать его не рекомендуется. Смотрите пример

Теперь пришло время рассмотреть вариант запуска внешнего скрипта при выполнении условия (условий). Для этого напишем стартер внешнего скрипта:

Copy to Clipboard
:STARTEX
03A4: name_thread 'STARTEX'
00D6: if  and
0038: $ONMISSION == 0 // не на  миссии
0256: player $PLAYER_CHAR defined
004D:  jump_if_false @STARTEX_120
0226: 0@ =  actor $PLAYER_ACTOR health
00D6: if
8039: not  0@ == 0
// если здоровье игрока равно 0 то идем на метку завершения  внешнего скрипта
004D:  jump_if_false @STARTEX_131
0926: $Script_Status = external_script_status 0 (MILITIA)
//определяем запущен внешний  скрипт или нет
00D6: if
0038: $Script_Status == 0// при 0 запускаем внешний скрипт
004D: jump_if_false @STARTEX_120
// если $Script_Status = 1,
// то соответственно  второй раз запускать скрипт не нужно
08A9:  load_external_script 0 (MILITIA)  // загружаем внешний скрипт
00D6: if
08AB: external_script 0 (MILITIA) loaded //проверяем загружен ли скрипт
004D:  jump_if_false @STARTEX_120
0913:  run_external_script 0 (MILITIA)  // запускаем внешний скрипт

:STARTEX_120
0001: wait 0 ms
0002: jump @STARTEX

:STARTEX_131
090F:  end_external_script 0 (MILITIA) // останавливаем работу скрипта
0001: wait 0 ms
0002: jump @STARTEX

ну что же стартер внешнего скрипта работает, но он не подходит нам, поскольку в нашем скрипте нет создания актера, а стало быть, наш внешний скрипт не работает полностью. Смотрите пример

Добавим в стартер создание актера актера

Copy to Clipboard
:STARTEX
03A4: name_thread 'STARTEX'
00D6: if  and
0038: $ONMISSION == 0
0256: player $PLAYER_CHAR defined
004D: jump_if_false @STARTEX_120
0226: 0@ =  actor $PLAYER_ACTOR health
00D6: if
8039: not  0@ == 0
004D: jump_if_false @STARTEX_131
0926: $Script_Status = external_script_status 0 (MILITIA)
00D6: if
0038: $Script_Status == 0
004D: jump_if_false @STARTEX_120
08A9: load_external_script 0 (MILITIA)
00D6: if
08AB: external_script 0 (MILITIA) loaded
004D: jump_if_false @STARTEX_120
04C4: store_coords_to 2@ 3@ 4@ from_actor $PLAYER_ACTOR with_offset 1.0 3.0 -0.9
009A: 1@ =  create_actor_pedtype 4  model #MALE01 at 2@ 3@ 4@
0913: run_external_script 0 (MILITIA) 1@

:STARTEX_120
0001: wait 0 ms
0002: jump @STARTEX

:STARTEX_131
090F: end_external_script 0 (MILITIA)
0002: jump @STARTEX

Опкодом 04C4: - записываем в переменные 2@ 3@ 4@ координаты относительно актера $PLAYER_ACTOR со смещением 1.0 3.0 -0.9.
Опкодом 009A: - создаем актера с в координатах 2@ 3@ 4@,
модели #MALE01 и #NULL не требуют предварительной загрузки.
0913: run_external_script 0 (MILITIA) 1@ - запускаем внешний скрипт с созданным нами актером. Это запуск внешнего скрипта с параметрами. Смотрите пример

Copy to Clipboard
:STARTEX
03A4: name_thread 'STARTEX'
00D6: if  and
0038: $ONMISSION == 0
0256: player $PLAYER_CHAR defined
004D: jump_if_false @STARTEX_159
0226: 0@ =  actor $PLAYER_ACTOR health
00D6: if
8039: not  0@ == 0
004D: jump_if_false @STARTEX_170
0926: $Script_Status = external_script_status 0 (MILITIA)
00D6: if
0038:  $Script_Status == 0
004D: jump_if_false @STARTEX_159
08A9: load_external_script 0 (MILITIA)
00D6: if
08AB: external_script 0 (MILITIA) loaded
004D: jump_if_false @STARTEX_159
0615: define_AS_pack_begin 5@
05DE: AS_actor -1 walk_around_ped_path
0616: define_AS_pack_end 5@
04C4: store_coords_to 2@ 3@ 4@ from_actor $PLAYER_ACTOR with_offset 1.0 3.0 -0.9
04C4: store_coords_to 7@ 8@ 9@ from_actor $PLAYER_ACTOR with_offset 1.0 -3.0 -0.9
061D: create_AS_origin_at 7@ 8@ 9@ Z_angle 60.0 unknown_angle 300.0 AS_pack 5@ handle_as 6@
0621: create_actor_pedtype 6 model #NULL at_AS_origin 6@ task 1502 handle_as 10@
009A: 1@ =  create_actor_pedtype 6 model #MALE01 at 2@ 3@ 4@
0913: run_external_script 0 (MILITIA) 1@
0913: run_external_script 0 (MILITIA) 10@

:STARTEX_159
0001: wait 0 ms
0002: jump @STARTEX

:STARTEX_170
090F: end_external_script 0 (MILITIA)
0001: wait 0 ms
0002: jump @STARTEX

Вот Вам второй вариант. Опкодом 061D: - записываем в переменную 6@ последовательность 5@ действий в точке 7@ 8@ 9@. Опкодом 0621: - в переменную 10@ записываем создание актера с типом 6 (полицейский), моделью #NULL с последовательностью действий 6@
Смотрите пример

Теперь рассмотрим запуск внешнего скрипта с различными параметрами.
Например для запуска GF_MEETING используется такая запись
0913: run_external_script 24 (GF_MEETING) $Girlfriend 10@ 11@ 12@ 13@
где соответственно:
$Girlfriend – актер
10@ - X
11@ - Y
12@ - Z
13@ - угол
а для запуска GF_SEX:
0913: run_external_script 26 (GF_SEX) $Girlfriend 1 3@ 10@ 11@ 12@ 13@
10@, 11@, 12@, 13@ - X, Y, Z, угол
3@ - интерьер
1 – пока не совсем понятно
или такой
0913: run_external_script 26 (GF_SEX) 40@ 41@ 0 2037.651 2723.871 9.8352 0.0702

Я долго не мог понять почему для разных скриптов порядок передачи параметров разный. В одних переменная актера стоит первой
0913: run_external_script 26 (GF_SEX) $Girlfriend 1 3@ 10@ 11@ 12@ 13@
а в других, переменная актера может быть в любом другом месте
0913: run_external_script 1 (PARACHUTE) -1 -10.0 10.0 -5.0 -2.0 10.0 12.0 1 70@
где
70@ - переменная актера.
Теперь могу сказать, что очередность параметров определяется во внешнем скрипте,
(СПАСИБО Seemann’у за помощь :))
Рассмотрим пример передачи параметров
Для этого напишем простейший внешний скрипт

Copy to Clipboard
:MILITIA
03A4:  name_thread 'MILITIA'

:MILITIA_1
009A: 4@ =  create_actor_pedtype 4 model 0@ at 1@ 2@ 3@

:MILITIA_2
wait 0
if
 8118: not  actor 4@ dead
jf @MILITIA_717
062E:  unknown_get_actor 4@ task 1506 status_store_to 5@ // ret 7 if not found
00D6: if
04A4: 5@ == 7 // @ == any
004D:  jump_if_false @MILITIA_2
05E2:  AS_actor 4@ kill_actor $PLAYER_ACTOR
jump @MILITIA_2

:MILITIA_717
01C2:  remove_references_to_actor 4@
004E: end_thread

и стартер внешнего скрипта

Copy to Clipboard
:STARTEX
03A4:  name_thread 'STARTEX'
00D6: if  and
0038: $ONMISSION == 0
0256: player $PLAYER_CHAR defined
004D: jump_if_false @STARTEX_159
0226: 10@ =  actor $PLAYER_ACTOR health
00D6: if
8039: not  10@ == 0
004D: jump_if_false @STARTEX_170
0926: $Script_Status = external_script_status 0 (MILITIA)
00D6: if
0038: $Script_Status == 0
004D: jump_if_false @STARTEX_159
08A9: load_external_script 0 (MILITIA)
00D6: if
08AB: external_script 0 (MILITIA) loaded
004D: jump_if_false @STARTEX_159
04C4: store_coords_to 1@ 2@ 3@ from_actor $PLAYER_ACTOR with_offset 1.0 3.0 -0.9
0913: run_external_script 0 (MILITIA) #MALE01 2482.72 -1658.6648 13.3372

:STARTEX_159
0001: wait 250 ms
0002: jump @STARTEX

:STARTEX_170
090F: end_external_script 0 (MILITIA)
0001: wait 0 ms
0002: jump @STARTEX

Очередность передачи зависит от очередности локальных переменных во внешнем скрипте.
Мы запускаем внешний скрипт с параметрами
0913: run_external_script 0 (MILITIA) #MALE01 2482.72 -1658.6648 13.3372
где
#MALE01 передается переменной 0@ во внешнем скрипте,
2482.72 - 1@
-1658.6648 - 2@
13.3372 - 3@

:MILITIA_1
009A: 4@ = create_actor_pedtype 4 model 0@ at 1@ 2@ 3@

Смотрите пример

Таким образом передавать можно до 34 параметров. 32 локальных переменных (0@ …31@) + 2 таймера (32@,33@).

Оригинальная игра в настоящий момент имеет 78 внешних скриптов.
Список внешних скриптов взят с http://www.gtamodding.com

Number | Name | Description
0 | PLAYER_PARACHUTE | Controls the player's parachute
1 | PARACHUTE | Controls the AI's parachute
2 | BCESAR2 | Smoke's money from Los Santos to San Fierro
3 | BCESAR3 | Smoke's yay from San Fierro to Los Santos
4 | SLOT_MACHINE | Slot machine
5 | ROULETTE | Roulette
6 | OTB_SCRIPT | Off track betting machine
7 | ARCADE | Arcade game mission checker (not the game itself)
8 | VENDING_MACHINE | Vending machines (both food and drinks)
9 | FOOD_VENDOR | Food vendors
10 | GATES_SCRIPT | Airport gates
11 | GYMBIKE | Bike
12 | GYMBENCH | Bench
13 | GYMTREAD | Treadmill
14 | GYMDUMB | Dumbell
15 | BASKETB | Basketball
16 | VIDPOK | Video poker machine
17 | BLACKJ | Blackjack
18 | WHEELO | Wheel of Fortune
19 | DEALER | Drug dealer
20 | HOME_BRAINS | Hobo's AI
21 | POOL_SCRIPT | Pool
22 | LOWR_CONT | Lowrider contest
23 | BURG_BRAINS | Burgulary's ped AI
24 | GF_MEETING | Girlfriend meeting
25 | GF_DATE | Girlfriend date
26 | GF_SEX | Girlfriend sex
27 | CASINO_AMBIENCE | Casino ambience
28 | BAR_AMBIENCE | Bar ambience
29 | FOODBRAINS | Restaurant's ped AI
30 | OTB_AMBIENCE | Off track betting ambience
31 | STRIP_AMBIENCE | Strip club ambience
32 | PLANES | Airline traveling
33 | TRAINS | Being a passenger in the train
34 | ZERO_AMBIENCE | Zero's RC Shop ambience
35 | DANCE | DDR
36 | SHOPKEEPER | Restuarant shopkeeper AI
37 | CUSTOMER_PANIC | Ped's panic AI
38 | BAR_STAFF | Bartender AI
39 | BOUNCER | Bouncer AI
40 | OTB_STAFF | OTB staff AI
41 | PCHAIR | Restaurant ped in chair AI
42 | PCUSTOM | Restaurant ped not in chair AI
43 | OTBWTCH | OTB ped AI
44 | OTBSLP | Ped betting OTB AI
45 | OTBTILL | Ped walking around OTB AI
46 | FBOOTHR | Ped eating food AI
47 | FBOOTHL | Ped eating food AI
48 | BARGUY | Barman AI
49 | PEDROUL | Roulette gamer AI
50 | PEDCARD | Card gamer AI
51 | PEDSLOT | Slot-machine gamer AI
52 | DANCER | Club dancer AI
53 | STRIPW | Strip dancing female
54 | STRIPM | Strip dancing male
55 | BROWSE | Inside police HQ cop browsing folder or locker
56 | COPSIT | Inside police HQ cop sitting
57 | COPLOOK | Inside police HQ cop looking at posters
58 | TICKET | Train ticket machine AI
59 | SHOPPER | Ped Binco AI
60 | AMMU | Ammunation
61 | TATTOO | Tatto
62 | BARBER | Barber
63 | WARDROBE | Player's wardrobe
64 | CLOTHES | Clothes
65 | JUNKFUD | Food selection
66 | CARMOD1 | Mod garage
67 | CRANE1 | San Fierro and Las Venturas construction site cranes
68 | CRANE2 | IE ship crane
69 | CRANE3 | Quarry crane
70 | CARPARK1 | Random car for carpark generators
71 | IMPOUND | Impound lots
72 | VALET | Valet
73 | PHOTO | Suicide photographer
74 | PRISONR | Prisoner AI
75 | CAMERA | Homie's camera holding AI
76 | DEBT | Casino debt
77 | HOTDOG | Hotdog van

Список внешних скриптов by spaceeinstein


External скрипты

Внешние скрипты

Эта тема ещё не полностью раскрыта, поэтому опишу, наверное, самую малую её часть.
"External" в переводе с английского означает "внешний". Внешние скрипты - это скрипты хранящиеся в файле "script.img", который лежит в одной папке с "Main.scm", но для нас это не важно, потому что любой билдер для Сан Андреаса поддерживает работу с внешними скриптами через "Main.scm", наверняка Вы встречали в коде Main'a к-л информацию о внешних скриптах, весь конец кода Main'a состоит из них, но про дописывание своих внешних скриптов потом. Сейчас я расскажу, как использовать уже готовые, или как я модифицировал некоторые из них:
Давайте начнём с самого первого внешнего скрипта - парашют для игрока:

ПАРАШУТ ДЛЯ ИГРОКА

Покопавшись немного в нём я переписал его так, что как бы CJ не падал с парашютом, ему ничего не будет, вот описание по установке:

1) Если вы не используете оригинальный Main.scm,то переходите ко второй части установки, а если используете оригинальный, то сначала находим label ":INTRO_7264", затем в нём находим строку с текстом "create_thread @A_TERM", и после нёё вставляем :

create_thread @MaxHealth

Затем находим строку с текстом --Mission 0-- и перед ней вставляем :

Copy to Clipboard
:MaxHealth
wait 1000
062A: change_stat 24 to 1000.0
wait 500
actor.Health($PLAYER_ACTOR)=1000
end_thread

Теперь переходите к третьей части установки.

2) Если максимальная жизнь игрока маленькая, как в самом начале, то создаём поток, там где и всегда, с именем MaxHealth, затем находим строку с текстом --Mission 0-- и перед ней вставляем:

Copy to Clipboard
:MaxHealth
wait 1000
062A: change_stat 24 to 1000.0
wait 500
actor.Health($PLAYER_ACTOR)=1000
end_thread

Если же максимальная жизнь большая, то переходим сразу к третьей части установки.

3) Находим label ":PLCHUTE_1231", затем в этом label'e находим строку с текстом "$1513 = 2" и заменяем эту строку на данное выражение:

Copy to Clipboard
$1513 = 3 // integer values
0812: unknown_action_sequence $PLAYER_ACTOR "FALL_SKYDIVE" "PED" 1.0 1 0 0 0 100
wait 0
actor.Health($PLAYER_ACTOR) = 1000
0992: set_player $PLAYER_CHAR weapons_scrollable 1
Model.Destroy(#PARACHUTE)
04EF: release_animation "PARACHUTE"
if
  model.Available(#GUN_PARA)
jf @PLCHUTE_A1
model.Destroy(#GUN_PARA)

:PLCHUTE_A1
wait 0
end_thread

4) Находим label ":PLCHUTE_2386" находим в нём строку "Actor.Angle($PLAYER_ACTOR) = 1@" и меняем её на данное выражение:

Copy to Clipboard
0812: unknown_action_sequence $PLAYER_ACTOR "FALL_SKYDIVE" "PED" 1.0 1 0 0 0 100
actor.Health($PLAYER_ACTOR) = 1000
0992: set_player $PLAYER_CHAR weapons_scrollable 1
Model.Destroy(#PARACHUTE)
04EF: release_animation "PARACHUTE"
if
  model.Available(#GUN_PARA)
jf @PLCHUTE_A2
model.Destroy(#GUN_PARA)

:PLCHUTE_A2
wait 0
end_thread

Теперь компилируем, запускаем игру и падаем сколько влезет !!!

ПАРАШУТ ДЛЯ АКТЁРОВ

Второй скрипт про парашют для актёров мало чем отличается от первого,вот только его можно прицеплять.
Чтобы прицепить скрипт к актёру, надо сначала его загрузить:

08A9: load_external_script 1 (PARACHUTE)
// весь список скриптов приведён в начале Main'a

После того, как мы загрузили скрипт, надо же ещё создать актёра, который будет его выполнять, чтобы актёр использовал скрипт нужна данная команда:

0913: run_external_script 1 -1 -5.0 10.0 -5.0 -1.0 5.25 6.75 1 $Act

1 - номер скрипта
-1 - что-то типа времени, если ставить 0, то вообще ничего не будет
-5.0 - скорость снижения актёра без парашюта, если (-) поменять на (+), то актёр полетит вверх
10.0 -5.0 - вот эти 2 параметра указывают на принадлежность раскрытого парашюта к игроку, если их выставить по 0.0, то актёр будет лететь, как если игрок летит с нераскрытым парашютом и мы жмём клавишу "Назад", предыдущий параметр скорости снижения уже не будет действовать, если парашют раскрыт
-1.0 - а будет действовать вот этот, который показывает скорость снижения актёра с раскрытым парашютом
5.25 - показывает на сколько сместится актёр, если парашют откроется
6.75 - это скорость смещения,поставьте 50(+) и увидите эффект ракеты !
1 - если 0, то актёр летит с нераскрытым парашютом, и все параметры должны быть выставлены соответственно:

0913: run_external_script 1 -1 0.0 0.0 0.0 0.0 0.0 0.0 0 $Act

Можно менять только первый 0.0 скорость смещения вниз/вверх,если 1,то у актёра парашют от- крыт,почитайте выше, а вообще - то этот параметр когда нужен, а когда нет.

$Act - имя актёра, который будет выполнять скрипт

Это очень непонятная команда, SB вообще пишет, что в ней 32 параметра должно быть, так что поймите сами, что абсолютно всего я не знаю.
Вот вам пример:

Copy to Clipboard
create_thread @ParaTest // создаём поток

:ParaTest // начинаем поток
wait 0 // ждём 0 мс, если не напишем, то может повиснуть
if // условие
player.Defined($PLAYER_CHAR) // проверка(игрок существует)
jf @ParaTest // если не существует, то прыгаем на начало
wait 3000 // ждём 3 сек
04C4: create_coordinate 1@ 2@ 3@ from_actor $PLAYER_ACTOR offset 0.0 0.0 1500.0
// создаём точку на большой высоте от игрока
0376: $Act  = create_random_actor 1@ 2@ 3@ // создаём в этой точке случайного актёра
actor.LockInCurrentPosition($Act ) = true // закрепляем актёра в данной позиции
08A9: load_external_script 1 // загружаем наш скрипт

:ParaTest_2 // создаём второй label
wait 0 // ждём 0 мс,если не напишем, то может повиснуть
if // условие
08AB: external_script 1 loaded // проверка(скрипт 1 уже загружен)
jf @ParaTest_2 // если ещё не загружен, то переходим на начало label'a
actor.LockInCurrentPosition($Act ) = false // делаем актёра не закреплённым
wait 400 // ждём немного
0913: run_external_script 1 -1 -59.0 0.0 0.0 0.0 0.0 0.0 0 $Act
// запускаем скрипт с параметрами, соответствующими просому полёту

02A3: toggle_widescreen 1 // включаем широкий экран

:ParaTest_3 // создаём третий label
wait 0 // ждём 0 мс, если не напишем, то может повиснуть
0819: 16@ = actor $Act distance_from_ground
// измеряем расстояние от актёра до земли
04C4: create_coordinate 4@ 5@ 6@ from_actor $Act offset 0.0 -2.0 10.0
// создаём координаты
camera.SetPosition(4@,5@,6@,0.0,0.0,0.0) // ставим по ним камеру
camera.OnPed($Act,15,2) // и направляем на актёра
if
16@ < 200.0 // проверка (если позиция актёра меньше,чем 200)
jf @ParaTest_3 // если проверка не выполнилась, т.е высота больше, чем 200,
//  то прыгаем к началу label'a
camera.Restore_WithJumpCut // восстанавливаем нормальную позицию камеры
02A3: toggle_widescreen 0 // выключаем широкий экран
actor.PutAt($Act,0.0,0.0,0.0) // помещаем актёра туда, откуда он больше не вернётся
actor.RemoveReferences($Act)// удаляем все сведения об актёре
end_thread // и завершаем поток

Ещё пример, но тут актёр уже летит на парашюте :

Комментировать небуду, потому что это практически тоже самое, что и предыдущий, скажу только, что основное отличие в строке 0913: run_external_script... Думаю, что сами разберётесь:

Copy to Clipboard
create_thread @ParaTest2

:ParaTest2
wait 0
player.Defined($PLAYER_CHAR)
jf @ParaTest
wait 3000
04C4: create_coordinate 1@ 2@ 3@ from_actor $PLAYER_ACTOR offset 0.0 0.0 150.0
0376: $Act = create_random_actor 1@ 2@ 3@
actor.LockInCurrentPosition($Act ) = true
08A9: load_external_script 1

:ParaTest2_2
wait 0
if
08AB: external_script 1 loaded
jf @ParaTest2_2
actor.LockInCurrentPosition($Act ) = false
wait 200
0913: run_external_script 1 -1 -5.0 10.0 -5.0 -1.0 5.25 6.75 1 $Act
actor.RemoveReferences($Act)
end_thread

И под конец скажу, что:
0913: run_external_script 1 -1 -59.0 0.0 0.0 0.0 0.0 0.0 0 $Act
// эту команду используйте, чтобы получить эффект парашюта, как в первом примере.
0913: run_external_script 1 -1 -5.0 10.0 -5.0 -1.0 5.25 6.75 1 $Act
// эту команду используйте, чтобы получить эффект парашюта, как во втором примере.

РАЗНЫЕ

Рассмоттрим скрипт "VENDING_MACHINE" про автомат напитков, тут интересные только 2 вещи:
узнаём стат наетости CJ'я, это стат под номером 245, команда блокировки клавиши:
07CC: player $PLAYER_CHAR disable_key_15 1
Но, увы, каким образом заставить эту команду работать, я не знаю, если вы узнаете как, то скажите пожалуйста мне.

Ну давайте изменим , хоть чуть-чуть, этот скрипт:

Ищем label с именем :VENDING_1210 , находим в нём строку с текстом 0623: add 5 to_stat 245 , число 5 изменяем на, допустим, 100, и там где написано $3396 += 30 ,меняем число 30 на 1000. Результат таков, что CJ будет пополнять своё здоровье по максимуму и сразу будет наедаться.

ДЕЙСТВИЯ НАД ВНЕШНИМИ СКРИПТАМИ

08E8: assign_external_script_handle 'DEALER' to_actor_model #BMYDRUG - данная команда заставляет всех актёров с моделью #BMYDRUG выполнять скрипт 'DEALER', скрипт торговца крэком.

Я хочу ещё добавить сюда про тюнинг машин, без добавления моделей в Define objects, но я в этом скрипте туплю, по поводу одежды, причёсок, татуировок всё написано в главе "Части тела игрока".


События актёров

События актёров применяются в скриптинге но редко, в большинстве случаев можно обойтись и без них.Принцип таков, что надо вычислить действие актёра, и исходя из этого действия сделать к-л вывод.

Насколько мне известно есть всего две команды работы с событиями актёров:
В переменную записывается текущее событие актёра:
080E: get_actor $PLAYER_ACTOR ped_event_to 1@

А вот и номера игровых событий актёров, я взял, то, что было в файле PedEvents.txt :

Выходит из машины или тяниться из неё 7
Удар от велосипеда или от падения 8
Повреждение актёра 9
Актёр помер 11
Перезарядка 12
Просто идёт,как прохожий 13
Актёр фотографирует 15
Актёр залез в тачку игрока 17
Проститутка 20
Актёра что-либо привлекает 27
Угроза столкновения с транспортным средством 30
Направленность прожектора на игрока 31
Актёр подпрыгивает 33
Актёр в ярости 36
Актёр в ярости и уже нападает 37
Типа предыдущих 38
Актёр уважает кого-либо 39
Машина актрёра повреждена оружеем 41
Специальный случай 42
Актёра сбил автомобиль 43
Актёр идёт с к-л целью 44
Актёр бежит,увидив огонь 46
Подготовка события для привлечения к нему актёра 48
Актра фотографируют 49
Неизвестно (низко) 50
Неизвестно (высоко)51
Здоровье актёра мало 52
Типа предыдущего 53
Актёр сел в автомобиль,как водитель 54
Актёр вылез из автомобиля с места водителя 55
Актёр едет в авто 56
Актёр вблизи огня 59
Актёр слышит громкий звук 61
Актёр слышит тихий звук 62
Актёр в ярости 63
Актёр паникует 65
Актёр как бы лидер группы 71
Актёр замечен полицейским 72
Машина актёра столкнулась с другой машиной 73
Актёру что-то угрожает 75
Актёру дана команда присоединиться у группе 76
Актёр убегает из транспортного средства, когда то загорается 79

Вот мой скрипт проверки событий игрока:

Copy to Clipboard
create_thread @PEVENT

:PEVENT
wait 5000

:PEVENT_2
wait 100
if
Player.Defined($PLAYER_CHAR)
jf @PEVENT_2
080E: get_actor $PLAYER_ACTOR ped_event_to $1
04F7: status_text $1 type 0 line 2 GXT 'NOTHING'
jump @PEVENT_2


Меняем игровую память через SCM (San Andreas)
1.
Всем известно, что San Andreas поддерживает массивы в SCM.
В общем виде массивы представлены так:

<array name>(<index name>,<size><type>)

Имя массива и индекса - это переменные, содержащие значения, которые определяют место начала массива (array name) и смещение от этого начала (или номер ячейки в массиве) на определенное число байтов (index name).

Так вот, например, $array($index,11i) будет указывать на определенную ячейку памяти, которая рассчитывается следующим образом:

берется имя (подробнее в разделе DMA) переменной $array, к ней прибавляется значение переменной $index, умноженное на размер одной ячейки.
Например, для типа i (integer) размер одной ячейки равен 4 байтам.

i,f : 4 байта
s : 8 байтов
v : 16 байтов

Таким образом, общая формула такова:

cA = aN + (iN * t)

cA адрес ячейки
aN $array
iN значение $index
t размер ячейки для данного типа

2.
Значение cA (адрес ячейки) - это смещение в main.scm относительно его начала. Все глобальные переменные и глобальные массивы хранятся в теле main.scm в блоке, который идет в самом начале файла (так называемый первый сегмент). Если вы откроете main.scm в хекс-редакторе, вы увидите, что в начале идет очень много нулей. Вот здесь потом и прописываются значения переменных.

Допустим, aN равно $8, iN равно 10, а тип массива Integer, т.е. t равно 4. Тогда cA равно 48. Тогда $array($index,11i) прочитает 4 байта из первого сегмента, начиная с 48-го байта от начала.

3.
DMA. DMA расшифровывается как Direct Memory Access (прямой доступ к памяти). Относительно скриптинга в GTA, речь идет об использовании прямого доступа к конкретной ячейке памяти. Реализуется эта технология путем указания числового имени для глобальной переменной. Например, $100 всегда указывает на сотую ячейку памяти (или четырехсотый байт, т.к. одна ячейка равна 4 байтам) относительно начала первого сегмента SCM.

А вот куда будет указывать $var (например), вы заранее знать не можете, т.к. память для переменных с текстовыми именами распределяется уже компилятором.
Правда здесь есть два исключения:
- Вы можете указать компилятору конкретную ячейку памяти для глобальной переменной командой Alloc.
- Переменные из файла CustomVariables.ini всегда имеют определенную ячейку.

Трансформируем наш пример в DMA:

$9 = 1
$10($9,11i)

$10 это имя массива, которое определяет его позицию в первом сегменте (40-й байт). $9 равно 1 поэтому cA = 40+1*4 = 44. $10($9,11i) читает и пишет значения в диапазоне [44..47] байты SCM.

Домашнее задание: докажите, что если $9 равно 0, то $10($9,11i) тоже самое что $10.

4.
aDMA. aDMA расшифровывается как Advanced DMA или продвинутый доступ к памяти.
Технология DMA имеет три ограничения:
- нельзя использовать имена $0 и $1, так как они выходят за пределы первого сегмента SCM.
- использование DMA-переменных влияет на размер первого сегмента, а значит и всего файла. Например, если вы используете в скрипте переменную $10000, то размер первого сегмента увеличится до катастрофического значения в ~ 40 килобайт, даже если у вас во всем файле лишь десяток переменных.
- DMA использует шаг в 4 байта, и вы не имеете доступа к адресам, которые не делятся нацело на 4. Например, вы не можете прочитать [11..14] байты, а только [8..11] - $2 или [12..15] - $3.

aDMA лишен этих недостатков. Вы можете использовать любые значения, кроме отрицательных. Реализуется aDMA через тип данных &. Используется шаг в один байт
Так, переменная &11 будет читать [11..14] байты, &9999999 – [9999999.. 1000002] и т.д.

&0 прочитает первые 4 байта SCM, которые равны 2147xxxxxx
Домашнее задание: проверьте это

Copy to Clipboard
054C: use_GXT_table 'POOL'
01E3: text_1number_styled 'NUM' &0 5000 ms 1 // ~1~

Самое важное, что aDMA не влияет на размер первого сегмента, и вы можете читать/менять значение за его пределами (например код второго сегмента - моделей).

Однако и DMA и aDMA ограничены в размере: максимальные значения для них равны $16383, &65536 соответственно. Поэтому доступный диапазон для таких переменных равен 65536.

5.
Возвращаемся к массивам. Как я уже говорил, для расчета конечной ячейки памяти к имени массива (оффсету) прибавляется содержимое индекса * 4. Теперь попробуем поразмыслить, ведь содержимое переменной не ограничено никакими лимитами (кроме естественно предела в 4,294,967,295 для всех 32-битных приложений, к коим относится и GTA). А значит теоретически мы может получить доступ к любой единице памяти игры.

Так и есть.

$index = 10 000 000
$10($index,1i) = 1

Этот код запишет 1 в cA = 40+10 000 000*4 = 40000040..3 байт.

Вроде все верно. Одна есть одна деталь: игровой движок рассчитывает конечный адрес cA, исходя из того, что адресация происходит внутри SCM, а значит это смещение будет не абсолютным, а относительным (от начала main.scm в памяти игры).

Так в чем проблема, спросите вы, нужно лишь учесть этот смещение и все. Да, так и есть.
Глобальный адрес main.scm в памяти игры равен: 0xA49960. Именно это значение прибавляется для получения адреса. Поэтому отняв его от значения iN и разделив число на 4 (смотри формулу) мы получим «магическое» значение iN, которое и будет потом, при обработке его игрой указывать на нужную нам ячейку.

Преобразуем формулу с учетом адреса SCM:

cA = 0xA49960 + aN + (iN * t)

Из нее легко видно, что нужно сделать чтобы cA был равен нужному нам адресу.
Есть последняя деталь. Чтобы не возиться с учетом aN, мы устанавливаем его равным 0. Делается это при помощи aDMA, о чем я писал выше.

Конечный код преобразования глобального адреса в «магическое» число:

Copy to Clipboard
:MemoryRead32
0@ -= 0xA49960
0@ /= 4
008B: 1@ = &0(0@,1i)
return

Эта функция возвращает в переменной 1@ значение памяти по адресу, переданному в 0@.

Например, есть адрес 0xB7CE50 – текущее количество денег игрока ( другие адреса )

Прочитаем сколько денег на счету у игрока:

Copy to Clipboard
…
0@ = 0xB7CE50
gosub @MemoryRead32
054C: use_GXT_table 'POOL'
01E3: text_1number_styled 'NUM' 1@ 5000 ms 1 // ~1~

...

:MemoryRead32
0@ -= 0xA49960
0@ /= 4
008B: 1@ = &0(0@,1i)
return

Код для записи в память разных значений вы можете прочитать в моем посте на GTAForums.com .

И напоследок.
Не все адреса одинаково полезны.. тьфу, доступны. При попытке изменить/прочитать некоторые из них вы можете получить ошибку с вылетом игры. Будьте осторожны.

См. также библиотека CLEO 3


Таблицы переходов.

Что же такое таблицы переходов? По моему это аналог массивов. Как и к массиву так и к таблице переходов обращение ведется по индексу. В качестве индекса у таблицы переходов выступает переменная, а правильнее сказать ее значение. Разберем принцип создания и работы таблицы переходов. Для создания таблицы переходов используется следующий опкод:

0871: init_jump_table $peremen total_jumps 7 0 @метка_выхода jumps 0 @метка1 1 @метка2 2 @метка3 3 @метка4 4 @метка5 5 @метка6 6 @метка7

total_jumps 7 – общее количество переходов, в нашем случае равно семи.
$peremen – переменная, по значению которой и будет осуществляться переход на определенную метку. Отсчет ведется с 0.
@метка_выхода – выход из таблицы.
jumps 0 @метка1 - 6 @метка7 – метки переходов, то есть те метки на которые будет осуществляться переход согласно значению переменной. Цифра 0 перед меткой @метка1 означает то, что если переменная $peremen = 0 то будет произведен переход на метку1 и т.д.

Максимальное количество переходов в строке не может превышать 7. Если же необходимо большее количество переходов, то в паре с опкодом 0871: используется еще и опкод 0872:

0871: init_jump_table $peremen total_jumps 8 0 @метка_выхода jumps 0 @метка1 1 @метка2 2 @метка3 3 @метка4 4 @метка5 5 @метка6 6 @метка7
0872: jump_table_jumps 7 @метка8 -1 @метка_выхода -1 @метка_выхода -1 @метка_выхода -1 @метка_выхода -1 @метка_выхода -1 @метка_выхода -1 @метка_выхода -1 @метка_выхода

Все отсутствующие переходы должны быть заполнены так -1 и метка выхода. В нашем случае это выглядит так -1 @метка_выхода. Так же они заполняются и в случае если переходов меньше 7.

Mаксимальное число меток для одной jump_table, созданной опкодами 0871 и 0872, равно 75.

Теперь посмотрим как же работает таблица переходов.

Copy to Clipboard
create_thread @JumpT

:JumpT
03A4: name_thread 'JumpT'
$CHECK=0

:JumpT_1
wait 0 ms
04C4: create_coordinate $X $Y $Z from_actor $PLAYER_ACTOR offset 1.0 3.0 0.0
 $Z -=1.1
gosub @Jump_table
actor.Create($Actor,7,$MODEL,$X, $Y, $Z)
actor.Health($Actor)= 1000
07FE: set_actor $Actor fighting_style_to 22@ 6
if
 $CHECK ==3
jf @JumpT_2
01B2: give_actor $Actor weapon 5 ammo 3000 // Load the weapon model before using this
:JumpT_2
05E2: actor $Actor kill_actor $PLAYER_ACTOR

:JumpT_3
wait 0 ms
if
actor.Dead($Actor)
jf @JumpT_3
wait 2000 ms
actor.DestroyInstantly($Actor)
$CHECK +=1

:JumpT_4
wait 0 ms
if
 4 > $CHECK
jf @JumpT_5
wait 1000 ms
jump @JumpT_1

:JumpT_5
model.Destroy(#VHMYELV)
model.Destroy(#VWMYBOX)
model.Destroy(#WMYCR)
model.Destroy(#OMYKARA)
model.Destroy(#BAT)
end_thread

:Jump_table
0871: init_jump_table $CHECK total_jumps 4 0 @EXIT_JT jumps 0 @JUMP_0 1 @JUMP_1 2 @JUMP_2 3 @JUMP_3 -1 @EXIT_JT -1 @EXIT_JT -1 @EXIT_JT

:JUMP_0
model.Load(#VHMYELV)
038B: load_requested_models

:JUMP_0_1
wait 0 ms
if
model.Available(#VHMYELV)
jf @JUMP_0_1
04AE:  $MODEL = 82
22@ = 5
jump @EXIT_JT

:JUMP_1
model.Load(#VWMYBOX)
038B: load_requested_models

:JUMP_1_1
wait 0 ms
if
model.Available(#VWMYBOX)
jf @JUMP_1_1
04AE:  $MODEL = 81
22@ = 6
jump @EXIT_JT

:JUMP_2
model.Load(#WMYCR)
038B: load_requested_models

:JUMP_2_1
wait 0 ms
if
model.Available(#WMYCR)
jf @JUMP_2_1
04AE:  $MODEL = 100
22@ = 7
jump @EXIT_JT

:JUMP_3
model.Load(#OMYKARA)
model.Load(#BAT)
038B: load_requested_models

:JUMP_3_1
wait 0 ms
if and
model.Available(#OMYKARA)
model.Available(#BAT)
jf @JUMP_3_1
04AE:  $MODEL = 203
22@ = 8
jump @EXIT_JT

:EXIT_JT
return

Принцип работы.

Переменная $CHECK=0
Командой gosub @Jump_table мы обращаемся к таблице переходов и сразу же производится переход на первую метку, т.е. :JUMP_0 , не забываем что отсчет ведется с 0.

Получаем данные, которые там находятся:

:JUMP_0
model.Load(#VHMYELV)
038B: load_requested_models

:JUMP_0_1
wait 0 ms
if
model.Available(#VHMYELV)
jf @JUMP_0_1
04AE: $MODEL = 82
22@ = 5
jump @EXIT_JT

и прыгаем на метку выхода.

:EXIT_JT
return

Далее возвращаемся на следующую строку после команды gosub @Jump_table.
Создаем актера, устанавливаем ему стиль борьбы и здоровье. Проверяем, равна ли переменная 3 и если равна то даем ему оружие, а в противном случае сразу идем на метку :JumpT_2 и даем команду актеру атаковать игрока. Делаем проверку умер ли актер и если умер то удаляем его, увеличиваем переменную на единицу $CHECK +=1, производим проверку 4 > $CHECK и если больше то идем на метку jump @JumpT_1. Теперь в таблице переходов будет выбрана метка @JUMP_1, поскольку $CHECK=1 и т.д.

Смотрите пример здесь.


Проверка нажатия клавиш

Вы можете проверять в скриптах нажатие абсолютно любой кнопки на клавиатуре (за исключением ESC и PrintScreen, их я не нашел, а также правый Wnd, которого нет на моей клавиатуре).

GTA SA 1.0 Key Codes
# | Index | Key Lo | Key Hi | #
0 | 304474 |  | Insert | 1
2 | 304475 | Delete | Home | 3
4 | 304476 | End | Page Up | 5
6 | 304477 | Page Down | Arrow Up | 7
8 | 304478 | Arrow Down | Arrow Left | 9
10 | 304479 | Arrow Right | Scroll Lock | 11
12 | 304480 | Pause | Numlock | 13
14 | 304481 | Num / | Num * | 15
16 | 304482 | Num - | Num + | 17
18 | 304483 | Num Enter | Num Del | 19
20 | 304484 | Num 1 | Num 2 | 21
22 | 304485 | Num 3 | Num 4 | 23
24 | 304486 | Num 5 | Num 6 | 25
26 | 304487 | Num 7 | Num 8 | 27
28 | 304488 | Num 9 | Num 0 | 29
30 | 304489 | Backspace | Tab | 31
32 | 304490 | Caps Lock | Enter | 33
34 | 304491 | Left Shift | Right Shift | 35
36 | 304492 |  | Left Ctrl | 37
38 | 304493 | Right Ctrl | Left Alt | 39
40 | 304494 | Right Alt | Left Windows | 41
42 | 304495 |  | Right Menu | 43
44 | 304496 | F1 | F2 | 45
46 | 304497 | F3 | F4 | 47
48 | 304498 | F5 | F6 | 49
50 | 304499 | F7 | F8 | 51
52 | 304500 | F9 | F10 | 53
54 | 304501 | F11 | F12 | 55
56 | 304518 |  | Space | 57
58 | 304521 |  | ' | 59
60 | 304524 | , | - | 61
62 | 304525 | . | / | 63
64 | 304526 | 0 | 1 | 65
66 | 304527 | 2 | 3 | 67
68 | 304528 | 4 | 5 | 69
70 | 304529 | 6 | 7 | 71
72 | 304530 | 8 | 9 | 73
74 | 304531 |  | ; | 75
76 | 304532 |  | = | 77
78 | 304534 |  | A | 79
80 | 304535 | B | C | 81
82 | 304536 | D | E | 83
84 | 304537 | F | G | 85
86 | 304538 | H | I | 87
88 | 304539 | J | K | 89
90 | 304540 | L | M | 91
92 | 304541 | N | O | 93
94 | 304542 | P | Q | 95
96 | 304543 | R | S | 97
98 | 304544 | T | U | 99
100 | 304545 | V | W | 101
102 | 304546 | X | Y | 103
104 | 304547 | Z | [ | 105
106 | 304548 | \ | ] | 107
108 | 304550 | ~ |  | 109
©2007 by Seemann

Для проверки нажатия нужно прочитать область памяти по указанному в таблице индексу

Пример 1. Проверяем, нажат ли Enter.

1. Находим в таблице Enter. Его индекс равен 304490.
2. Enter стоит в столбце KeyHi, это значит, что когда кнопка будет нажата в переменной будет записано число 0x00FF0000. Кнопки в столбце KeyLo возвращают число 255 (0xFF), когда нажаты.
3. Пишем код

Copy to Clipboard
0@ = 304490

:loop
wait 0
&0(0@,1i) == 0x00FF0000
jf @loop
player.money($player_char) += 100

при нажатии Enter игроку дадут 100 долларов.

Пример 2. Проверяем, нажата ли тильда (слева от единицы)

1. Находим в таблице ~. Ее индекс равен 304550.
2. ~ стоит в столбце KeyLo, это значит, что когда кнопка будет нажата в переменной будет записано число 0xFF
3. Пишем код

Copy to Clipboard
0@ = 304550

:loop
wait 0
&0(0@,1i) == 0xFF
jf @loop
player.money($player_char) += 100

при нажатии ~ игроку дадут $100.

Пример 3. Комбинируем проверки. Проверяем нажатие Num1 + Num2

1. У обоих кнопок один индекс 304484, поэтому при нажатии враз они вернут число 0x00FF00FF.
2. Пишем код

Copy to Clipboard
0@ = 304484

:loop
wait 0
&0(0@,1i) == 0x00FF00FF
jf @loop
player.money($player_char) += 100

при нажатии Num1 и Num2 игроку дадут $100.

См. также опкод 0AB0


Работа с битами переменной.

Любому человеку, изучавшему основы программирования известно, что число в машинном коде представлено в виде нулей и единиц, то есть в двоичной системе счисления. Минимальной единицей информации в компьютере является бит. Бит может быть либо «выключен», при этом его значение равно нулю, либо «включен», тогда его значение равно единице.
Процессор в РС и по сей день используют 32-битную архитектуру (intel и AMD выпускают процессоры с 64-битной архитектурой, но на данный момент операционные системы толком ее не поддерживают). Биты пронумерованы от 0 до 31 справа на лево:
31 30 29 28 27 ………..5 4 3 2 1 0.

К примеру десятичное число 65 будет представлено так:
0000 0000 0000 0000 0000 0000 0100 0001.

Ну что ж вернемся к нашим опкодам.

Наверное многие задавались вопросом, что же это за такие мудреные команды?

0004: $391 = 0 // integer values

. . . .

08BA: set $391 bit 0 - ?

. . . .

08C0: clear $391 bit 0 - ?

. . . .

08B4: test $391 bit 0 - ?

Прировняв переменную $391 к нулю мы, тем самым, установили все 32 бита в ноль.
Следующим опкодом 08BA: set $391 bit 0 мы устанавливаем нулевой бит равным единице, то есть 0000 0000...0000 0001.

Для примера напишем такой поток:

Copy to Clipboard
:TEST1
0004: $391 = 0 // integer values

:TEST1_1
08BA: set $391 bit 0

:TEST1_2
045A: text_draw_1number 20.0 430.0 ' NUMBER ' $391 // ~1~
wait 3000
end_thread

В результате в нижнем левом углу экрана появится цифра 1.

Для чего это нужно? Предположим что переменная $391 у нас будет отвечать за одежду игрока. К примеру нулевой бит имеет отношение к головному убору или прическе, второй – рубашка, третий – штаны и так далее. Либо каждый бит будет отвечать за различные варианты одежды. Тогда:

08BA: set $391 bit 0
08BA: set $391 bit 1
08BA: set $391 bit 2

будет означать что вся эта одежда будет применена к модели игрока.
Перед созданием игрока делаем проверку

if
08B4: test $391 bit 0
jf @xxx

тем самым мы проверяем равен ли нулевой бит единице.
Опкод 08C0: clear $391 bit 0 – очишаем нулевой бит переменной, то есть приравниваем его к нулю. Для примера рассмотрим такой поток:

Copy to Clipboard
create_thread @TEST1

:TEST1
thread 'TEST1'
$391 = 0 // integer values

:TEST1_18
wait 0
if
00E1: key_pressed 0 8 //Group CTRL Forward
jf @TEST1_46
08BA: set $391 bit 0
jump @TEST1_102

:TEST1_46
wait 0
if
00E1: key_pressed 0 9 //Group CTRL back
jf @TEST1_74
08BA: set $391 bit 1
jump @TEST1_102

:TEST1_74
wait 0
if
00E1: key_pressed 0 10 //conversation - no
jf @TEST1_102
08BA: set $391 bit 2

:TEST1_102
wait 0
if
08B4: test $391 bit 0 // проверяем равен ли нулевой bit единице
jf @TEST1_235 //если нет то переходим на следующую метку
Player.SetClothes($PLAYER_CHAR, "PLAYER_TORSO", "TORSO", Torso)
Player.SetClothes($PLAYER_CHAR, "AFRO", "AFRO", Head)
Player.SetClothes($PLAYER_CHAR, "BBSHORTRED", "BOXINGSHORT", Legs)
Player.SetClothes($PLAYER_CHAR, "COWBOYBOOT2", "BIKER", Shoes)
Player.Build($PLAYER_CHAR)
0110: clear_player $PLAYER_CHAR wanted_level
//А это делаем, для того, чтобы копы игрока не доставали после переодевания
jump @TEST1_510

:TEST1_235
wait 0
if
08B4: test $391 bit 1
jf @TEST1_372
Player.SetClothes($PLAYER_CHAR, "BBJERSEY", "SLEEVT", Torso)
Player.SetClothes($PLAYER_CHAR, "GROOVECUT", "GROOVECUT", Head)
Player.SetClothes($PLAYER_CHAR, "SUIT1TRGANG", "SUIT1TR", Legs)
Player.SetClothes($PLAYER_CHAR, "SHOEDRESSBRN", "SHOE", Shoes)
Player.Build($PLAYER_CHAR)
0110: clear_player $PLAYER_CHAR wanted_level
jump @TEST1_510

:TEST1_372
wait 0
if
08B4: test $391 bit 2
jf @TEST1_510
Player.SetClothes($PLAYER_CHAR, "TSHIRTERISYELL", "TSHIRT", Torso)
Player.SetClothes($PLAYER_CHAR, "WEDGE", "WEDGE", Head)
Player.SetClothes($PLAYER_CHAR, "BBSHORTWHT", "BOXINGSHORT", Legs)
Player.SetClothes($PLAYER_CHAR, "FLIPFLOP", "FLIPFLOP", Shoes)
Player.Build($PLAYER_CHAR)
0110: clear_player $PLAYER_CHAR wanted_level

:TEST1_510
08C0: clear $391 bit 0
08C0: clear $391 bit 1
08C0: clear $391 bit 2
jump @TEST1_18

Смотрите пример здесь.

P.S. Надеюсь после прочитанного появилось представление о работе выше перечисленных опкодов.


CLEO 3 Code Library
CLEO 3
Что такое CLEO 3? -------

CLEO 3 – это следующий шаг в развитии проекта CLEO, расширяющего границы возможностей скриптинга San Andreas. После установки библиотеки CLEO вы получаете все то, что может библиотека CLEO 2, а также некоторые нововведения третьей версии.

1. Новые опкоды
CLEO 3 имеет в наличии 40 полезных опкодов, среди которых есть опкоды чтения файлов, изменения игровой памяти, вызова процедур и функций и многое другое. Третья версия добавляет такие опкоды как вызов функции в SCM, запуск потока или миссии из внешнего файла и другие.

2. Плагины
Более подробнее о плагинах смотри ниже.

3. Добавление скриптов.
CLEO 3 позволяет добавить в игру новые скрипты, написанные в Sanny Builder’е без необходимости начала новой игры. Все, что требуется, это написать скрипт, поместить его в папку CLEO и запустить игру (новую или сейв).

Какие версии игры поддерживаются? -------

CLEO 3 поддерживает версию игры 1.0 и 1.01. CLEO 3 тестировался на US 1.0 и EUR 1.1. Если вы имеете иные версии игры, сообщите о том, как там работает CLEO 3.

Если CLEO 3 не работает на вашей версии, сообщите об этом, будем разбираться.

Как установить CLEO 3? -------

Для установки CLEO 3 запустите Sanny Builder. На нижней панели вы увидите слово CLEO в красной рамке. Кликните по нему, ознакомьтесь с лицензионным соглашением и нажмите кнопку Установить.
Физически CLEO 3 использует 3 файла в работе: vorbisFile.dll, vorbishooked.dll, cleo.asi. Обновленные версии этих файлов вы всегда можете найти на сайте cleo.sannybuilder.com.

Если вы использовали CLEO 2 или более раннюю версию, удалите ее, чтобы избежать конфликтов. Если вы использовали cleo.asi второй версии, замените его на новый (это произойдет при автоматической установке). Если вы использовали cleo.dll с запуском из main.scm, вы должны удалить cleo.dll и убрать его загрузку из файла main.scm.

Библиотеки CLEO 2 и CLEO 3 полностью совместимы. Все моды/плагины, написанные для CLEO 2 должны работать с новой версией.

Нужно ли менять SASCM.INI? -------

Необходимые изменения уже внесены в ваш SASCM.INI и OPCODES.TXT. При последующих обновлениях функционала библиотеки возможны добавления новых опкодов. Все необходимые инструкции будут даны вместе с обновлением на сайте cleo.sannybuilder.com.

Что там насчет плагинов? -------

Плагины - это обычные DLL-файлы, имеющие расширение .CLEO. При запуске библиотека CLEO 3 ищет в папке GTA SA\CLEO\ файлы с данным расширением и пытается загрузить их. После удачной загрузки плагин начинает работать и выполнять те функции, для которых он написан.

Процедура установки плагина очень проста: просто скопируйте файл в папку GTA SA\CLEO\. Чтобы прекратить пользование плагином - удалите файл.
Список доступных плагинов можно найти на cleo.sannybuilder.com.

Распространение CLEO 3? -------

Если вы написали скрипт, использующий библиотеку CLEO 3 и (или) ее плагины, вы можете также распространять вместе с ним необходимые файлы. Вы можете указать ссылку на cleo.sannybuilder.com, чтобы пояснить, как необходимо пользоваться библиотекой и сопутствующими файлами.

Кредиты? -------

Автор библиотеки CLEO 3 - Seemann. Автор не несет никакой ответственности за возможные негативные последствия, вызванные использованием данного продукта. Используйте его на свой страх и риск.
Если вы хотите помочь в разработке библиотеки или плагинов, обращайтесь на форум.
Автор также благодарит Станислава Головина (aka listener) за поддержку и полезную информацию.


FAQ по CLEO 3

Q: Где можно ознакомиться со списком новых опкодов и значениями параметров?

A: смотрите здесь.

Q: Правда ли, что можно добавлять новые скрипты и не начинать новую игру?

A: Да, это является основным нововведением CLEO 3. Подробнее о новом способе скриптинга написано здесь: CLEO3: скрипты.
 Q: Как использовать в скрипте модель, которая обычно содержится в списке DEFINE OBJECT?

A: CLEO-скрипты содержатся в scm-файлах без заголовка, т.е. являются аналогом внешних скриптов из файла script.img. Поэтому в них нет такого понятия как DEFINE OBJECT. Чтобы использовать такую модель, нужно указать вместо #имени ее глобальный ID (число).

Вы можете воспользоваться встроенной в SB функцией поиска ID модели (Ctrl+Alt+H).
Также вы можете воспользоваться способом, описанным здесь.

Если вам потребуется в скрипте использовать глобальный ID модели из списка импортирумых моделей (DEFINE OBJECTS), вы можете прочитать его из адреса памяти игры, используя следующую формулу:

MA = -4982 + (ModelID * -7)

Например, чтобы прочитать глобальный ID модели INFO используйте следующий код:

Copy to Clipboard
0@ = #INFO
0@ *= -7
0@ += -4982
0084: $modelID = &0(0@,1i)

в modelID будет записано 1239.

вот пример цикла, который выводит по очереди все ID моделей из стандартного майна

Copy to Clipboard
03C4: set_status_text_to $modelID 0 'FEC_NMN'

 // -4982 + (ModelID * -7)
for 1@ = -1 downto -388 // #INFO downto #SFCOPDR
 0085: 0@ = 1@
 0@ *= -7
 0@ += -4982
 0084: $modelID = &0(0@,1i)
 wait 1000
end // for

Свернуть

Q: Можно ли писать CLEO-скрипты в других редакторах?

A: Если вы по каким-то причинам не хотите или не можете использовать SB в качестве редактора скриптов, это не мешает вам писать скрипты для CLEO 3. Для этого вам нужно использовать первый способ написания скрипта, описанный здесь (извлечение скрипта из script.img).

Q: Для чего в начале некоторых скриптов стоит опкод 0000?

A: Это связано с некорректной обработкой скриптовым движком игры "нулевых переходов" (т.е. переходов на самое начало внешнего скрипта или миссии). Если скрипт представляет собой сплошной цикл, то этот опкод 0000 предназначен для создания минимального смещения от начала скрипта (эдакий буфер). Вместо 0000 можно использовать, например, wait 0.
Подробнее смотрите здесь.

Скриптовый движок SA имеет один неприятный баг, связанный с метками. Вы не можете осуществить переход из тела внешнего скрипта к его началу, т.е. сделать jump на самую первую метку.

DEFINE SCRIPT TEST_SCR AT @TEST_SCR
...

//-------------External script (TEST_SCR)---------------

:TEST_SCR
wait 0
jump @TEST_SCR // этот опкод вызовет ошибку

Поэтому, если внешний скрипт представляет собой сплошной цикл, то нужно вставить какой-то опкод в начале, а затем метку для перехода:

DEFINE SCRIPT TEST_SCR AT @TEST_SCR
...

//-------------External script (TEST_SCR)---------------

:TEST_SCR
0000: // можно вставить 03A4

:TEST_SCR_1
wait 0
jump @TEST_SCR_1 // этот опкод будет работать.

Тот же баг проявляет себя и в миссиях, но там переход к самому началу почти никогда не требуется.

Свернуть

Q: Почему в CLEO-скриптах нельзя использовать глобальные переменные? Что тогда использовать?

Подробнее смотрите здесь.

Когда мы компилируем main.scm вместе со всеми миссиями и скриптами, все глобальные переменные получают свой ID (порядковый номер). Часть из них получает ID всегда один и тот же (например, $PLAYER_CHAR компилируется как $2, $PLAYER_ACTOR - $3 и т.п.). Это справедливо для всех глобальных переменных, которые определены в CustomVariables.ini

Этот порядковый номер означает номер ячейки в памяти игры, где хранится значение переменной. Понятное дело, этот номер должен быть уникальным для каждой переменной. Иными словами, каждая переменная должна быть скомпилирована с уникальным ID.

Все остальные переменные компилируются следующих образом. Если имя переменной не найдено в CustomVariables.ini, то она компилируется с номером, который идет следом за наибольшей использованной переменной в скрипте. Звучит сложновато, поэтому пояcню на примере:

Простой скрипт из 2х строк:

$PLAYER_CHAR = 1
$MYVAR = 1

$PLAYER_CHAR компилируется как $2. Значит, переменная $MYVAR, которая не содержится в CustomVariables.ini и имя которой не числовое, будет скомпилирована как $3. (на самом деле там будет не $3, потому что $3 зарезервировано для $PLAYER_ACTOR, поэтому $MYVAR получит первое свободное имя - $4

Другой пример

$PLAYER_CHAR = 1
$MYVAR = 1
$100 = 1

Наибольшая переменная в скрипте теперь $100, поэтому $MYVAR станет $101.

Такой механизм позволяет присвоить каждой переменной свое уникальное имя.

В main.scm все новые переменные получают имена при компиляции начиная с $10948, т.к. $10947 наибольшая переменная, использованная в оригинальном main.scm.

Теперь вернемся к CLEO-скриптам. Каждый раз, когда мы компилируем новый скрипт, компилятор не знает ничегошеньки про состояние main.scm и сколько переменных в нем использовалось. Он именует переменные с нуля каждый раз. Это значит, что если ты сделаешь два скрипта, в которых будет:

в одном скрипте

$MYVAR = 1

в другом скрипте

$MYVAR1 = 1

то обе переменные будут скомпилированы как:

$4 = 1
несмотря на то, что имена у них разные. И каждый раз компилятор будет в новом клео-скрипте именовать переменные, начиная с $4. Эффект, думаю, ясен. Переменные будут использовать одну и ту же ячейку памяти и менять значения друг друга. Если ты в одном скрипте запишешь актера в $MYVAR, а в другом в $MYVAR1 = 0, то когда первый скрипт обратится к $MYVAR, он прочитает не актера, а 0, т.к. обе переменные используют 4-ю ячейку памяти.

Другая ситуация - это выход за пределы памяти для глобальных переменных. Например, обычный stripped имеет размер памяти для глобальных переменных в 409 ячеек, поскольку наибольшая использованная переменная $ONMISSION это $409. Предположим, мы создали клео-скрипт:

$ONMISSION = 1
$MYVAR = 0

Как будет скомпилирована переменная $MYVAR, если вы поняли, о чем я говорил выше ? Правильный ответ $411. $ONMISSION это $409, поэтому переменная должна бы стать $410, но этот ID уже зарезервирован для $Help_SprayCan_Shown (см. CustomVariables.ini). Поэтому первый свободный номер это $411.

Вернемся теперь к stripped. Размер памяти-то у него так и остался - 409 (если бы $MYVAR = 0 компилировалась в майне, то память была бы увеличена до 411). Поэтому когда клео-скрипт будет работать с переменной $MYVAR, ее значения будут читаться и писаться за пределами дозволенной области памяти. В худшем случае, такие переменные будут менять код самого main.scm (опкоды и параметры), что неминуемо повлечет вылет.

Свернуть

А также здесь.

Глобальные переменные ($) вообще не рекомендуется использовать в CLEO-скриптах, не важно, каким способом их называть. Есть только 2 исключения: 1) это общераспространенные переменные типа $PLAYER_CHAR, $PLAYER_GROUP, $ONMISSION и 2) неиспользуемые переменные типа $30, $56. В любом случае к использованию глобальных переменных нужно подходить очень осторожно, иначе не минуемы различные глюки в игре.

Зато СВОБОДНО, БЕЗ ОГРАНИЧЕНИЙ можно пользоваться локальными переменными. Мало 32-х переменных? Есть масса способов как обойти ограничение (начиная от простой оптимизации, заканчивая использованием scm-функций - 0AB1, 0AB2).

Если неудобно пользоваться локальными переменными из-за их имени (согласен, 1@ не всегда явно выражает смысл переменной), пользуйтесь конструкцией CONST..END Пара строк

const
TRAIN_MODEL = 1@
end
позволяет использовать в скрипте слово TRAIN_MODEL, которое на самом деле будет обозначать локальную переменную и компилироваться соответственно. Например, TRAIN_MODEL = 400 - это в переменную 1@ записали число 400. И все, больше никаких проблем из-за глобальных переменных.

Свернуть

Q: Можно ли в CLEO-скриптах использовать опкоды set_status_text и set_timer?

Подробнее смотрите здесь.

В CLEO скриптах в настоящее время нельзя использовать опкоды set_status_text и set_timer, а также сопутствующие им опкоды. Связано это с тем, что эти опкоды требуют задания глобальной переменной, которые, за редким исключением, использовать в CLEO-скриптах нельзя.

Поскольку написать альтернативу этим опкодам довольно непросто, я решил пойти другим путем. Я написал 4 функции, которые работают аналогично опкодам 03C3, 03С4, 014F, 0151, только принимают в качестве переменной - локальную переменную. Это позволяет использовать статус_текст и таймеры в CLEO-скриптах и CLEO-миссиях.

Внимание! Для корректной работы функций нужен CLEO 3 v3.0.950 и выше

Функции работают только в GTA: SA v1.0

Copy to Clipboard
:AddStatusText
0AB1: call_scm_func @__VarToOffset 1 0@ 0@
0AB1: call_scm_func @__LabelToOffset 1 2@ 2@
0AA6: call_method 0x0044CDA0 struct 0x00BA1788 num_params 4 pop 0 ( LINE = 3@ GXT = 2@ TYPE = 1@ VARNUMBER = 0@ )
0AB2: ret 0

:RemoveStatusText
0AB1: call_scm_func @__VarToOffset 1 0@ 0@
0AA6: call_method 0x0044CE80 struct 0x00BA1788 num_params 1 pop 0 ( VARNUMBER = 0@ )
0AB2: ret 0

:SetTimer
0AB1: call_scm_func @__VarToOffset 1 0@ 0@
0AB1: call_scm_func @__LabelToOffset 1 2@ 2@
0AA6: call_method 0x0044CD50 struct 0x00BA1788 num_params 3 pop 0 ( TYPE = 1@ GXT = 2@ VARNUMBER = 0@ )
0AB2: ret 0

:StopTimer
0AB1: call_scm_func @__VarToOffset 1 0@ 0@
0AA6: call_method 0x0044CE60 struct 0x00BA1788 num_params 1 pop 0 ( VARNUMBER = 0@ )
0AB2: ret 0

:__VarToOffset
0A9F: 1@ = current_thread_pointer
0A8E: 2@ = 1@ + 0xDC // mission Flag
0A8D: 2@ = read_memory 2@ size 1 virtual_protect 0
if
    2@ == 1
then
    1@ = 0x00A48960 // mission locals
else
    1@ += 0x3C
end
0@ *= 4
005A: 1@ += 0@ // address of the local variable
1@ -= 0xA49960
0AB2: ret 1 1@

:__LabelToOffset
if
    0@ == 0
then
    0AB2: ret 1 0
end
0A9F: 1@ = current_thread_pointer
1@ += 0x10
0A8D: 1@ = read_memory 1@ size 4 virtual_protect 0 // baseIP
0062: 1@ -= 0@ // label address
1@ += 3
0AB2: ret 1 1@

:StatusText
0900: 'BB_19'
0000:

Вот эти 4 функции.

1. AddStatusText эмулирует опкод
03C4: set_status_text $BEEFYBARON_SCORE type 0 GXT 'ZER2_43'.

Пример использования:

0AB1: call_scm_func @AddStatusText 4 VARNUMBER = 33 TYPE = 0 GXT = @StatusText LINE = 3

Параметры: VARNUMBER = 33 - это номер локальной переменной, значение которой будет выведено (т.е. 33@)

TYPE = 0 - как и в 03С4 тип статуса: полоска (1) или число (0).

GXT = @StatusText - это основное отличие от опкода. Напрямую передать строку в функцию нельзя (также как и в новый поток, например). Поэтому мы передаем метку, на которой стоит опкод 0900 с нужным текстом (GXT) (в данном случае 0900: 'BB_19'). Можно добавить несколько подряд опкодов 0900, каждый со своим GXT и своей меткой, и передавать в функцию нужную метку. Надеюсь, с этим проблем не возникнет.
Можно вместо метки написать 0, тогда будет выводиться только число, без текста слева.

LINE = 3 - номер строки, на которой появится статус. Если равно 0, то статус добавится к первой свободной строке.

2. RemoveStatusText эмулирует опкод 0151: remove_status_text $1924

Пример использования:

0AB1: call_scm_func @RemoveStatusText 1 VARNUMBER = 33

Параметр только один - номер локальной переменной, которая использовалась в AddStatusText.

3. SetTimer эмулирует опкод 03C3: set_timer_to $1923 type 1 GXT 'BB_19'

Пример использования:

0AB1: call_scm_func @SetTimer 3 VARNUMBER = 1 TYPE = 1 GXT = @StatusText

Параметры VARNUMBER и GXT аналогичны AddStatusText. Параметр TYPE означает вид таймера: увеличивающийся или уменьшающийся.

4. StopTimer эмулирует 014F: stop_timer $1923

Пример использования:

0AB1: call_scm_func @StopTimer 1 VARNUMBER = 1

Параметр - номер локальной переменной, которая использовалась в SetTimer.

Поскольку это лишь эмуляция настоящих опкодов, все ограничения сохраняются (1 таймер и 4 статуса).

Чтобы использовать эти функции, нужно скопировать их без изменений в ваш скрипт, изменить или добавить нужные GXT-ключи, и вызывать соответствующую функцию.

Вот пример скрипта, который в течение 10 секунд показывает состояние переменной 33@ (т.е. таймера) http://cleo.sannybuilder.com/scripts/status_text.cs

Свернуть

У меня есть код CLEO-скрипта, как получить из него .cs-файл?

A: Для этого понадобится программа Sanny Builder 3.03 и выше (найти можно на этом же сайте). Скачайте ее, установите. Запустите, зайдите в опции (F10), укажите путь к папке игры. Теперь нажмите Файл-Создать (Ctrl+N), копируйте весь скрипт в окно редактора (начиная со слова {$CLEO}) и сохраните полученный текстовый файл. После этого нажмите F7. Если все прошло успешно, в папке игры в папке CLEO должен появиться новый .cs-файл. Если возникли ошибки при компиляции, попытайтесь исправить их, следуя советам из справки (она на русском языке!).


Список значений кнопок для 0AB0
Character | Decimal | Hex
Backspace | 8 | 8
Tab | 9 | 9
Enter | 13 | D
Shift (both) | 16 | 10
Ctrl (both) | 17 | 11
Pause | 19 | 13
Caps Lock | 20 | 14
Esc | 27 | 1B
Spacebar | 32 | 20
Page Up | 33 | 21
Page Down | 34 | 22
End | 35 | 23
Home | 36 | 24
(left arrow) | 37 | 25
(up arrow) | 38 | 26
(right arrow) | 39 | 27
(down arrow) | 40 | 28
Insert | 45 | 2D
Delete | 46 | 2E
0 | 48 | 30
1 | 49 | 31
2 | 50 | 32
3 | 51 | 33
4 | 52 | 34
5 | 53 | 35
6 | 54 | 36
7 | 55 | 37
8 | 56 | 38
9 | 57 | 39
A or a | 65 | 41
B or b | 66 | 42
C or c | 67 | 43
D or d | 68 | 44
E or e | 69 | 45
F or f | 70 | 46
G or g | 71 | 47
H or h | 72 | 48
I or i | 73 | 49
J or j | 74 | 4A
K or k | 75 | 4B
L or l | 76 | 4C
M or m | 77 | 4D
N or n | 78 | 4E
O or o | 79 | 4F
P or p | 80 | 50
Q or q | 81 | 51
R or r | 82 | 52
S or s | 83 | 53
T or t | 84 | 54
U or u | 85 | 55
V or v | 86 | 56
W or w | 87 | 57
X or x | 88 | 58
Y or y | 89 | 59
Z or z | 90 | 5A
(left Windows key) | 91 | 5B
(right Windows key) | 92 | 5C
(application key - located between the right Windows and Ctrl keys on most keyboards) | 93 | 5D
0 (numpad with Num Lock on) | 96 | 60
1 (numpad with Num Lock on) | 97 | 61
2 (numpad with Num Lock on) | 98 | 62
3 (numpad with Num Lock on) | 99 | 63
4 (numpad with Num Lock on) | 100 | 64
5 (numpad with Num Lock on) | 101 | 65
6 (numpad with Num Lock on) | 102 | 66
7 (numpad with Num Lock on) | 103 | 67
8 (numpad with Num Lock on) | 104 | 68
9 (numpad with Num Lock on) | 105 | 69
* (numpad) | 106 | 6A
+ (numpad) | 107 | 6B
- (numpad) | 109 | 6D
. (numpad) | 110 | 6E
/ (numpad) | 111 | 6F
F1 | 112 | 70
F2 | 113 | 71
F3 | 114 | 72
F4 | 115 | 73
F5 | 116 | 74
F6 | 117 | 75
F7 | 118 | 76
F8 | 119 | 77
F9 | 120 | 78
F10 | 121 | 79
F11 | 122 | 7A
F12 | 123 | 7B
Num Lock | 144 | 90
Scroll Lock | 145 | 91
; | 186 | BA
= | 187 | BB
, | 188 | BC
- | 189 | BD
. | 190 | BE
/ | 191 | BF
` | 192 | C0
[ | 219 | DB
\ | 220 | DC
] | 221 | DD
' | 222 | DE


CLEO 3: опкоды

Пользование следующими опкодами возможно только при установленной библиотеке CLEO 3. При компиляции Sanny Builder проверяет, установлена ли CLEO 3 и при необходимости предупреждает о том, что следует провести ее установку. Если вы написали скрипт с использованием данных опкодов, не забудьте включить в комплект файлы библиотеки или иным способом обеспечить для конечного пользователя работоспособность такого скрипта.

Opcode 0A8C | Opcode 0A99 | Opcode 0AA6 | Opcode 0AB3
Opcode 0A8D | Opcode 0A9A | Opcode 0AA7 | Opcode 0AB4
Opcode 0A8E | Opcode 0A9B | Opcode 0AA8 | Opcode 0AB5
Opcode 0A8F | Opcode 0A9C | Opcode 0AA9 | Opcode 0AB6
Opcode 0A90 | Opcode 0A9D | Opcode 0AAA | Opcode 0AB7
Opcode 0A91 | Opcode 0A9E | Opcode 0AAB | Opcode 0AB8
Opcode 0A92 | Opcode 0A9F | Opcode 0AAC | Opcode 0AB9
Opcode 0A93 | Opcode 0AA0 | Opcode 0AAD | Opcode 0ABA
Opcode 0A94 | Opcode 0AA1 | Opcode 0AAE | Opcode 0ABD
Opcode 0A95 | Opcode 0AA2 | Opcode 0AAF | Opcode 0ABE
Opcode 0A96 | Opcode 0AA3 | Opcode 0AB0 | Opcode 0ABF
Opcode 0A97 | Opcode 0AA4 | Opcode 0AB1 |
Opcode 0A98 | Opcode 0AA5 | Opcode 0AB2 |

Опкоды CLEO 2

0A8C: write_memory 0xC0BC15 size 1 value 1 virtual_protect 0

Опкод 0A8C записывает значение по указанному адресу памяти игры.

Параметры:
1 – адрес памяти (любое целое число)
2 – размер записи: 1, 2, 4 байта
3 – значение (любое число)
4 – Virtual Protect: 1 – если нужно сделать адрес памяти записываемым, 0 – если запись идет в перезаписываемый адрес памяти.

0A8D: $result = read_memory 1@ size 4 virtual_protect 0

0A8D читает определенный адрес памяти и записывает результат в переменную.

Параметры:
1 – переменная, в которую будет записан результат чтения (любая переменная или массив)
2 – адрес памяти (любое целое число)
3 – размер области чтения: 1, 2, 4 байта
4 – Virtual Protect: 1 – если нужно сделать адрес памяти читаемым, 0 – если запись идет в читаемый адрес памяти.

0A8E: 4@ = 5@ + 6@ // int

0A8E складывает два целых значения и записывает результат в переменную.

Параметры:
1 – переменная, в которую будет записана сумма (любая переменная или массив)
2 – первое слагаемое (любое целое число)
3 – второе слагаемое (любое целое число)

0A8F: $var = 0@(1@,2i) - 1 // int

0A8F вычитает одно целое значение из другое и записывает результат в переменную.

Параметры:
1 – переменная, в которую будет записана разность (любая переменная или массив)
2 – уменьшаемое (любое целое число)
3 – вычитаемое (любое целое число)

0A90: $var(0@,10i) = 100 * 1@ // int

0A90 перемножает два целых числа и записывает результат в переменную.

Параметры:
1 – переменная, в которую будет записано произведение (любая переменная или массив)
2 – умножаемое число (любое целое число)
3 – множитель (любое целое число)

0A91: $div = 1 / 5 // int

0A91 делит одно целое число на другое и записывает результат в переменную. Остаток от деления отбрасывается.

Параметры:
1 – переменная, в которую будет записано частное (любая переменная или массив)
2 – делимое (любое целое число)
3 – делитель (любое целое число)

0A96: $ActorStruct = actor $PLAYER_ACTOR struct

0A96 записывает в переменную адрес структуры актера в памяти. Структура – это совокупность разных значений, таких как здоровье, координаты и т.д. Зная адрес структуры актера можно читать эти значения, используя опкод 0A8D.

Параметры:
1 – переменная, в которую будет записан адрес структуры
2 – хендл (handle) актера

0A97: $CarStruct = car $MyCar struct

0A97 записывает в переменную адрес структуры машины в памяти.

Параметры:
1 – переменная, в которую будет записан адрес структуры
2 – хендл (handle) машины

0A98: $ObjectStruct = object 0@ struct

0A98 записывает в переменную адрес структуры объекта в памяти.

Параметры:
1 – переменная, в которую будет записан адрес структуры
2 – хендл (handle) объекта

0A99: chdir 0

0A99 меняет глобальный указатель игры на директорию, делая ее директорией по умолчанию.
Параметр:
0 – сделать директорией по умолчанию корневую папку игры
1 – сделать директорией по умолчанию папку с сейвами

0A9A: $hFILE = openfile "settings.ini" mode 0x72 // IF and SET

0A9A открывает файл для чтения и записи. Данный опкод может использоваться и как условие: если файл не был открыт, проверка вернет False, иначе True.

Параметры:
1 – переменная, в которую будет записан указатель на файл
2 – путь к файлу. Если путь локальный, файл ищется относительно текущей директории (см. опкод 0A99).
3 – режим открытия файла:
0x6272 – открыть байтовый файл для чтения
0x72 – открыть текстовый файл для чтения
0x6277 – открыть бинарный файл для записи
0x77 – открыть текстовый файл для записи

0A9B: closefile $hFILE

0A9B закрывает файл и освобождает память.

Параметр: указатель на файл

0A9C: 0@ = file $hFILE size

0A9C записывает в переменную размер файла в байтах.

Параметры:
1 – переменная, в которую будет записан размер файла
2 – указатель на файл

0A9D: readfile $hFILE size 2 to $150

0A9D считывает определенное число байтов из открытого файла и записывает их в область памяти, где находится переменная.

Параметры:
1 – указатель на файл
2 – количество байтов чтения
3 – переменная в которую будет записан результат чтения. Если размер чтения превышает 4 байта, остаток будет записан в следующую переменную (в данном случае в $151).

0A9E: writefile $hFILE size 128 from 0@

0A9E записывает в открытый файл определенное число байтов, начиная адреса по которому находится переменная – последний параметр.

Параметры:
1 – указатель на файл
2 – количество байтов, который будут записаны в файл
3 – переменная, начиная с которой будет вестись запись. Если размер записи превышает 4, будет записано значение следующей переменной и т.д. В данном примере в файл будет записан дамп всех локальных переменных потока (32 переменных по 4 байта = 128 байтов).

0A9F: 0@ = current_thread_pointer

0A9F записывает в переменную адрес структуры текущего потока. Зная этот адрес можно работать напрямую с определенными значениями потока, такими как имя потока, локальные переменные, базовый IP и т.д.

0AA0: gosub_if_false @CREATE_NEW_ACTOR

0AA0 делает gosub, если условие было ложным. В целом данный опкод напоминает 004D: jump_if_false и может использоваться вместо него.

Параметр: метка для перехода

0AA1: return_if_false

0AA1 делает return, если условие было ложным. В целом данный опкод напоминает 004D: jump_if_false и может использоваться вместо него.

0AA2: $hLIB = load_library "CLEO\version.dll" // IF and SET

0AA2 загружает библиотеку DLL по указанному адресу и записывает указатель на нее в переменную. Данный опкод может использоваться и как условие. Если библиотека не была загружена, проверка вернет False, иначе True.

Параметры:
1 – переменная, в которую будет записан указатель на библиотеку (любая локальная или глобальная переменная)
2 – путь к библиотеке. Если указан относительный путь (без указания диска), поиск файла будет вестись относительно текущей активной директории (см. опкод 0A99). Если расширение файла не указано, будет использовано расширение по умолчанию (.DLL).

0AA3: free_library $hLIB

0AA3 выгружает библиотеку из памяти.

Параметр: указатель на библиотеку

0AA4: $hPROC = get_proc_address "GetVersion" library $hLIB // IF and SET

0AA4 ищет в библиотеке процедуру с указанным именем и если находит записывает ее адрес в переменную. Этот адрес может потом быть использован в опкодах типа call. Данный опкод может использоваться и как условие. Если процедура не была найдена, проверка вернет False, иначе True.

Параметры:
1 – переменная, в которую будет записан адрес процедуры.
2 – имя процедуры (строка или стринговая переменная). Обратите внимание, get_proc_address чуствительна к регистру имени. Если процедура импортирована из DLL с именем GetVersion, это значит, что например get_proc_address “getversion” такую процедуру не найдет. Вы должны указывать точное имя. Также помните, что при компиляции Sanny Builder по умолчанию переводит все строки в верхний регистр. Это значит, что данный пример будет скомпилирован как «GETVERSION», и соответственно процедура GetVersion не будет найдена. Чтобы избежать этого, переключите регистр букв в опциях на «Как есть».
3 – указатель на загруженную библиотеку (0AA2)

0AA5: call $hPROC num_params 1 pop 1 $param

0AA5 и подобные ему опкоды имеют переменное количество параметров. Данный опкод имеет минимум 3 параметра, а также дополнительные, число и значение которых зависит от вызываемой процедуры. Общее число таких дополнительных параметров должно соответствовать параметру num_params. Все передаваемые параметры должны быть числовыми (константы или переменные), но не строковыми.

Параметры:
1 – глобальный адрес процедуры. Это может быть адрес в gta_sa.exe или загруженной dll.
2 – число передаваемых в процедуру параметров.
3 – число параметров, которые должны быть убраны со стека после того как отработает вызываемая процедура. Это значение может быть в интервале от 0 до num_params. Точное число зависит от самой вызываемой процедуры. Как правило, отдельные функции в ехе сами не «чистят» за собой стек, поэтому число pop должно быть чаще всего равно num_params.

0AA6: call_method $Destroy struct $CarStruct params 0 pop 0

0AA6 вызывает процедуру для класса. Каждый класс имеет кроме набора значений еще и набор процедур (ближайшее сравнение – классы в SB), которые называются методами. В данном примере мы вызываем метод уничтожения структуры $CarStruct (условно, если $Destroy содержит глобальный адрес такой процедуры в ЕХЕ). С определенными оговорками, можно сказать что это тоже самое, что Car.Destroy($MyCar).

Параметры:
1 – глобальный адрес процедуры. Это может быть адрес в gta_sa.exe или загруженной dll.
2 – указатель на структуру, частью которой является вызываемая процедура. Может быть получен опкодами 0A96 - 0A98.
3 – число передаваемых параметров
4 – число параметров, которые должны быть убраны со стека после того как отработает вызываемый метод. Как правило, методы сами чистят за собой стек и параметр pop должен быть равен 0.

0AA7: call_function 0x569660 num_params 2 pop 2 $COORD_X $COORD_Y $GROUND

0AA7 работает по схожему принципу, что и 0AA5, только дополнительно записывает в переменную результат вызванной функции. Последним параметром всегда должна быть переменная – в нее будет записан результат. num_params таким образом будет на 1 меньше, чем кол-во дополнительных параметров (в данном примере мы вызвали функцию по адресу 0x569660 и передали ей два параметра X и Y, результат функции будет записан в $GROUND).

Параметры:
1 – глобальный адрес процедуры. Это может быть адрес в gta_sa.exe или загруженной dll.
2 – число передаваемых в функцию параметров.
3 – число параметров, которые должны быть убраны со стека после того как отработает вызываемая функция. Это значение может быть в интервале от 0 до num_params. Точное число зависит от самой вызываемой процедуры. Как правило, отдельные функции в ехе сами не «чистят» за собой стек, поэтому число pop должно быть чаще всего равно num_params.

0AA8: call_function_method 0x4048E0 struct 0xB74494  num_params 1 pop 0 $MyCar 0@

0AA8 вызывает функцию из структуры struct и записывает результат в переменную, которая всегда должна идти в конце. Принцип работы схож с опкодами 0AA6 и 0AA7. В данном примере мы вызываем функцию по адресу 0x4048E0 и передаем ей как параметр хендл машины. struct 0xB74494 это структура всех машин в игре. 0x4048E0 – функция, которая переводит хендл в указатель на структуру (аналог опкода 0A97). Полученный указатель будет записан в переменную 0@.

Параметры:
1 – глобальный адрес функции. Это может быть адрес в gta_sa.exe или загруженной dll.
2 – указатель на структуру, частью которой является вызываемая функция. Может быть получен опкодами 0A96 - 0A98.
3 – число передаваемых параметров
4 – число параметров, которые должны быть убраны со стека после того как отработает вызываемый метод. Как правило, методы сами чистят за собой стек и параметр pop должен быть равен 0.

0AA9: is_game_version_original

Данный опкод используется как условие. Если вы работаете в оригинальной версии GTA SA 1.0 проверка вернет True, иначе False. Опкод полезен при написании модов, которые будут работать на разных версиях игры.

0AAB: file_exists "CLEO\version.dll"

0AAB проверяет, существует ли физически указанный файл. Данная проверка является частью опкодов 0A9A и 0AA2 и для них дублировать ее необязательно.

Параметр: путь к файлу. Если указан относительный путь (без указания диска), поиск файла будет вестись относительно текущей активной директории (см. опкод 0A99).

0AAC: $hMP3 = load_mp3 "CLEO\playlist\01.mp3"

0AAC загружает в память mp3-файл и записывает указатель на него в переменную.

Параметры:
1 – переменная, в которую будет записан указатель на загруженный mp3.
2 – путь к mp3-файлу. Если указан относительный путь (без указания диска), поиск файла будет вестись относительно текущей активной директории (см. опкод 0A99).

0AAD: set_mp3 $hMP3 perform_action 1

Данный опкод выполняет одно из заранее определенных действий над загруженным mp3.

Параметры:
1 – указатель на загруженный mp3
2 – число, определяющее одно из выполняемых действий:
0: остановить проигрывание
1: запустить проигрывание файла
2: поставить проигрывание на паузу
3: продолжить проигрывание

0AAE: release_mp3 $hMP3

0AAE выгружает mp3-файл из памяти.

Параметр: указатель на загруженный mp3-файл.

0AAF: 0@ = get_mp3_length $hMP3

Данный опкод записывает в переменную длину mp3-файла в секундах.

Параметры:
1 – переменная, в которую будет записана длина трека
2 – указатель на загруженный mp3-файл

0AB0: key_pressed 0x73

0AB0 используется как условие. Данный опкод проверяет, была ли нажата клавиша на клавиатуре. Если клавиша с указанным номером была нажата, проверка вернет True, иначе False.

Параметр: номер клавиши на клавиатуре. Список значений кнопок для 0AB0 см. здесь

Опкоды CLEO 3

0A92: create_custom_thread "ShowTextBox.s"

0A92 создает поток из указанного файла. Обратите внимание, что если файл имеет расширение .cs, поток из этого файла будет создан автоматически при старте игры. При создании потока опкодом 0A92 можно передать в него до 34 параметров, как в опкоде 004F.

Параметр: путь к файлу. Имя файла должно быть указано полностью с расширением (если таковое имеется). Поиск файла ведется относительно папки ‘игра\CLEO’.

0A93: end_custom_thread

0A93 останавливает текущий CLEO-поток. Данный опкод должен использоваться только внутри файлов с CLEO-потоками (не CLEO-миссиями и не в main.scm). В целом данный опкод является аналогом опкода 004E.
Для остановки CLEO-миссии используйте опкод 004E.

0A94: start_custom_mission "missions\CustomMission1"

0A94 стартует CLEO-миссию из указанного файла аналогично опкоду 0417. Обратите внимание, что расширение указывать не надо. В действительности опкод будет искать файл с расширением .cm (Custom Mission). В данном примере миссия будет запущена из файла CLEO\missions\CustomMission1.cm

Параметр: путь к файлу. Имя файла должно быть без расширения. Поиск файла ведется относительно папки ‘игра\CLEO’.

0A95: enable_thread_saving

0A95 устанавливает флаг сохранения для текущего CLEO-потока. По умолчанию CLEO-потоки не сохраняются в CLEO-сейве, а при запуске игры начинают работу с самого начала. Для того чтобы сохранить в сейве статус потока, его переменные и т.п., добавьте этот опкод в самое начало скрипта.

0AAA: 0@ = thread 'OTB' pointer

Данный опкод проверяет, активен ли поток с указанным именем. Если он активен, в переменную записывается адрес данного потока. Если поток с указанным именем не был найден в памяти игры, в переменную будет записано число 0.

Параметры:
1 - имя переменной, в которую будет записан результат поиска
2 - имя потока для поиска

0AB1: call_scm_func @GetSQR 1 10 $result

Данный опкод вызывает код из текущего скрипта (по аналогии с gosub), передает в него параметры и получает результат. Передаваемые параметры последовательно копируются в локальные переменные, затем поток переходит на указанную метку, выполняет код по данной метке и возвращается после опкода 0AB2.

Параметры:
1 – имя метки (начало SCM-функции)
2 – количество передаваемых параметров

После этого идут передаваемые параметры, в данном случае число 10. После этого должны стоять переменные, в которые будет записан результат (см. 0AB2).

0AB2: ret 1 0@

Данный опкод возвращает поток на опкод 0AB1 и записывает значения в его результирующие переменные. Общее число возвращаемых значений обязательно должно соответствовать числу переменных в опкоде 0AB1. В данном примере опкод 0AB2 вернет одно значение, которое содержится в переменной 0@ и это значение будет записано в переменную $result (см. 0AB1). Если 0AB2 не возвращает значений, в нем должен стоять ноль как единственный параметр, а 0AB1 не должен иметь переменных для приема.

Параметры:
1 – количество возвращаемых значений
После этого идут возвращаемые значения, в данном случае значение переменной 0@.

Вот простой пример оформления SCM-функции получения квадрата числа.

0@ = 5
0AB1: call_scm_func @GetSQR 1 10 $result
end_thread

…..

: GetSQR
006A: 0@ *= 0@
0AB2: ret 1 0@

Объясню механизм работы. Сперва игра приходит на опкод 0AB1. После этого читаются передаваемые параметры – в данном случае он один и равен 10. Переменная 0@ текущего потока приравнивается к 10 (если бы число параметров было больше, следующее значение было бы записано в 1@, потом 2@ и т.д.). После этого поток переходит на метку GetSQR. Здесь происходит вычисление квадрата числа (параметра в 0@). Опять-таки, если бы функция была сложнее, то могли бы еще учитываться переменные 1@ (второй переданный параметр) и т.д. После вычислений игра переходит на опкод 0AB2. Значение 0@ в этот момент равно 10*10 = 100. Игра читает, сколько значений нужно вернуть (в данном примере 1, см. 0AB2). После этого происходит следующее: возвращаемое значение (0@) записывается в те переменные, которые стоят в опкоде 0AB1, вызвавшем данную функцию. В этом примере это переменная $result. После записи значения, поток возвращается обратно к опкоду 0AB1 и переходит на команду end_thread. Значение переменной $result в этот момент равно 100.

Напоследок скажу, что 0AB2 может возвращать не только значения переменных, но и числовые константы. Например, 0AB2: ret 1 1 всегда будет записывать в результат 1.
Также обратите внимание, что сами значения локальных переменных после вызова функции не меняются! В данном примере, перед опкодом 0AB1 переменная 0@ была равна 5. Несмотря на то, что она использовалась в вычислениях внутри функции, после вызова она будет по-прежнему равна 5. Это распространяется на все 32 локальные переменные, поэтому вы можете свободно работать с ними внутри функции, не боясь потери данных.

0AB3: var 0 = 10

0AB3 устанавливает значение глобальной CLEO-переменной. Эти переменные могут использоваться для обмена данными между CLEO-потоками, а также между CLEO и main.scm. Общее число таких переменных равно 1000. Их значения сохраняются в CLEO-сейве.
Такие переменные могут использоваться и в самом main.scm как альтернатива простым глобальным переменным.

Параметры:
1 – ID глобальной переменной. Должно быть в интервале 0..999.
2 – значение глобальной переменной (любое число, целое или дробное).

0AB4: 0@= var 0

0AB4 записывает в переменную значение глобальной CLEO-переменной. В данном примере 0@ будет равно 10 (см. опкод 0AB3).

Параметры:
1 – переменная, в которую будет записано значение глобальной CLEO-переменной.
2 – ID глобальной переменной. Должно быть в интервале 0..999.

0AB5: store_actor $PLAYER_ACTOR closest_vehicle_to 0@ closest_ped_to 1@

Данный опкод записывает в переменные хэндлы ближайших к актеру машины и прохожего. Если близко к актеру нет ни одной машины или прохожего, в соответствующую переменную будет записано -1.

Параметры:
1 – хендл актера
2 – переменная, в которую будет записан хендл ближайшей машины
3 – переменная, в которую будет записан хендл ближайшего прохожего

0AB6: store_target_marker_coords_to 0@ 1@ 2@ // IF and SET

Этот опкод записывает в переменные координаты места, отмеченного на карте красным маркером цели (правый клик по карте). Если этой отметки на карте нет, значения переменных не изменятся.

Параметры:
1,2,3 – переменные, в которые будут записаны координаты XYZ

0AB7: get_vehicle $CAR number_of_gears_to 10@

Опкод 0AB7 записывает в переменную общее число передач в коробке передач данной машины. Это число соответствует параметру TransmissionData.nNumberOfGears в файле handling.cfg.

Параметры:
1 – хендл машины
2 – переменная, в которую будет записано число передач

0AB8: get_vehicle $CAR current_gear_to 11@

Данный опкод записывает в переменную номер текущей передачи в коробке передач машины.

Параметры:
1 – хендл машины
2 – переменная, в которую будет записана текущая передача

0AB9: get_mp3 $hMP3 state_to 7@

Данный опкод записывает в переменную состояние mp3-файла.

Параметры:
1 – хендл загруженного mp3 (опкод 0AAC)
2 – переменная, в которую будет записана состояние mp3:
1 – файл проигрывается
2 – файл на паузе
-1 – файл остановлен

0ABA: end_custom_thread_named 'BENZIN'

0ABA завершает CLEO-поток с указанным именем. Имя потоку дается опкодом 03A4. Если имя потоку не было задано опкодом 03A4, поток получает имя по первым 7 буквам названия файла. Например, поток из файла test.cs будет иметь имя 'test.cs', из файла myscript.cs - 'myscrip'. Опкод 0ABA немедленно прекращает работу потока с указанным именем. Этот опкод аналогичен опкоду 0459, но предназначен для CLEO-скриптов.

Параметры:
1 - имя потока

0ABD: vehicle 0@ siren_on

0ABD 0ABD проверяет, включена ли сирена на машине 0@. Если сирена включена, проверка вернет True.

Параметры:
1 - хендл машины

0ABE: vehicle 0@ engine_on

0ABE проверяет, запущен ли двигатель на машине 0@. Если двигатель запущен, проверка вернет True.

Параметры:
1 - хендл машины

0ABF: set_vehicle 0@ engine_state_to 0

0ABF устанавливает режим двигателя: выключен, включен.

Параметры:
1 - хендл машины
2 - режим двигателя:
0 - выключить двигатель
1 - включить двигатель


CLEO3: скрипты

CLEO 3 позволяет добавлять новые скрипты без необходимости начала новой игры. Строго говоря. для них не имеет значения состояние вашего main.scm. CLEO-скрипты запускаются и функционируют отдельно от main.scm.

Что это дает? Вы можете в любой момент игры добавить новые скрипты, а также удалить имеющиеся. При этом вам не требуется редактировать main.scm, а значит пропадают проблемы с необходимостью начала новой игры, несовместимостью сейвов, скриптовыми лимитами и так далее.

CLEO-скрипт – это обычный скрипт, написанный с использованием опкодов в Sanny Builder. Каждый скрипт должен быть выполнен в виде отдельного файла с расширением .cs (Custom Script). Главное требование, которое предъявляется к написанию таких скриптов, это то, что они должны быть скомпилированы как внешние скрипты.

Существует несколько способов написания CLEO-скрипта, способного нормально работать в игре.
Во-первых, вы добавляете в исходник новый внешний скрипт, после этого компилируете, и извлекаете нужный файл из script.img. Этот файл будет иметь расширение .scm, и вам останется только изменить его на .cs и скопировать в папку ‘игра\CLEO’.
Второй способ гораздо проще. Создайте новый файл в Sanny Builder’е, напишите в начале директиву $E, после этого код скрипта и скомпилируйте. Полученный файл будет точно такой, как если бы вы извлекли его из script.img. Вам останется только дать ему нужное расширение .cs и скопировать в папку \CLEO.

Наконец, самый простой способ. Создайте новый файл, в начале напишите директиву {$CLEO .cs} (или с другим расширением), после этого код скрипта и скомпилируйте. Файл автоматически будет скопирован в директорию CLEO и будет иметь такое расширение, которое вы указали в директиве $CLEO (.cs по умолчанию).

CLEO-скрипты могут использоваться и как миссии. Процесс компиляции точно такой же, однако итоговый файл должен иметь расширение .cm (Custom Mission). Для того чтобы запустить такую миссию, используйте опкод 0A94.

Правила, которым вы обязаны следовать при использовании CLEO 3:

  1. Один файл – один поток. Каждый CLEO-скрипт должен быть выполнен в виде отдельного потока, который компилируется в отдельный файл. Если вам нужно создавать дополнительные потоки для вашего скрипта, используйте опкоды 004F или 0A92, в зависимости от того, где находится этот поток: в main.scm или отдельном cs-файле.
  2. Никогда не используйте опкод 004E в CLEO-скриптах. Они работают отдельно от обычных потоков, и использование этого опкода вызовет ошибку. Если вам нужно остановить CLEO-поток, используйте опкод 0A93. В CLEO-миссиях наоборот никогда не используйте опкод 0A93, а для остановки миссии используйте 004E.
  3. Не используйте в CLEO-скрипте собственные глобальные переменные ($car, $blahblah и т.д.), иначе скрипт будет работать неправильно. Вы можете использовать только некоторые глобальные переменные (см. ниже).

Как уже говорилось, для установки скрипта достаточно скопировать его в папку ‘игра\CLEO’. Имя файла не имеет значения, работа с файлами происходит по расширению. Однако имя файла используется при инициализации CLEO-потока, чтобы дать ему имя (name_thread) по названию файла (первые 7 символов). Например, CLEO-поток в файле showsavescreen будет иметь имя SHOWSAV.
Для удаления скрипта из игры просто удалите соответствующий файл.

Статус CLEO-потоков может сохраняться и загружаться вместе с обычными потоками. По умолчанию эти потоки не сохраняются. Сами сейвы находятся отдельно, в папке CLEO\cleo_saves. Для каждого слота используется отдельный сейв. В сейве сохраняются только те CLEO-потоки, для которых включен флаг сохранения (опкод 0A95). В сейве сохраняются не только активные потоки, но и те, которые были завершены (опкод 0A93), чтобы предотвратить их повторную загрузку. Если при последующей загрузке один из сохраненных скриптов не будет найден, ошибки не будет. Если вы добавите новый скрипт, которого нет в сейве, он запустится вместе со всеми и начнет работать с начала.

В целом CLEO-потоки такие же как и обычные потоки. У них также 32 локальных переменных и 2 таймера. При создании CLEO-потока или CLEO-миссии можно передавать в них до 34 параметров (по аналогии с опкодом 004F).

Важный момент, связанный с обменом данными между CLEO-скриптом и main.scm. Чтобы пользоваться кодом из майна, его переменными, потоками, вы должны компилировать CLEO-скрипт как внешний скрипт, а затем извлекать из script.img. Однако этот способ очень не рекомендован, поскольку такой скрипт становится весьма чувствительным к изменению main.scm. По смыслу, CLEO-скрипты должны быть самодостаточными и использовать минимум ресурсов главного скм-файла. Вы, однако, можете свободно использовать имена глобальных переменных из файла CustomVariables.ini (например, $PLAYER_CHAR, $PLAYER_ACTOR, $ONMISSION и т.д.).
Также для обмена данными между main.scm и CLEO, или между CLEO-скриптами вы можете использовать CLEO-переменные (см. опкоды 0AB3, 0AB4).

В комплект CLEO 3 включены примеры простых скриптов с исходниками.

Описание примеров CLEO-скриптов:

test_example.txt

Базовый пример создания CLEO-скрипта. Смысл его заключается в выводе сообщения при запуске игры. Для этого используется доп. скрипт ShowTextBox, который показывает текстбокс на экране. Данный пример может служит основой для вывода тестовых сообщений в любом моде.

Скрипт срабатывает однократно при запуске игры. После сохранения-загрузки сообщение появляться не будет (благодаря опкоду 0A95). TXT-файл (исходник), здесь.

showsavescreen.txt

Пример постоянно работающего скрипта. Представляет собой бесконечный цикл, проверяющий нажатие кнопки F4. После ее нажатия появляется окно сохранения. TXT-файл (исходник), здесь.

CustomMission.txt

Болванка CLEO-миссии. Если создать скрипт по аналогии с showsavescreen, только вместо вывода экрана сохранения использовать 0A94, можно запускать эту миссию. TXT-файл (исходник), здесь.

otbhook.txt

Пример хука. Этот скрипт проверяет запущена ли миссия OTB (скачки на лошадях), и если да, то повышает значения ставок. Скрипт предназначен для оригинальной игры. TXT-файл (исходник), здесь.

VCCam.txt

Позаимствовано из мультимода Capushon’а. Скрипт меняет положение камеры при езде на машине, делая обзор гораздо удобнее. TXT-файл (исходник), здесь.


Sanny Builder Help: О программе

Что это такое?

Список изменений


Предыдущие релизы

История изменений Sanny Builder, начиная с версии 0.6...

01.01.2007
version 2.99e

* исправлена ошибка с пропаданием части кода при декомпиляции в режиме отладки внутри конструкции hex..end
* конструкция hex..end может принимать тип aDMA для записи чисел
к цикле FOR можно использовать имена моделей в качестве значений счетчика
конструкция hex..end может принимать строки

03.12.2006
version 2.99d

* убран Memory Hacker (он стал отдельной программой: http://sannybuilder.com/downloads)
* исправлена одна ошибка в декомпиляторе

30.11.2006
version 2.99c

* добавлен плагин Memory Hacker
* возможность декомпиляции main.scm Liberty City Stories
* поддержка числовых констант в качестве индекса глобального массива
* при декомпиляции переменные заменяются на тип ADMA, если не делятся
на 4
* при компиляции при отсутствии заголовка выставляются значения по умолчанию
* возможность открывать файлы в редакторе методом Drag&Drop
* новые препроцессорные директивы: {$VERSION}, {$VERSION_RESTORE}

(!) Если при компиляции вы получаете сообщение об ошибке в заголовке

("Неизвестная команда DEFINE OBJECTS") переместите строку

{$VERSION xxxx} в любое место после заголовка, например перед комментарием

//-------------MAIN---------------

27.09.2006
version 2.99

* добавлены две новые команды WriteMem и ReadMem
* поддержка чисел в шестнадцатиричном формате
* конструкция hex..end может принимать значения меток и глобальных переменных
* поддержка типа данных & для массивов, а также в выражениях без опкодов:
&57 += &120(&231,4i)
* возможность давать собственные имена меткам
* возможность выбирать регистр букв для собственных имен меток и переменных, а также стринговых переменных (Настройки -> Форматирование)
* добавлена консоль для специальных опций SB
* поддержка GXT-файлов GTA III, GTA VC
* поддержка символьных констант в длинных стрингах
* минорные исправления и добавления:
- информация об авторе и версии INI файла
- поддержка классами INI с оригинальным порядком следования параметров (как SASCM.INI от PLPynton)
- опция подтверждения выхода
- возможность быстро переключать режим редактирования
- конвертация отдельного, выделенного участка кода SAMB
- возможность передавать во внешнее приложение в качестве параметра имя текущего открытого файла
- исправлены некоторые ошибки в конфигурационных файлах
- убрана автоматическая конвертация числа в тип Float, если переменная была объявлена как Float, а в нее записывалось целое число. Теперь опкод выбирается только в зависимости от типа числа.
- чтение/изменение Z_angle игрока в Coord Manager; возможность вставки значения угла в скрипт нажатием Ctrl+Shift+E (для SA)

04.08.2006
version 2.98

* Sanny Builder полностью русифицирован
* добавлено меню внешних приложений
* в SB встроена специальная версия Opcode Search Tool
(http://gtacoding.nm.ru/tool). Подробности в файле 'Readme OST.txt'
* проверка математических выражений при декомпиляции с выключенной опцией "Писать опкоды"*
* возможность выбирать IMG-файл самостоятельно, если таковой не найден в папке с SCM-файлом (опция "Ручной выбор IMG-файла")
* возможность добавлять новые макросы прямо из редактора; добавлены описания макросов
* список моделей можно сортировать по алфавиту/по значению (Alt+S, когда активен список)
* минорные исправления и изменения

11.06.2006
version 2.97

* новый тип данных: & (direct byte address)
* минорные изменения

01.04.2006
version 2.96

* расширена опция прохода по меткам
* добавлена возможность вызвать список макросов
* добавлена опция замены номеров миссий на их имена
* исправлены некоторые ошибки

18.02.2006
version 2.9f

* новые модели автоматически добавляются в список DEFINE OBJECTS (этот список можно вообще не использовать)
* добавлены блочные комментарии: {}
* добавлена запись макросов
* минорные исправления и добавления
... этот релиз стал первым в череде обновлений версии 2.9. Все эти версии вносили несущественные изменения в язык, а основной упор делался на шлифовку интерфейса, упрощение работы с программой и устранение багов. Исключением стала пожалуй версия 2.99 ...

Факт:
Это был юбилейная, десятая версия программы.

15.12.2005
version 2.9

* добавлены дополнительные команды
* добавлен оператор IN
* добавлена конструкция IF..THEN..ELSE..END
* добавлены циклы WHILE, REPEAT; добавлена возможность использования вложенных циклов.
* новый стиль комментариев: //
* позиции маркеров и курсора запоминаются для закрытых файлов
... эта версия стала самой "долгоиграющей" в истории SB. Строго говоря, ее развитие продолжается и в настоящий момент. Изначально планировалось, что она станет последней для данного движка, и следующая версия выйдет под цифрой 3. Но время, изменившиеся обстоятельства, возникшие трудности сыграли свою роль и поэтому "трешки" нет и сейчас :( ...

Факт:
Оператор IN, введенный в данной версии просуществовал совсем недолго. Уже в следующем релизе он был убран, как не оправдавший надежд.
Факт:
Исполняемый факт был переименован с SannyBuilder.exe на sanny.exe

05.11.2005
version 2.6

* добавлена поддержка форматов Vice City и GTA3
* добавлена возможность инициализации переменных и массивов как членов класса
* добавлен показ списка переменных и меток
* добавлена поддержка циклов ( оператор FOR )
* минорные изменения:
* миссии можно запускать по их имени ( start_mission MYMISSION ), где MYMISSION - это имя стартовой метки ( DEFINE MISSION 100 at @MYMISSION )
* доступен список импортируемых моделей (defined objects) по Ctrl+Space
* новый псевдооператор <>
* если при декомпиляции не найден script.img, используется оригинальный
* для массивов добавлен тип handle
* возможность отключения предупреждения об использовании IMG игрой
... наконец-то была добавлена поддержка всех игр GTA, использующих main.scm. Единообразный синтаксис и возможность работать в одной программе - вот основополагающие факторы, позволяющие в настоящий момент создавать кроссплатфоренные моды и использовать старые наработки в новых частях GTA ...

Факт:
В данной версии появилась папка example, в которой содержатся небольшие примеры кодов, в основном связанные с использованием высокоуровневых конструкций языка SB.

10.10.2005
version 2.5

* добавлена поддержка свойств классов
* добавлена поддержка макросов
* добавлена конструкция VAR..END для эффективного управления переменными
* описаны все возможные математические опкоды: 0004..008B
* новые псевдознаки < и <=
* добавлена возможность автоподбора необходимого значения для оператора IF
* добавлена поддержка расширенных названий параметров
* добавлен показ списка моделей
* минорные добавления и исправления
... данная версия привнесла одну из основных достоинств нового высокоуровневого языка: свойства. Свойство - это особый член класса, который в зависимости от положения в выражении и знака операции обозначал различные опкоды (1@ = Actor.Health; Actor.Health = 1@ это два РАЗНЫХ опкода при одном свойстве класса). Кроме этого было внесены существенные изменения в язык, направленные на упрощение процесса написания кода ...

Факт:
В версии 2.5 была изменена иконка SB, на ту, что есть сейчас

18.09.2005
version 2.0 b demo

* добавлена поддержка классов
* добавлена поддержка ключевых слов
* добавлена возможность писать некоторые математические команды без опкодов
* для опкода 00D6 по умолчанию устанавливается параметр 0, если иное не установлено (if = if 0)
* добавлена опция выбора различных видов меток (Formats->Labels Format)
* добавлены ключевые слова True и False, которые обозначают 1 и 0 соответственно
* добавлена конструкция HEX..END для записи шестнадцатиричных значений прямо в SCM.
... Sanny Builder перешел на вторую версию движка, развитие которого продолжается до настоящего времени. Список изменений был настолько внушительным, что я даже удивляюсь, как мне удалось сделать это за 10 дней. В редакторе появилась функция Ctrl+Space, позволяющая выводить список кейвордов и классов для быстрой вставки в код (правда, тогда еще данные элементы списка не разграничивались и не подкрашивались). Все это стало возможным благодаря компоненту SynEdit. Я добавил его в SB еще в версии 0.7 и потом нахально пользовался его возможностями :). Без него не было бы подсветки, списков и прочих "вкусностей" редактора. Спасибо вам, авторы SynEdit ...

Факт:
Английская версия программы обрела новую домашную страницу: http://freewebs.com/sannybuilder
Факт:
Приставка Demo в версии программы означала, что количество доступных классов (Player, Model и Camera) и их членов (написано 9 на все три класса) было лишь временным ограничением, и что в последующих версиях их число будет увеличиваться.

07.09.2005
version 1.1

* добавлен coord manager
* исправлены некоторые ошибки
... спустя пару дней после выпуска версии 1.0 мы получили сообщения от первых западных пользователях SB об ошибках. Чтобы не выпускать версию, похожую на патч, в SB была добавлена возможность чтения координат игрока в San Andreas. Само по себе весьма значительное событие для увеличения номера версии на единицу, не так ли? ...

Факт:
В данной версии появился файл stripped.txt - жалкие огрызки main.scm, позволяющие лишь запустить игру и создать игрока. По идее - идеальное место для тестирования новых опкодов, скриптов, миссий и прочего.

04.09.2005
version 1.0

* новый формат меток
* добавлен конвертор из синтаксиса BW's SA Mission Builder
* при декомпиляции в исходник добавляются названия моделей и содержимое american.gxt
* добавлены новые опции
* пофиксены некоторые ошибки
... новая цифра в версии был сделана исключительно из маркетинговых соображений. Западной публике требовался готовый продукт, а не полуфабрикаты. С точки зрения движка, все осталось без существенных изменений. Зато появился конвертор для SAMB. Это сразу увеличило число потенциальных пользователй SB, поскольку процесс перехода на новую платформу существенно ускорился ...

Факт:
Данная версия стала первой, которая при первом запуске разворачивалась сразу на весь экран. До этого SB по умолчанию запускался в виде окна.

20.08.2005
version 0.8 b

* добавлена подсветка синтаксиса
* добавлена возможность ассоциировать SCM-файлы с программой
* сообщения об ошибках стали более информативными
* теперь при декомпиляции имя выходного файла изменяется, если такой файл уже существует (например, если уже существует main.scm.txt, то имя нового файла будет main.scm[0].txt)
* добавлена проверка на дублирование меток
* пофиксены некоторые ошибки
... версией 0.8 Sanny Builder был официально представлен забугорной публике. На GTAForums.com появился соответствующий топик. Данное событие оказалось решающее воздействие на развитие SB. Мы отказались от идеи сделать второй MB, а вместо этого решили создать высокоуровневый компилятор, который упростил бы процесс кодинга в разы. ...

Факт:
В данной версии появилась подсветка синтаксиса, без которой сейчас я лично SB не представляю. Любой уважающий себя редактор имеет (или должен иметь) нечто подобное. Вроде бы SAMB тоже, но у меня это не получалось заставить его раскрашивать строки.
Факт:
Меню опций приобрело окончательный вид (деление на 4 вкладки) и до настоящего момента не менялось.

10.08.2005
version 0.7 a

* увеличено число опций для работы с текстом
* добавлена возможность работать с несколькими файлами одновременно
* добавлена функция поиска опкодов через F1 (beta)
... спустя несколько дней после выпуска пилотной версии, вышла следующая, которая добавила первые пожелания пользователей. Изменения касались прежде всего повышения удобства работы в программе. Также в данной версии появилась одна важная составляющая, которая впоследствии определила дальнейший ход разработки программы. Об этом чуть позже ...

Факт:
Начиная с данной версии основной тулбар (панелька с кнопочками сразу под меню) не менялся в течении года. Следующее изменение было внесено версией 2.98: была добавлена кнопка Replace.
Факт:
В данной версии появилась папка Help, которая сразу стала неотъемлемой частью Sanny Builder.

04.08.2005
version 0.6 a

* полная декомпиляция *.scm файлов San Andreas
* компиляция скриптов в SCM-файл (SA) и IMG-файл.
* доступны минимальные опции работы с текстом
... данная версия стала первым официальным релизом данной программы. Первое упоминание о ней было сделано на форуме ag.ru. На самом деле данная версия с точки зрения юзабилити представляла собой весьма убогое зрелище, но благодаря помощи и советам первых ее пользователей, особенно Capushon'а, разработка пошла в правильном направлении ...

Факт:
Содержимое архива версии 0.6 составляло лишь три (!) файла: SannyBuilder.exe, Readme.txt и vars.ini

Факт:
Данная версия была единственной из всех, которая позволяла распечатывать файл. Впоследствии данная возможность была вырезана.


CLEO не найден

CLEO не найден

Данная ошибка возникает, когда вы используете опкод, требующий установленной библиотеки CLEO. Программа либо не нашла требуемые файлы, либо версия имеющейся библиотеки не подходит.

Возможные решения: установите библиотеку, кликнув по слову CLEO на нижней панели.


INI-файл не найден

Сообщения и ошибки

INI-файл не найден

Данная ошибка возникает, когда при загрузке программа не находит INI-файл, содержащий перечень всех опкодов и их параметров. Без этого файла работа компилятора невозможна.

Возможные решения: переустановите программу или укажите корректный путь к INI файлу.


Неизвестный тип массива

Сообщения и ошибки

Неизвестный тип массива

Массивы имеют строго определенный перечень типов. Если декомпилятор не находит соответствия тому типу массива, который записан в SCM-файле, возвращается данная ошибка. Она может возникать вследствие неправильной компиляции

Возможные решения: включите через консоль пропуск неизвестных опкодов (команда toggle ignore_unknown).


Невозможно декомпилировать script.img

Сообщения и ошибки

Невозможно декомпилировать script.img

Если при декомпиляции возникает такая ошибка, значит файл script.img поврежден или имеет неизвестный формат. Ошибка может возникать также при несоответствии файла script.img тем данным, которые записаны в заголовке main.scm. Проверьте, чтобы эти файлы были скомпилированы одновременно.

Возможные решения: замените script.img на файл, соответствующий тому SCM-файлу, который вы декомпилируете.


Неизвестный параметр

Сообщения и ошибки

Неизвестный параметр

Каждый опкод имеет ограниченное количество типов параметров, каждый из которых обозначен определенным числом. Если данное число неизвестно декомпилятору, или оно выходит за границы типов параметров для данной версии игры, возникает эта ошибка. Ошибка возникает, если файл был скомпилирован неправильно, либо число параметров для декомпилируемого опкода не совпадает с оригинальным.

Возможные решения: включите через консоль пропуск неизвестных опкодов (команда toggle ignore_unknown).


Невозможно декомпилировать файл

Сообщения и ошибки

Невозможно декомпилировать файл

Эта ошибка возникает, если вы пытаетесь декомпилировать SCM-файл GTA3 или Vice City при включенном режиме редактирования игры San Andreas

Возможные решения: переключите режим редактирования


Неверный заголовок файла

Сообщения и ошибки

Неверный заголовок файла

Данная ошибка возникает, если заголовок декомпилируемого файла содержит неверные или невозможные данные.

Возможные решения: отключите через консоль чтение заголовка файла (команда skip_scm_header)


Невозможно загрузить файл

Сообщения и ошибки

Невозможно загрузить файл

Ошибка возникает, если программа не может найти файл, необходимый ей для работы.

Возможные решения: проверьте правильность указания пути и наличия указанного файла.


Невозможно создать таблицу опкодов

Сообщения и ошибки

Невозможно создать таблицу опкодов

Данная ошибка возникает при старте программы, если в INI-файле, содержащем опкоды, содержатся ошибки.

Возможные решения: переустановите программу или обновите INI-файл.


Нет INI-файла

Сообщения и ошибки

Нет INI-файла

Данная ошибка возникает при попытке запуска компилятора или декомпилятора при отсутствующем INI-файле, содержащем опкоды (см. ошибка 1)

Возможные решения: проверьте наличие INI-файла и перезапустите программу.


Неизвестный опкод

Сообщения и ошибки

Неизвестный опкод

Данная ошибка возникает, если компилятор встречает опкод, значение которого не определено в INI-файле.

Возможные решения: отредактируйте указанный опкод. Вероятно, вы указали неверное значение.


Неизвестный опкод

Сообщения и ошибки

Неизвестный опкод

Данная ошибка возникает, если декомпилятор встречает опкод, значение которого не определено в INI-файле. Чаще всего ошибка возникает в случае, когда у предыдущего опкода число параметров не совпадает с эталонным.

Возможные решения: добавьте указанный опкод в соответствующий INI-файл, либо включите через консоль пропуск неизвестных опкодов (команда toggle ignore_unknown).


Переход за границы файла

Сообщения и ошибки

Переход за границы файла

Данная ошибка возникает, когда декомпилятор находит значение метки, которое превышает размеры скриптового кода.

Возможные решения: декомпиляция невозможна


Неизвестная команда

Сообщения и ошибки

Неизвестная команда

Общая ошибка, возникающая когда компилятор находит команду, которая ему неизвестна или находится в неверном месте. Это может быть слово в начале строки, в то время как компилятор ожидает найти там опкод.

Возможные решения: отредактируйте указанную команду, возможно вы написали ее с опечаткой.


Неверное выражение

Сообщения и ошибки

Неверное выражение

Эта ошибка возникает, когда вы используете математическое выражение без указания опкода, и типы операндов несовместимы. Несовместимость операндов возможна в случае, когда вы:

а) указали тип переменной, используя конструкцию VAR..END, однако используете данную переменную вместе с другим типом.
б) обе переменные не имеют указанного через конструкцию VAR..END типа
в) один из операндов невозможен. Например, вы используете число в операции присваивания как левый операнд (5=5)

Возможные решения: проверьте правильность указанного выражения. Выберите решение в зависимости от типа ошибки (см. выше):

а) переопределите переменную с нужным типом
б) укажите типы переменных, используя конструкцию VAR..END
в) укажите допустимое значение


Память превышена

Сообщения и ошибки

Память превышена

Данная ошибка возникает, если количество используемых меток в декомпилируемом файле превышает число 65536

Возможные решения: декомпиляция невозможна


Поток не найден

Сообщения и ошибки

Поток не найден

Эта ошибка возникает, когда декомпилятор не находит указанного начала миссии или внешнего скрипта. Чаще всего это бывает, когда используется script.img, внутренние смещения файлов которого отличны от тех, что записаны в заголовке main.scm

Возможные решения: включите через консоль пропуск неизвестных опкодов (команда toggle ignore_unknown).


Переменная не объявлена

Сообщения и ошибки

Переменная не объявлена

Эта ошибка возникает, когда компилятор не может определить тип переменной. Чаще всего это возникает вследствие неверного указанного типа, либо его отсутствия

Возможные решения: укажите корректное значение типа переменной, используя автоподстановку (Ctrl+Space)


Невозможно узнать размер массива

Сообщения и ошибки

Невозможно узнать размер массива

Ошибка возникает вследствие того, что вы не указали размер массива при его объявлении в конструкции VAR..END, либо указали некорректное значение (например, строку).

Возможные решения: укажите корректное целочисленное значение


Неизвестный тип массива

Сообщения и ошибки

Неизвестный тип массива

Ошибка возникает вследствие того, что вы не указали тип массива, либо указали некорректное значение (например, число).

Возможные решения: укажите корректное значение, в соответствии с данным топиком


Переменная не объявлена как массив

Сообщения и ошибки

Переменная не объявлена как массив

Данная ошибка возникает, когда вы используете короткую нотацию для массива, но при этом переменная массива не была объявлена как массив.

Возможные решения: объявите переменную как массив с указанием типа и размера, используя конструкцию VAR..END


Неверное целочисленное значение в имени переменной

Сообщения и ошибки

Неверное целочисленное значение в имени переменной

Ошибка возникает, когда вы используете нечисловое значение для локальных стринговых переменных (@s, s$)

Возможные решения: укажите корректное целое значение в соответствии с лимитами локальных переменных для San Andreas


Некорректный счетчик итераций

Сообщения и ошибки

Некорректный счетчик итераций

Данная ошибка возникает, когда вы указываете в качестве счетчика не переменную, а например число или не указываете его совсем.

Возможные решения: укажите переменную для счетчика


Ожидалось одно, но найдено другое

Сообщения и ошибки

Ожидалось одно, но найдено другое

Общая ошибка, возникающая при некорректном синтаксисе конструкций FOR..END и VAR..END.

Возможные решения: проконсультируйтесь с соответствующими топиками для написания корректного синтаксиса.


Ожидалось целочисленное значение

Сообщения и ошибки

Ожидалось целочисленное значение

Общая ошибка, возникающая когда вы используете нецелочисленное значение, а например дробное, там, где оно требуется (Например, тип aDMA).

Возможные решения: проконсультируйтесь с соответствующими топиками для написания корректного синтаксиса.


Некорректные значения счетчика

Сообщения и ошибки

Некорректные значения счетчика

Ошибка возникает, когда вы используете некорректные значения счетчика. Таковыми считаются

а) при конструкции FOR..to – когда начальное значение счетчика больше конечного
б) при конструкции FOR..downto – когда конечное значение счетчика больше начального

Возможные решения: проконсультируйтесь с данным топиком и укажите корректные значения счетчика


Невозможно посчитать дробный параметр

Сообщения и ошибки

Невозможно посчитать дробный параметр

Данная ошибка возникает когда вы используете неверный синтаксис дробного числа, например, слишком большое число перед точкой.

Возможные решения: укажите допустимое значение


Слишком длинная строка

Сообщения и ошибки

Слишком длинная строка

Строковые значения имеют определенные ограничения по длине, поэтому когда вы превышаете лимит для данного типа строки, возникает эта ошибка.

Возможные решения: ограничьте длину строки до допустимого значения, либо используйте другой тип (“…” вместо ‘…’).


Незавершенная строка

Сообщения и ошибки

Незавершенная строка

Данная ошибка возникает, поскольку компилятор не может найти конец указанной строки. Строки должны обозначаться открывающей и закрывающей кавычкой (одинарными или двойными, в зависимости от типа строки).

Возможные решения: проверьте правильность написания строковых параметров на данной строке


Невозможно определить ID отладочного скрипта

Сообщения и ошибки

Невозможно определить ID отладочного скрипта

Данная ошибка возникает, когда компилятор не может распознать параметр специального опкода 05B6 как целое число. Этот опкод содержит 128-байтовые строки, содержащие отладочную информацию, используемую R*. Данные строки добавляются исключительно в целях компиляции кода аналогичного оригинальному.

Возможные решения: укажите корректное целое число.


Ожидалось определение количества элементов

Сообщения и ошибки

Ожидалось определение количества элементов

Данная ошибка возникает, когда компилятор не нашел ожидаемое определение количества миссий или внешних скриптов. Чаще всего это возникает вследствие неправильно определенного кол-ва элементов в предыдущем сегменте заголовка main.scm

Возможные решения: проверьте правильность задания значений в заголовке файла


Невозможно определить количество элементов

Сообщения и ошибки

Невозможно определить количество элементов

Данная ошибка возникает, когда компилятор не может распознать значение для количества объектов, миссий или внешних скриптов, либо указанное значение недопустимо.

Возможные решения: проверьте правильность задания количества элементов в данном сегменте заголовка файла


Невозможно определить значение элемента

Сообщения и ошибки

Невозможно определить значение элемента

Данная ошибка возникает, когда компилятор не может распознать значение для четвертого (UNKNOWN_EMPTY_SEGMENT) или пятого (UNKNOWN_THREADS_MEMORY) элемента заголовка файла main.scm.

Возможные решения: укажите корректное целое значение для данного элемента заголовка


Невозможно установить локальную переменную

Сообщения и ошибки

Невозможно установить локальную переменную

Данная ошибка возникает, если компилятор не может распознать имя локальной переменной как целое число. Возникает это, когда вы указываете не целое число, а например строку. Эта ошибка похожа на ошибку 21.

Возможные решения: укажите корректное имя локальной переменной


Локальная переменная вне допустимых границ

Сообщения и ошибки

Локальная переменная вне допустимых границ

Эта ошибка возникает, когда вы указываете имя локальной переменной, которое превышает допустимое значение для потоков данной игры.

Возможные решения: укажите иное имя в соответствии с лимитами локальных переменных для потоков, либо отключите проверку локальных переменных в опциях.


Ожидалось определение элемента

Сообщения и ошибки

Ожидалось определение элемента

Данная ошибка возникает, когда компилятор ожидает встретить определенный элемент сегмента заголовка, но найденная строка таковым не является.

Возможные решения: проверьте правильность написания имени элемента


Локальная переменная вне допустимых границ

Сообщения и ошибки

Локальная переменная вне допустимых границ

Эта ошибка возникает, когда вы указываете имя локальной переменной, которое превышает допустимое значение для миссий данной игр. В целом эта ошибка сходна с ошибкой 34.

Возможные решения: укажите иное имя в соответствии с лимитами локальных переменных для миссий, либо отключите проверку локальных переменных в опциях.


Отладочный скрипт не найден

Сообщения и ошибки

Отладочный скрипт не найден

Данная ошибка возникает, когда компилятор находит специальный опкод 05B6 с параметром, большим чем это позволяет размер файла debug.bin. Этот файл содержит 128-байтовые строки, содержащие отладочную информацию, используемую R*. Данные строки добавляются исключительно в целях компиляции кода аналогичного оригинальному.

Возможные решения: укажите целое число не превышающее максимально допустимое значение (211).


Неизвестный тип массива

Сообщения и ошибки

Неизвестный тип массива

Эта ошибка возникает, когда вы указываете тип массива, который не известен компилятору. Число типов массивов строго ограничено.

Возможные решения: проконсультируйтесь с данным топиком и укажите корретное значение.


Невозможно определить элемент

Сообщения и ошибки

Невозможно определить элемент

Эта ошибка возникает, когда компилятор не может распознать один из элементов сегмента миссий или внешних скриптов: метку миссии, внешнего скрипта, а также номер определяемой миссии. Она может возникать, когда вы указываете вместо целого числа, например строку.

Возможные решения: укажите корректное значение элемента


Имя константы не определено

Сообщения и ошибки

Имя константы не определено

Данная ошибка возникает, если вы не указали имя константы или ее значение в конструкции CONST..END.

Возможные решения: проконсультируйтесь с данным топиком для правильного задания константы.


Неверный ID миссии

Сообщения и ошибки

Неверный ID миссии

Эта ошибка возникает, когда определяемый номер миссии либо меньше нуля, либо превышает общее кол-во миссий, заданное в заголовке файла.

Возможные решения: отредактируйте указанное значение, указав допустимый номер.


Внешний скрипт уже был определен

Сообщения и ошибки

Внешний скрипт уже был определен

Данная ошибка возникает, когда вы используете в заголовке одно и тоже имя для нескольких внешних скриптов. Данная операция недопустима.

Возможные решения: укажите другое имя для данного скрипта


Неверное имя индексной переменной массива

Сообщения и ошибки

Неверное имя индексной переменной массива

Данная ошибка возникает, когда вы используете в качестве индекса массива не переменную, а например число. Для того, чтобы указать число используйте индексированные переменные.

Возможные решения: укажите глобальную или локальную переменную,
содержащую индекс данного массива.


Неверное имя массива

Сообщения и ошибки

Неверное имя массива

Данная ошибка возникает, когда вы используете в качестве имени массива не переменную, а например число. Данная ошибка сродни ошибке 43.

Возможные решения: укажите глобальную или локальную переменную


Имя не найдено

Сообщения и ошибки

Имя не найдено

Данная ошибка возникает, когда компилятор не может найти имя массива или его индексной переменной.

Возможные решения: укажите соответствующее имя


Стринговая переменная не может использоваться

Сообщения и ошибки

Стринговая переменная не может использоваться

Данная ошибка возникает, когда вы используете в качестве имени массива или его индексной переменной стринговую переменную (@s, s$).

Возможные решения: используйте обычную глобальную или локальную переменную.


Размер массива не может быть меньше 1

Сообщения и ошибки

Размер массива не может быть меньше 1.

Данная ошибка возникает, если вы указываете в качестве размера массива нулевое или отрицательное значение, что противоречит сущности массива.

Возможные решения: укажите корректное целое значение


Невозможно получить размера массива

Сообщения и ошибки

Невозможно получить размера массива

Ошибка возникает вследствие того, что вы не указали размер массива, либо указали некорректное значение (например, строку).

Возможные решения: укажите корректное целочисленное значение


Недостаточно параметров для опкода

Сообщения и ошибки

Недостаточно параметров для опкода

Данная ошибка возникает, если компилятор не смог получить необходимое количество параметров для опкода на данной строке. Параметров может быть меньше нужного количества, либо некоторые из них невозможны. Число параметров для каждого опкода устанавливается в INI-файле и может отображаться в статус-баре при включенной опции Показывать информацию об опкодах

Возможные решения: укажите требуемое количество параметров


Недостаточно параметров для команды

Сообщения и ошибки

Недостаточно параметров для команды

Данная ошибка возникает, если компилятор не смог получить необходимое количество параметров для дополнительной команды или директивы. Параметров может быть меньше нужного количества, либо некоторые из них невозможны. Вы можете узнать требуемое количество параметров в соответствующем топике, а также в подсказке, появляющейся после нажатия Ctrl+Shift+Space.

Возможные решения: укажите требуемое количество параметров.


Невозможно записать заголовок IMG-файла

Сообщения и ошибки

Невозможно записать заголовок IMG-файла

Данная ошибка возникает, если во время компиляции заголовка файла script.img возник какой-либо сбой.

Возможные решения: попробуйте повторить процесс компиляции еще раз. Если ошибка повторяется, обратитесь к разработчикам.


Невозможно записать IMG-файл

Сообщения и ошибки

Невозможно записать IMG-файл

Данная ошибка возникает, если во время компиляции содержимого файла script.img возник какой-либо сбой.

Возможные решения: убедитесь, что на диске достаточно места, и файл script.img может быть перезаписан.


Рекурсивное подключение файла

Сообщения и ошибки

Рекурсивное подключение файла

Данная ошибка возникает в директиве $INCLUDE, если в подключаемом файле содержится рекурсивное подключение текущего файла.

Возможные решение: проверьте, чтобы подключаемые файлы не ссылались на предыдущие файлы.


Метка не найдена

Сообщения и ошибки

Метка не найдена

Данная ошибка возникает, если компилятор не смог найти данную метку в скрипте.

Возможные решения: укажите имя существующей метки, возможно вы написали ее с ошибкой, либо напишите эту метку в нужном месте.


Идентификатор не найден

Сообщения и ошибки

Идентификатор не найден

Общая ошибка, возникающая когда компилятор не смог распознать действительный идентификатор (имя переменной, значение константы и т.п.) по причине его отсутствия или недопустимой длины.

Возможные решения: укажите корректный идентификатор


Метка переобьявлена

Сообщения и ошибки

Метка переобьявлена

Данная ошибка возникает, если вы используете одно и то же имя для нескольких меток, вследствие чего компилятор не может распознать на какую из них вы ссылаетесь.

Возможные решения: укажите иное имя для метки, которая повторяется дважды.


Невозможно выполнить переход к метке. Внутренная метка не найдена

Сообщения и ошибки

Невозможно выполнить переход к метке. Внутренная метка не найдена

Данная ошибка возникает, когда вы используете неверный синтаксис высокоуровневых конструкций (if..then..else..end, while..end, и т.д.). Чаще всего это возникает, когда вы не указываете закрывающий end в конце конструкции.

Возможные решения: проконсультируйтесь с соответствующими топиками и проверьте правильность написания высокоуровневых конструкций.


Неверный параметр

Сообщения и ошибки

Неверный параметр

Общая ошибка, возникающая когда вы используете недопустимый параметр в одной из внутренних команд. Например, ошибка может возникнуть, если вы используете в качестве результата функции Sqr или Random не переменную, а число.

Возможные решения: проконсультируйтесь с соответствующими топиками и укажите допустимый вариант.


Неверное число параметров в файле

Сообщения и ошибки

Неверное число параметров в файле

Данная ошибка возникает, если при загрузке INI-файла, программа обнаруживает недопустимое число параметров.

Возможные решения: обновите INI-файл


Нет исходного файла

Сообщения и ошибки

Нет исходного файла

Данная ошибка может возникнуть, если во время работы компилятора исходный файл был закрыт. В нормальных условиях это невозможно.

Возможные решения: откройте исходный файл и повторите компиляцию


Пустой исходный файл

Сообщения и ошибки

Пустой исходный файл

Данная ошибка может возникнуть, если вы пытаетесь скомпилировать пустой файл. В нормальных условиях это невозможно.

Возможные решения: откройте исходный файл и повторите компиляцию


IDE-файл не найден

Сообщения и ошибки

IDE-файл не найден

Данная ошибка возникает, если программа не может загрузить требуемый IDE-файл из папки data в директории игры. Ошибка может возникать, например если в файле default.dat (SA) указана ссылка на несуществующий IDE-файл.

Возможные решения: проверьте наличие указанного IDE-файла.


Ожидалась метка миссии

Сообщения и ошибки

Ожидалась метка миссии

Эта ошибка возникает, если компилятор обнаружил метку миссии, которая должна была стоять в другом месте в соответствии с заголовком файла. Ошибка также может возникнуть, если вы вставили внешний скрипт между миссиями. Внешние скрипты должны следовать после всех миссий.

Возможные решения: проверьте соответствие последовательности расположения миссий в скрипте и заголовке файла. Одна из миссий нарушает эту последовательность.


Метка миссии не найдена

Сообщения и ошибки

Метка миссии не найдена

Если компилятор не смог найти в скрипте начало одной из миссии, указанное в заголовке файла, возникает эта ошибка.

Возможные решения: проверьте наличие в скрипте всех миссий, определенных в заголовке файла. Добавьте пропущенную миссию, либо уберите упоминание о ней в заголовке.


Метка внешнего скрипта не найдена

Сообщения и ошибки

Метка внешнего скрипта не найдена

Если компилятор не смог найти в скрипте начало одного из внешних скриптов, указанное в заголовке файла, возникает эта ошибка.

Возможные решения: проверьте наличие в скрипте всех внешних скриптов, определенных в заголовке файла. Добавьте пропущенный скрипт, либо уберите упоминание о нем в заголовке.


Неверный символ в имени внешнего скрипта

Сообщения и ошибки

Неверный символ в имени внешнего скрипта

Данная ошибка возникает, если вы используете недопустимые символы в имени внешнего скрипта. Допустимыми считаются цифры, латинские буквы и знак подчеркивания («_»).

Возможные решения: откорректируйте имя в соответствии с предъявляемыми требованиями.


Неверный символ в идентификаторе

Сообщения и ошибки

Неверный символ в идентификаторе

Общая ошибка, которая возникает если вы используете недопустимые символы в идентификаторе (имени переменной, метке и т.д.). Допустимыми считаются цифры, латинские буквы и знак подчеркивания («_»).

Возможные решения: откорректируйте идентификатор в соответствии с предъявляемыми требованиями.


Неверный символ в имени объекта

Сообщения и ошибки

Неверный символ в имени объекта

Общая ошибка, которая возникает если вы используете недопустимые символы в имени определяемого объекта. Допустимыми считаются цифры, латинские буквы и знак подчеркивания («_»).

Возможные решения: откорректируйте имя объекта в соответствии с предъявляемыми требованиями.


Неверное число условий. Используйте число от 0 до %0:d или от 21 до 2%0:d

Сообщения и ошибки

Неверное число условий.

Данная ошибка возникает, если вы используете выражение, число условий в котором превышает допустимое число. Максимальное число условий, проверяемых одновременно равно 9.

Возможные решения: отредактируйте число условий в соответствии с предъявляемыми требованиями.


Неверное число условий.

Сообщения и ошибки

Неверное число условий

Данная ошибка возникает в конструкции IF..END, когда вы используете несколько условий одновременно, при этом не указывая связку AND или OR.

Возможные решения: отредактируйте данное выражение, используйте только одно условие, либо укажите связку AND или OR.


Неверное число условий. Максимум %0:d

Сообщения и ошибки

Неверное число условий

Данная ошибка возникает в конструкции IF..END, когда вы используете единственное условие, при этом указывая связку AND или OR. Данные связки используются только в случае одновременной проверки нескольких условий.

Возможные решения: отредактируйте данное выражение, уберите связку либо используйте несколько условий.


Включите опцию проверки условий

Сообщения и ошибки

Включите опцию проверки условий

Данная ошибка возникает, если вы используете выражения со связками AND или OR при выключенной опции проверки условий. Данная функция компилятора работает только при включении этой опции.

Возможные решения: включите опцию проверки условий в настройках программы (F10).


Неверное шестнадцатиричное значение

Сообщения и ошибки

Неверное шестнадцатиричное значение

Данная ошибка возникает в конструкции HEX..END, если вы используете нешестнадцатиричный символ в записи. Шестнадцатиричными символами являются латинские буквы от A до F, а также цифры ( 0..9).

Возможные решения: исправьте указанное значение


Ожидалось условие

Сообщения и ошибки

Ожидалось условие

Общая ошибка, возникающая если вы не указали проверяемое условие после слова while или until. Данные конструкции должны иметь хотя бы одно проверяемое условие. Вы можете также использовать константы True и False в качестве проверяемого условия.

Возможные решения: укажите условие для данной конструкции


Аллокация может быть только для глобальных переменных

Сообщения и ошибки

Аллокация может быть только для глобальных переменных

Данная ошибка возникает, если вы используете неглобальную переменную в команде Alloc. Подобная операция недопустима для данной команды.

Возможные решения: укажите глобальную переменную


Используйте положительное целое значение

Сообщения и ошибки

Используйте положительное целое значение

Общая ошибка, возникающая когда вы используете отрицательное значение или не число, а, например, строку, в том месте, где требуется указать положительное целое число (индексированные переменные, команда Alloc и т.д.).

Возможные решения: укажите корректное положительное число


Слишком много параметров

Сообщения и ошибки

Слишком много параметров

Общая ошибка, возникающая, если вы используете больше параметров, чем это требуется по синтаксису данной команды (например, Sqr).

Возможные решения: проконсультируйтесь с соответствующими топиками и укажите требуемое число параметров.


Неверная конструкция

Сообщения и ошибки

Неверная конструкция

Данная ошибка возникает, когда вы используете часть конструкции вне ее основного положения. Например, такая ошибка возникает, если вы указываете слово ELSE вне конструкции IF..END, что противоречит ее синтаксису.

Возможные решения: проконсультируйтесь с соответствующими топиками и укажите допустимую конструкцию.


Имя модели не может быть использовано

Сообщения и ошибки

Имя модели не может быть использовано

Эта ошибка возникает, когда вы пытаетесь использовать в SCM-файле без заголовка имя модели, значение ID которой не известно компилятору. Чаще всего это происходит, когда вы компилируете CLEO-скрипт с именем модели, которая в оригинальной main.scm содержится в списке DEFINE OBJECT (например, #KEYCARD). Такие #имена в отличие от моделей, которые прописаны в vehicles.ide, peds.ide default.ide, не могут быть скомпилированы.

Самое яркое проявление такой ошибки – в игре вместо ожидаемого вам объекта появляется иконка информации (#INFO).

Возможные решения: используйте числовой идентификатор модели (ID) вместо имени. Например, для #KEYCARD ID = 1581. Найти нужный ID можно в IDE-файлах игры. Также вы можете воспользоваться встроенной в SB функцией конвертации имени модели в ID и наоборот (Ctrl+Alt+H).

См. также FAQ по CLEO 3


Переход на нулевой оффсет

Сообщения и ошибки

Переход на нулевой оффсет

Это сообщение появляется, если в вашем CLEO-скрипте есть переход на метку, расположенную в самом начале скрипта. В игре есть баг, из-за которого такой переход вызывает неверную работу в скрипте. Основным проявлением такой ошибки является эффект начатой заново игры (когда при старте скрипта игра перезапускается заново).

Возможные решения: добавьте в самое начало скрипта (перед меткой) опкод 0000. Этого будет достаточно.

См. также FAQ по CLEO 3


Sanny Builder

Только локальные переменные могут использоваться как индексы массивов в режимах LCS и VCS

Скриптовый движок Liberty City Stories и Vice City Stories допускает только локальные переменные для индексации массивов. Например, такой код будет генерировать ошибку: $array($index,1).

Возможные решения: замените глобальную переменную на локальную: $array(0@,1)


Sanny Builder

Номер aDMA-переменной должен быть кратен 4 в режимах LCS и VCS

Система типов Liberty City Stories и Vice City Stories ограничивает обращение к области хранения глобальных переменных только по оффсетам кратным 4.

Возможные решения: измените ADMA-переменную, чтобы номер был кратен 4, например: &0, &4, &8, и т.д.


Sanny Builder

Глобальная переменная вне допустимых границ

Начиная с версии v3.3.0 Sanny Builder проверяет что глобальные переменные с числовыми номерами находятся в пределах допустимых границ. Таковыми являются номера от $2 до $3FFF, в LCS максимальная переменная $6655, в VCS - $6399.

Возможные решения: измените номер глобальной переменной так, чтобы он был положительным числом в пределах допустимых границ для текущей игры. Также вы можете отключить опцию проверки границ в опциях программы.


// example of using Alloc Function

DEFINE OBJECTS 0
DEFINE MISSIONS 0
DEFINE EXTERNAL_SCRIPTS -1 // Use -1 to not write AAA script
DEFINE UNKNOWN_EMPTY_SEGMENT 0
DEFINE UNKNOWN_THREADS_MEMORY 0

// --------------------
// THE STRIPPED MAIN THREAD
// contains initial info
// --------------------
thread 'MAIN'
 var
  $PLAYER_CHAR : Player
 end
01F0: set_max_wanted_level_to 6
set_wb_check_to 0
00C0: set_current_time 8 0
04E4: unknown_refresh_game_renderer_at 2488.5601 -1666.84
Camera.SetAtPos(2488.5601, -1666.84, 13.38)

alloc($PLAYER_CHAR, 10) // the variable $PLAYER_CHAR will be located at memory address 10

$PLAYER_CHAR = Player.Create(#NULL, 2488.5601, -1666.84, 13.38)

// we know that player's handle was stored at address 10
// so, use DMA to give money to the player

Player.Money($10) += 333

$PLAYER_ACTOR = Actor.EmulateFromPlayer($PLAYER_CHAR)
Camera.SetBehindPlayer
set_weather 0
wait 0
$PLAYER_CHAR.SetClothes("PLAYER_FACE", "HEAD",  Head)
$PLAYER_CHAR.SetClothes("JEANSDENIM", "JEANS", Legs)
$PLAYER_CHAR.SetClothes("SNEAKERBINCBLK", "SNEAKER", Shoes)
$PLAYER_CHAR.SetClothes("VEST", "VEST", Torso)
$PLAYER_CHAR.Build
$PLAYER_CHAR.CanMove = True
fade 1 (out) 0 ms
select_interior 0
016C: restart_if_wasted at 2027.77 -1420.52 15.99 angle 137.0 unknown 0
016D: restart_if_busted at 1550.68 -1675.49 14.51 angle 90.0 unknown 0
end_thread


{
  use macro (Ctrl+J) "headsa"
  to insert a file header
}
{$VERSION 3.0.0000}
thread 'Main'
var
$PLAYER_CHAR: Player
end // var
01F0: set_max_wanted_level_to 6
set_wb_check_to 0
00C0: set_current_time 8 0
04E4: unknown_refresh_game_renderer_at 2488.5601 -1666.84
Camera.SetAtPos(2488.5601, -1666.84, 13.38)
$PLAYER_CHAR = Player.Create(#NULL, 2488.5601, -1666.84, 13.38)
$PLAYER_ACTOR = Actor.EmulateFromPlayer($PLAYER_CHAR)
Camera.SetBehindPlayer
set_weather 0
wait 0 ms
$PLAYER_CHAR.SetClothes("PLAYER_FACE", "HEAD", Head)
$PLAYER_CHAR.SetClothes("JEANSDENIM", "JEANS", Legs)
$PLAYER_CHAR.SetClothes("SNEAKERBINCBLK", "SNEAKER", Shoes)
$PLAYER_CHAR.SetClothes("VEST", "VEST", Torso)
$PLAYER_CHAR.Build
$PLAYER_CHAR.CanMove = True
fade 1 (out) 0 ms
select_interior 0
0629: change_stat 181 (islands unlocked) to 4
016C: restart_if_wasted at 2027.77 -1420.52 15.99 angle 137.0 unknown 0
016D: restart_if_busted at 1550.68 -1675.49 14.51 angle 90.0 unknown 0
0180: set_on_mission_flag_to $ONMISSION
// put your create_thread commands here
create_thread @TEST1 // создаём поток
end_thread

// put your mission mods here

:TEST1
thread 'TEST1'
$391 = 0 // integer values

:TEST1_18
wait 0
if
00E1: key_pressed 0 8 //Group CTRL Forward
jf @TEST1_46
08BA: set $391 bit 0
jump @TEST1_102

:TEST1_46
wait 0
if
00E1: key_pressed 0 9 //Group CTRL back
jf @TEST1_74
08BA: set $391 bit 1
jump @TEST1_102

:TEST1_74
wait 0
if
00E1: key_pressed 0 10 //conversation - no
jf @TEST1_102
08BA: set $391 bit 2

:TEST1_102
wait 0
if
08B4: test $391 bit 0 // проверяем равен ли нулевой bit единице
jf @TEST1_235 //если нет то переходим на следующую метку
Player.SetClothes($PLAYER_CHAR, "PLAYER_TORSO", "TORSO", Torso)
Player.SetClothes($PLAYER_CHAR, "AFRO", "AFRO", Head)
Player.SetClothes($PLAYER_CHAR, "BBSHORTRED", "BOXINGSHORT", Legs)
Player.SetClothes($PLAYER_CHAR, "COWBOYBOOT2", "BIKER", Shoes)
Player.Build($PLAYER_CHAR)
0110: clear_player $PLAYER_CHAR wanted_level
jump @TEST1_510

:TEST1_235
wait 0
if
08B4: test $391 bit 1
jf @TEST1_372
Player.SetClothes($PLAYER_CHAR, "BBJERSEY", "SLEEVT", Torso)
Player.SetClothes($PLAYER_CHAR, "GROOVECUT", "GROOVECUT", Head)
Player.SetClothes($PLAYER_CHAR, "SUIT1TRGANG", "SUIT1TR", Legs)
Player.SetClothes($PLAYER_CHAR, "SHOEDRESSBRN", "SHOE", Shoes)
Player.Build($PLAYER_CHAR)
0110: clear_player $PLAYER_CHAR wanted_level
jump @TEST1_510

:TEST1_372
wait 0
if
08B4: test $391 bit 2
jf @TEST1_510
Player.SetClothes($PLAYER_CHAR, "TSHIRTERISYELL", "TSHIRT", Torso)
Player.SetClothes($PLAYER_CHAR, "WEDGE", "WEDGE", Head)
Player.SetClothes($PLAYER_CHAR, "BBSHORTWHT", "BOXINGSHORT", Legs)
Player.SetClothes($PLAYER_CHAR, "FLIPFLOP", "FLIPFLOP", Shoes)
Player.Build($PLAYER_CHAR)
0110: clear_player $PLAYER_CHAR wanted_level

:TEST1_510
08C0: clear $391 bit 0
08C0: clear $391 bit 1
08C0: clear $391 bit 2
jump @TEST1_18


// This file was decompiled using sascm.ini published by Seemann (http://sannybuilder.com/files/SASCM.rar) on 23.02.2007
DEFINE OBJECTS 1
DEFINE OBJECT SANNY BUILDER v. 2.99f

DEFINE MISSIONS 0

DEFINE EXTERNAL_SCRIPTS 0 // Use -1 in order not to compile AAA script

DEFINE UNKNOWN_EMPTY_SEGMENT 0

DEFINE UNKNOWN_THREADS_MEMORY 0

{$VERSION 3.1.0020}

//-------------MAIN---------------
thread 'MAIN'
fade 0 0
01F0: set_max_wanted_level_to 6
set_wb_check_to 0
00C0: set_current_time_hours_to 8 minutes_to 0
04E4: unknown_refresh_game_renderer_at 2488.56 -1666.84
Camera.SetAtPos(2488.56, -1666.84, 13.38)
$PLAYER_CHAR = Player.Create(#NULL, 2488.56, -1666.84, 13.38)
$PLAYER_ACTOR = Actor.EmulateFromPlayer($PLAYER_CHAR)
07AF: $PLAYER_GROUP = player $PLAYER_CHAR group
Camera.SetBehindPlayer
set_weather 0
wait 0
Player.SetClothes($PLAYER_CHAR, "PLAYER_FACE", "HEAD", Head)
Player.SetClothes($PLAYER_CHAR, "JEANSDENIM", "JEANS", Legs)
Player.SetClothes($PLAYER_CHAR, "SNEAKERBINCBLK", "SNEAKER", Shoes)
Player.SetClothes($PLAYER_CHAR, "VEST", "VEST", Torso)
Player.Build($PLAYER_CHAR)
Player.CanMove($PLAYER_CHAR) = True
//fade 1 0
select_interior 0
0629: change_integer_stat 181 to 4
016C: restart_if_wasted_at 2027.77 -1420.52 15.99 angle 137.0 town_number 0
016D: restart_if_busted_at 1550.68 -1675.49 14.51 angle 90.0 town_number 0
0180: set_on_mission_flag_to $ONMISSION // Note: your missions have to use the variable defined here
03E6: remove_text_box
create_thread @CreateActor
end_thread

:CreateActor
thread "CreateActor"
//даем название потоку, это нужно для того, чтобы была возможность вызывать этот поток из любого другого потока или миссии
player.CanMove($PLAYER_CHAR)=False
//отключаем управление игроком
02A3: toggle_widescreen 1
// включаем широкоэкранный режим
Model.Load(#CSHER)
Model.Load(#WMOPJ)
// запрашиваем модели
038B: load_requested_models
// загружаем запрошенные модели

:CreateActor_31
wait 0
if and
// проверка выполнится, если ВСЕ условия, входящие в нее, верны
   Model.Available(#CSHER)
   Model.Available(#WMOPJ)
//проверяем загружены ли модели
jf @CreateActor_31
//если нет, то идем назад на метку @CreateActor_31
wait 250
$acror1 = Actor.Create(Cop, #CSHER, 2484.56, -1665.84, 12.28)
 //создаем актера в заданных координатах
Actor.Health($acror1) = 300
//устанавливаем здоровье актеру $acror1
$acror1_ANGLE = Actor.Angle($acror1)
//записываем в переменную $acror1_ANGLE угол актера $acror1
07FE: set_actor $acror1 fighting_style_to 7 6
//устанавливаем стиль борьбы актеру $acror1
04C4: store_coords_to $X $Y $Z from_actor $acror1 with_offset 0.0 2.0 0.0
//создаем координаты $X $Y $Z относительно актёра $acror1 со смещением 0.0 2.0 0.0
02CE: $Z = ground_z_at $X $Y $Z
//получить Z земли_для 3D точки $X $Y $Z,
// это нужно для того, чтобы актер $acror2 создавался на земле, а не падал на нее
04C4: store_coords_to $Camera_X1 $Camera_Y2 $Camera_Z3 from_actor $PLAYER_ACTOR with_offset 0.0 0.0 2.0
//создаем координаты камеры относительно игрока
$acror1_ANGLE -= 180.0
//необходимо для того, чтобы актер $acror2 был повернут лицом к $acror1
$acror2 = Actor.Create(Dealer, #WMOPJ, $X, $Y, $Z)
//создаем $acror2 в координатах $X, $Y, $Z с учетои Z земли
Actor.Angle($acror2) = $acror1_ANGLE
//устанавливаем угол $acror1_ANGLE актеру $acror2
Actor.Health($acror2) = 1000
//устанавливаем здоровье актеру $acror2
07FE: set_actor $acror2 fighting_style_to 6 6
//устанавливаем стиль борьбы актеру $acror2
Camera.SetPosition($Camera_X1, $Camera_Y2, $Camera_Z3, 0.0, 0.0, 0.0)
// устанавливаем камеру
Camera.OnPed($acror1, 15, 2)
//камера будет направлена на актера $acror1
fade 1 0
wait 2000
Actor.PutAt($PLAYER_ACTOR, 2494.767, -1685.347, 13.5118)
//перемещаем игрока, чтобы не мешал
05E2: AS_actor $acror2 kill_actor $acror1   //актер $acror2 атакует $acror1
05E2: AS_actor $acror1 kill_actor $acror2

:CreateActor_310
wait 0
if or
//проверка сработает тогда, когда будет выполнено одно из условий
   Actor.Dead($acror1)
   // проверяем умер ли актер $acror1
   Actor.Dead($acror2)
   // проверяем умер ли актер $acror1
jf @CreateActor_310
wait 1000
Actor.DestroyWithFade($acror1)
//удаляем актера (Актёр исчезает как призрак)
Actor.DestroyWithFade($acror2)
Model.Destroy(#CSHER)
Model.Destroy(#WMOPJ)
//удаляем модели
Actor.PutAt($PLAYER_ACTOR, 2488.56, -1666.84, 12.38)
//возвращаем игрока на прежнее место
player.CanMove($PLAYER_CHAR)= true
//включаем возможность управления игроком
wait 1000
Camera.Restore_WithJumpCut
//восстановить последнюю позицию камеры
02A3: toggle_widescreen 0
//отключаем широкоэкранный режим
end_thread  // завершаем поток


{$CLEO .cm}

:MyMission
thread "MyMission"
gosub @MissionStart
if
  wasted_or_busted
then
  gosub @MissionFailed
end
gosub @MissionCleanup
end_thread

:MissionStart
gosub @MissionPassed
return

:MissionPassed
wait 500
01E3: text_1number_styled 'M_PASSD' 0 5000 ms 1 // MISSION PASSED!
return

:MissionFailed
00BA: text_styled 'M_FAIL' 5000 ms 1 // ~r~MISSION FAILED!
return

:MissionCleanup
$ONMISSION = 0 // integer values
mission_cleanup
return


{$CLEO}
var
  $Player_Actor: Actor
  $Player_Char: Player
  0@: Integer
end
const
  I = 0@
end
0000:
while true
  if 0AB0:  key_pressed 0x4A // VK_J
  then
    select_interior 0
    $Player_Actor.PutAt(1945.2737, -2300.6677, 13.5469)
    Camera.SetAtPos(1945.6265, -2356.5925, 13.5469) // Для убыстрения загрузки
    wait 500
    015D: set_gamespeed 0.3333333 // Замедление времени
    Camera.SetPosition(1945.1906, -2335.4775, 18.3014, 0.0, 0.0, 0.0)
    Camera.PointAt(1945.6265, -2356.5925, 13.5469, 2)
    for I = 0 to 6
      020C: create_explosion_with_radius 0 at 1945.6265 -2356.5925 13.5469
    end // для оставления чёрного следа
    wait 3000
    0826: enable_hud 0     // убираем HUD
    0581: enable_radar 0   //
    for I = 0 to 13
      031a: remove_all_fires // Для того, что-бы огонь не мешал посмотреть на взрывы
      0980: extinguish_all_fires_at 1945.6265 -2356.5925 13.5469 radius 10.0
      020C: create_explosion_with_radius I at 1945.6265 -2356.5925 13.5469
      0513: show_text_box_1number 'NUMBER' number I // Вывод текст-бокса с номером взрыва
      wait 2600
    end
    Camera.Restore_WithJumpCut
    Camera.SetBehindPlayer
    015D: set_gamespeed 1.0
    0826: enable_hud 1
    0581: enable_radar 1
  end
  wait 25 // что-бы не зависла
end


// This file was decompiled using SASCM.INI published by Seemann (http://sannybuilder.com/files/SASCM.rar) on 23.02.2007
DEFINE OBJECTS 1
DEFINE OBJECT SANNY BUILDER v. 2.99F

DEFINE MISSIONS 0

DEFINE EXTERNAL_SCRIPTS 1 // Use -1 in order not to compile AAA script
DEFINE SCRIPT MILITIA AT @MILITIA      // 0

DEFINE UNKNOWN_EMPTY_SEGMENT 0

DEFINE UNKNOWN_THREADS_MEMORY 0

{$VERSION 3.1.0020}

//-------------MAIN---------------
03A4: name_thread 'MAIN'
01F0: set_max_wanted_level_to 6
0111: toggle_wasted_busted_check 0
00C0: set_current_time_hours_to 8 minutes_to 0
04E4: unknown_refresh_game_renderer_at 2488.56 -1666.84
03CB: set_rendering_origin_at 2488.56 -1666.84 13.38
0053: $PLAYER_CHAR = create_player #NULL at 2488.56 -1666.84 13.38
01F5: $PLAYER_ACTOR = create_player_actor $PLAYER_CHAR
07AF: $PLAYER_GROUP = player $PLAYER_CHAR group
0373: set_camera_directly_behind_player
01B6: set_weather 0
0001: wait 0 ms
087B: set_player $PLAYER_CHAR clothes_texture "PLAYER_FACE" model "HEAD" body_part 1
087B: set_player $PLAYER_CHAR clothes_texture "JEANSDENIM" model "JEANS" body_part 2
087B: set_player $PLAYER_CHAR clothes_texture "SNEAKERBINCBLK" model "SNEAKER" body_part 3
087B: set_player $PLAYER_CHAR clothes_texture "VEST" model "VEST" body_part 0
070D: rebuild_player $PLAYER_CHAR
01B4: toggle_player $PLAYER_CHAR can_move 1
016A: fade 1 time 0
04BB: select_interior 0
0629: change_integer_stat 181 to 4
016C: restart_if_wasted_at 2027.77 -1420.52 15.99 angle 137.0 town_number 0
016D: restart_if_busted_at 1550.68 -1675.49 14.51 angle 90.0 town_number 0
0180: set_on_mission_flag_to $ONMISSION // Note: your missions have to use the variable defined here
03E6: remove_text_box
0928: init_external_script_trigger 0 (MILITIA) with_actor_model #BFYST priority 100
08E8: assign_external_script_handle 'MILITIA' to_model #BFYST
004E: end_thread

//-------------External script 0 (MILITIA)---------------

:MILITIA
03A4: name_thread 'MILITIA'
0006: 2@ = 0

:MILITIA_18
00D6: if
8248:   not model #COLT45 available
004D: jump_if_false @MILITIA_46
0247: load_model #COLT45
0002: jump @MILITIA_18

:MILITIA_46
00D6: if
8118:   not actor 0@ dead
004D: jump_if_false @MILITIA_145
01B2: give_actor 0@ weapon 22 ammo 99999999 // Load the weapon model before using this
01B9: set_actor 0@ armed_weapon_to 0
00D6: if
0491:   actor 0@ has_weapon 3
004D: jump_if_false @MILITIA_106
0555: remove_weapon 3 from_actor 0@

:MILITIA_106
02E2: set_actor 0@ weapon_accuracy_to 80
0978: copy_decision_maker 65537 to $9538
0708: add_decision_maker $9538 event 27
0708: add_decision_maker $9538 event 48
060B: set_actor 0@ decision_maker_to $9538

:MILITIA_145
0006: 4@ = 0

:MILITIA_152
0001: wait 0 ms
00D6: if and
8118:   not actor 0@ dead
0256:   player $PLAYER_CHAR defined
004D: jump_if_false @MILITIA_216
00D6: if
810F:   not player $PLAYER_CHAR wanted_level > 0
004D: jump_if_false @MILITIA_551
0050: gosub @MILITIA_230
0002: jump @MILITIA_209

:MILITIA_209
0002: jump @MILITIA_223

:MILITIA_216
0002: jump @MILITIA_717

:MILITIA_223
0002: jump @MILITIA_152

:MILITIA_230
0871: init_jump_table 4@ total_jumps 3 default_jump 0 @MILITIA_549 jumps 0 @MILITIA_293 1 @MILITIA_356 2 @MILITIA_516 -1 @MILITIA_549 -1 @MILITIA_549 -1 @MILITIA_549 -1 @MILITIA_549

:MILITIA_293
062E: unknown_get_actor 0@ task 1502 status_store_to 2@ // ret 7 if not found
00D6: if
04A4:   2@ == 7 // @ == any
004D: jump_if_false @MILITIA_349
05DE: AS_actor 0@ walk_around_ped_path
0006: 33@ = 0
0006: 6@ = 5000
000A: 4@ += 1

:MILITIA_349
0002: jump @MILITIA_549

:MILITIA_356
00D6: if
002D:   33@ >= 6@ // (int)
004D: jump_if_false @MILITIA_509
0209: 2@ = random_int_in_ranges 1 10
00D6: if
0019:   2@ > 5
004D: jump_if_false @MILITIA_453
062E: unknown_get_actor 0@ task 1481 status_store_to 2@ // ret 7 if not found
00D6: if
04A4:   2@ == 7 // @ == any
004D: jump_if_false @MILITIA_446
05C9: AS_actor 0@ on_guard -1 ms
0006: 6@ = 5000

:MILITIA_446
0002: jump @MILITIA_495

:MILITIA_453
062E: unknown_get_actor 0@ task 1502 status_store_to 2@ // ret 7 if not found
00D6: if
04A4:   2@ == 7 // @ == any
004D: jump_if_false @MILITIA_495
05DE: AS_actor 0@ walk_around_ped_path
0006: 6@ = 5000

:MILITIA_495
0006: 33@ = 0
000A: 4@ += 1

:MILITIA_509
0002: jump @MILITIA_549

:MILITIA_516
00D6: if
002D:   33@ >= 6@ // (int)
004D: jump_if_false @MILITIA_542
0006: 4@ = 1

:MILITIA_542
0002: jump @MILITIA_549

:MILITIA_549
0051: return

:MILITIA_551
0001: wait 0 ms
00D6: if and
8118:   not actor 0@ dead
0256:   player $PLAYER_CHAR defined
004D: jump_if_false @MILITIA_703
00D6: if
02E0:   actor $PLAYER_ACTOR aggressive
004D: jump_if_false @MILITIA_650
01B9: set_actor 0@ armed_weapon_to 22
062E: unknown_get_actor 0@ task 1588 status_store_to 5@ // ret 7 if not found
00D6: if
04A4:   5@ == 7 // @ == any
004D: jump_if_false @MILITIA_643
0634: AS_actor 0@ attack_using_weapon_actor $PLAYER_ACTOR unknown 1 unknown 4000 unknown 60

:MILITIA_643
0002: jump @MILITIA_696

:MILITIA_650
062E: unknown_get_actor 0@ task 1506 status_store_to 5@ // ret 7 if not found
00D6: if
04A4:   5@ == 7 // @ == any
004D: jump_if_false @MILITIA_696
07FE: set_actor 0@ fighting_style_to 7 6
05E2: AS_actor 0@ kill_actor $PLAYER_ACTOR

:MILITIA_696
0002: jump @MILITIA_710

:MILITIA_703
0002: jump @MILITIA_717

:MILITIA_710
0002: jump @MILITIA_551

:MILITIA_717
065C: remove_references_to_decision_maker $9538
01C2: remove_references_to_actor 0@ // Like turning an actor into a random pedestrian
004E: end_thread


// This file was decompiled using SASCM.INI published by Seemann (http://sannybuilder.com/files/SASCM.rar) on 23.02.2007
DEFINE OBJECTS 1
DEFINE OBJECT SANNY BUILDER v. 2.99F

DEFINE MISSIONS 0

DEFINE EXTERNAL_SCRIPTS 1 // Use -1 in order not to compile AAA script
DEFINE SCRIPT MILITIA AT @MILITIA      // 0

DEFINE UNKNOWN_EMPTY_SEGMENT 0

DEFINE UNKNOWN_THREADS_MEMORY 0

{$VERSION 3.1.0020}

//-------------MAIN---------------
03A4: name_thread 'MAIN'
01F0: set_max_wanted_level_to 6
0111: toggle_wasted_busted_check 0
00C0: set_current_time_hours_to 8 minutes_to 0
04E4: unknown_refresh_game_renderer_at 2488.56 -1666.84
03CB: set_rendering_origin_at 2488.56 -1666.84 13.38
0053: $PLAYER_CHAR = create_player #NULL at 2488.56 -1666.84 13.38
01F5: $PLAYER_ACTOR = create_player_actor $PLAYER_CHAR
07AF: $PLAYER_GROUP = player $PLAYER_CHAR group
0373: set_camera_directly_behind_player
01B6: set_weather 0
0001: wait 0 ms
087B: set_player $PLAYER_CHAR clothes_texture "PLAYER_FACE" model "HEAD" body_part 1
087B: set_player $PLAYER_CHAR clothes_texture "JEANSDENIM" model "JEANS" body_part 2
087B: set_player $PLAYER_CHAR clothes_texture "SNEAKERBINCBLK" model "SNEAKER" body_part 3
087B: set_player $PLAYER_CHAR clothes_texture "VEST" model "VEST" body_part 0
070D: rebuild_player $PLAYER_CHAR
01B4: toggle_player $PLAYER_CHAR can_move 1
016A: fade 1 time 0
04BB: select_interior 0
0629: change_integer_stat 181 to 4
016C: restart_if_wasted_at 2027.77 -1420.52 15.99 angle 137.0 town_number 0
016D: restart_if_busted_at 1550.68 -1675.49 14.51 angle 90.0 town_number 0
0180: set_on_mission_flag_to $ONMISSION // Note: your missions have to use the variable defined here
03E6: remove_text_box

004F: create_thread @STARTEX
004E: end_thread

:STARTEX
03A4: name_thread 'STARTEX'
00D6: if and
0038:   $ONMISSION == 0
0256:   player $PLAYER_CHAR defined
004D: jump_if_false @STARTEX_109
0226: 0@ = actor $PLAYER_ACTOR health
00D6: if
8039:   not  0@ == 0
004D: jump_if_false @STARTEX_120
0926: $Script_Status = external_script_status 0 (MILITIA)
00D6: if
0038:   $Script_Status == 0
004D: jump_if_false @STARTEX_109
08A9: load_external_script 0 (MILITIA)
00D6: if
08AB:   external_script 0 (MILITIA) loaded
004D: jump_if_false @STARTEX_109
0913: run_external_script 0 (MILITIA)

:STARTEX_109
0001: wait 0 ms
0002: jump @STARTEX

:STARTEX_120
090F: end_external_script 0 (MILITIA)
0002: jump @STARTEX

//-------------External script 0 (MILITIA)---------------

:MILITIA
03A4: name_thread 'MILITIA'
0006: 2@ = 0

:MILITIA_18
00D6: if
8248:   not model #COLT45 available
004D: jump_if_false @MILITIA_46
0247: load_model #COLT45
0002: jump @MILITIA_18

:MILITIA_46
00D6: if
8118:   not actor 0@ dead
004D: jump_if_false @MILITIA_145
01B2: give_actor 0@ weapon 22 ammo 99999999 // Load the weapon model before using this
01B9: set_actor 0@ armed_weapon_to 0
00D6: if
0491:   actor 0@ has_weapon 3
004D: jump_if_false @MILITIA_106
0555: remove_weapon 3 from_actor 0@

:MILITIA_106
02E2: set_actor 0@ weapon_accuracy_to 80
0978: copy_decision_maker 65537 to $9538
0708: add_decision_maker $9538 event 27
0708: add_decision_maker $9538 event 48
060B: set_actor 0@ decision_maker_to $9538

:MILITIA_145
0006: 4@ = 0

:MILITIA_152
0001: wait 0 ms
00D6: if and
8118:   not actor 0@ dead
0256:   player $PLAYER_CHAR defined
004D: jump_if_false @MILITIA_216
00D6: if
810F:   not player $PLAYER_CHAR wanted_level > 0
004D: jump_if_false @MILITIA_551
0050: gosub @MILITIA_230
0002: jump @MILITIA_209

:MILITIA_209
0002: jump @MILITIA_223

:MILITIA_216
0002: jump @MILITIA_717

:MILITIA_223
0002: jump @MILITIA_152

:MILITIA_230
0871: init_jump_table 4@ total_jumps 3 default_jump 0 @MILITIA_549 jumps 0 @MILITIA_293 1 @MILITIA_356 2 @MILITIA_516 -1 @MILITIA_549 -1 @MILITIA_549 -1 @MILITIA_549 -1 @MILITIA_549

:MILITIA_293
062E: unknown_get_actor 0@ task 1502 status_store_to 2@ // ret 7 if not found
00D6: if
04A4:   2@ == 7 // @ == any
004D: jump_if_false @MILITIA_349
05DE: AS_actor 0@ walk_around_ped_path
0006: 33@ = 0
0006: 6@ = 5000
000A: 4@ += 1

:MILITIA_349
0002: jump @MILITIA_549

:MILITIA_356
00D6: if
002D:   33@ >= 6@ // (int)
004D: jump_if_false @MILITIA_509
0209: 2@ = random_int_in_ranges 1 10
00D6: if
0019:   2@ > 5
004D: jump_if_false @MILITIA_453
062E: unknown_get_actor 0@ task 1481 status_store_to 2@ // ret 7 if not found
00D6: if
04A4:   2@ == 7 // @ == any
004D: jump_if_false @MILITIA_446
05C9: AS_actor 0@ on_guard -1 ms
0006: 6@ = 5000

:MILITIA_446
0002: jump @MILITIA_495

:MILITIA_453
062E: unknown_get_actor 0@ task 1502 status_store_to 2@ // ret 7 if not found
00D6: if
04A4:   2@ == 7 // @ == any
004D: jump_if_false @MILITIA_495
05DE: AS_actor 0@ walk_around_ped_path
0006: 6@ = 5000

:MILITIA_495
0006: 33@ = 0
000A: 4@ += 1

:MILITIA_509
0002: jump @MILITIA_549

:MILITIA_516
00D6: if
002D:   33@ >= 6@ // (int)
004D: jump_if_false @MILITIA_542
0006: 4@ = 1

:MILITIA_542
0002: jump @MILITIA_549

:MILITIA_549
0051: return

:MILITIA_551
0001: wait 0 ms
00D6: if and
8118:   not actor 0@ dead
0256:   player $PLAYER_CHAR defined
004D: jump_if_false @MILITIA_703
00D6: if
02E0:   actor $PLAYER_ACTOR aggressive
004D: jump_if_false @MILITIA_650
01B9: set_actor 0@ armed_weapon_to 22
062E: unknown_get_actor 0@ task 1588 status_store_to 5@ // ret 7 if not found
00D6: if
04A4:   5@ == 7 // @ == any
004D: jump_if_false @MILITIA_643
0634: AS_actor 0@ attack_using_weapon_actor $PLAYER_ACTOR unknown 1 unknown 4000 unknown 60

:MILITIA_643
0002: jump @MILITIA_696

:MILITIA_650
062E: unknown_get_actor 0@ task 1506 status_store_to 5@ // ret 7 if not found
00D6: if
04A4:   5@ == 7 // @ == any
004D: jump_if_false @MILITIA_696
07FE: set_actor 0@ fighting_style_to 7 6
05E2: AS_actor 0@ kill_actor $PLAYER_ACTOR

:MILITIA_696
0002: jump @MILITIA_710

:MILITIA_703
0002: jump @MILITIA_717

:MILITIA_710
0002: jump @MILITIA_551

:MILITIA_717
065C: remove_references_to_decision_maker $9538
01C2: remove_references_to_actor 0@ // Like turning an actor into a random pedestrian
004E: end_thread


// This file was decompiled using SASCM.INI published by Seemann (http://sannybuilder.com/files/SASCM.rar) on 23.02.2007
DEFINE OBJECTS 1
DEFINE OBJECT SANNY BUILDER v. 2.99F

DEFINE MISSIONS 0

DEFINE EXTERNAL_SCRIPTS 1 // Use -1 in order not to compile AAA script
DEFINE SCRIPT MILITIA AT @MILITIA      // 0

DEFINE UNKNOWN_EMPTY_SEGMENT 0

DEFINE UNKNOWN_THREADS_MEMORY 0

{$VERSION 3.1.0020}

//-------------MAIN---------------
03A4: name_thread 'MAIN'
01F0: set_max_wanted_level_to 6
0111: toggle_wasted_busted_check 0
00C0: set_current_time_hours_to 8 minutes_to 0
04E4: unknown_refresh_game_renderer_at 2488.56 -1666.84
03CB: set_rendering_origin_at 2488.56 -1666.84 13.38
0053: $PLAYER_CHAR = create_player #NULL at 2488.56 -1666.84 13.38
01F5: $PLAYER_ACTOR = create_player_actor $PLAYER_CHAR
07AF: $PLAYER_GROUP = player $PLAYER_CHAR group
0373: set_camera_directly_behind_player
01B6: set_weather 0
0001: wait 0 ms
087B: set_player $PLAYER_CHAR clothes_texture "PLAYER_FACE" model "HEAD" body_part 1
087B: set_player $PLAYER_CHAR clothes_texture "JEANSDENIM" model "JEANS" body_part 2
087B: set_player $PLAYER_CHAR clothes_texture "SNEAKERBINCBLK" model "SNEAKER" body_part 3
087B: set_player $PLAYER_CHAR clothes_texture "VEST" model "VEST" body_part 0
070D: rebuild_player $PLAYER_CHAR
01B4: toggle_player $PLAYER_CHAR can_move 1
016A: fade 1 time 0
04BB: select_interior 0
0629: change_integer_stat 181 to 4
016C: restart_if_wasted_at 2027.77 -1420.52 15.99 angle 137.0 town_number 0
016D: restart_if_busted_at 1550.68 -1675.49 14.51 angle 90.0 town_number 0
0180: set_on_mission_flag_to $ONMISSION // Note: your missions have to use the variable defined here
03E6: remove_text_box
004F: create_thread @STARTEX
004E: end_thread

:STARTEX
03A4: name_thread 'STARTEX'
00D6: if and
0038:   $ONMISSION == 0
0256:   player $PLAYER_CHAR defined
004D: jump_if_false @STARTEX_159
0226: 0@ = actor $PLAYER_ACTOR health
00D6: if
8039:   not  0@ == 0
004D: jump_if_false @STARTEX_170
0926: $Script_Status = external_script_status 0 (MILITIA)
00D6: if
0038:   $Script_Status == 0
004D: jump_if_false @STARTEX_159
08A9: load_external_script 0 (MILITIA)
00D6: if
08AB:   external_script 0 (MILITIA) loaded
004D: jump_if_false @STARTEX_159
04C4: store_coords_to 2@ 3@ 4@ from_actor $PLAYER_ACTOR with_offset 1.0 3.0 -0.9
009A: 1@ = create_actor_pedtype 4 model #MALE01 at 2@ 3@ 4@
0913: run_external_script 0 (MILITIA) 1@

:STARTEX_159
0001: wait 0 ms
0002: jump @STARTEX

:STARTEX_170
090F: end_external_script 0 (MILITIA)
0001: wait 0 ms
0002: jump @STARTEX

//-------------External script 0 (MILITIA)---------------

:MILITIA
03A4: name_thread 'MILITIA'
0006: 2@ = 0

:MILITIA_18
00D6: if
8248:   not model #COLT45 available
004D: jump_if_false @MILITIA_46
0247: load_model #COLT45
0002: jump @MILITIA_18

:MILITIA_46
00D6: if
8118:   not actor 0@ dead
004D: jump_if_false @MILITIA_145
01B2: give_actor 0@ weapon 22 ammo 99999999 // Load the weapon model before using this
01B9: set_actor 0@ armed_weapon_to 0
00D6: if
0491:   actor 0@ has_weapon 3
004D: jump_if_false @MILITIA_106
0555: remove_weapon 3 from_actor 0@

:MILITIA_106
02E2: set_actor 0@ weapon_accuracy_to 80
0978: copy_decision_maker 65537 to $9538
0708: add_decision_maker $9538 event 27
0708: add_decision_maker $9538 event 48
060B: set_actor 0@ decision_maker_to $9538

:MILITIA_145
0006: 4@ = 0

:MILITIA_152
0001: wait 0 ms
00D6: if and
8118:   not actor 0@ dead
0256:   player $PLAYER_CHAR defined
004D: jump_if_false @MILITIA_216
00D6: if
810F:   not player $PLAYER_CHAR wanted_level > 0
004D: jump_if_false @MILITIA_551
0050: gosub @MILITIA_230
0002: jump @MILITIA_209

:MILITIA_209
0002: jump @MILITIA_223

:MILITIA_216
0002: jump @MILITIA_717

:MILITIA_223
0002: jump @MILITIA_152

:MILITIA_230
0871: init_jump_table 4@ total_jumps 3 default_jump 0 @MILITIA_549 jumps 0 @MILITIA_293 1 @MILITIA_356 2 @MILITIA_516 -1 @MILITIA_549 -1 @MILITIA_549 -1 @MILITIA_549 -1 @MILITIA_549

:MILITIA_293
062E: unknown_get_actor 0@ task 1502 status_store_to 2@ // ret 7 if not found
00D6: if
04A4:   2@ == 7 // @ == any
004D: jump_if_false @MILITIA_349
05DE: AS_actor 0@ walk_around_ped_path
0006: 33@ = 0
0006: 6@ = 5000
000A: 4@ += 1

:MILITIA_349
0002: jump @MILITIA_549

:MILITIA_356
00D6: if
002D:   33@ >= 6@ // (int)
004D: jump_if_false @MILITIA_509
0209: 2@ = random_int_in_ranges 1 10
00D6: if
0019:   2@ > 5
004D: jump_if_false @MILITIA_453
062E: unknown_get_actor 0@ task 1481 status_store_to 2@ // ret 7 if not found
00D6: if
04A4:   2@ == 7 // @ == any
004D: jump_if_false @MILITIA_446
05C9: AS_actor 0@ on_guard -1 ms
0006: 6@ = 5000

:MILITIA_446
0002: jump @MILITIA_495

:MILITIA_453
062E: unknown_get_actor 0@ task 1502 status_store_to 2@ // ret 7 if not found
00D6: if
04A4:   2@ == 7 // @ == any
004D: jump_if_false @MILITIA_495
05DE: AS_actor 0@ walk_around_ped_path
0006: 6@ = 5000

:MILITIA_495
0006: 33@ = 0
000A: 4@ += 1

:MILITIA_509
0002: jump @MILITIA_549

:MILITIA_516
00D6: if
002D:   33@ >= 6@ // (int)
004D: jump_if_false @MILITIA_542
0006: 4@ = 1

:MILITIA_542
0002: jump @MILITIA_549

:MILITIA_549
0051: return

:MILITIA_551
0001: wait 0 ms
00D6: if and
8118:   not actor 0@ dead
0256:   player $PLAYER_CHAR defined
004D: jump_if_false @MILITIA_703
00D6: if
02E0:   actor $PLAYER_ACTOR aggressive
004D: jump_if_false @MILITIA_650
01B9: set_actor 0@ armed_weapon_to 22
062E: unknown_get_actor 0@ task 1588 status_store_to 5@ // ret 7 if not found
00D6: if
04A4:   5@ == 7 // @ == any
004D: jump_if_false @MILITIA_643
0634: AS_actor 0@ attack_using_weapon_actor $PLAYER_ACTOR unknown 1 unknown 4000 unknown 60

:MILITIA_643
0002: jump @MILITIA_696

:MILITIA_650
062E: unknown_get_actor 0@ task 1506 status_store_to 5@ // ret 7 if not found
00D6: if
04A4:   5@ == 7 // @ == any
004D: jump_if_false @MILITIA_696
07FE: set_actor 0@ fighting_style_to 7 6
05E2: AS_actor 0@ kill_actor $PLAYER_ACTOR

:MILITIA_696
0002: jump @MILITIA_710

:MILITIA_703
0002: jump @MILITIA_717

:MILITIA_710
0002: jump @MILITIA_551

:MILITIA_717
065C: remove_references_to_decision_maker $9538
01C2: remove_references_to_actor 0@ // Like turning an actor into a random pedestrian
004E: end_thread


// This file was decompiled using SASCM.INI published by Seemann (http://sannybuilder.com/files/SASCM.rar) on 23.02.2007
DEFINE OBJECTS 1
DEFINE OBJECT SANNY BUILDER v. 2.99F

DEFINE MISSIONS 0

DEFINE EXTERNAL_SCRIPTS 1 // Use -1 in order not to compile AAA script
DEFINE SCRIPT MILITIA AT @MILITIA      // 0

DEFINE UNKNOWN_EMPTY_SEGMENT 0

DEFINE UNKNOWN_THREADS_MEMORY 0

{$VERSION 3.1.0020}

//-------------MAIN---------------
03A4: name_thread 'MAIN'
01F0: set_max_wanted_level_to 6
0111: toggle_wasted_busted_check 0
00C0: set_current_time_hours_to 8 minutes_to 0
04E4: unknown_refresh_game_renderer_at 2488.56 -1666.84
03CB: set_rendering_origin_at 2488.56 -1666.84 13.38
0053: $PLAYER_CHAR = create_player #NULL at 2488.56 -1666.84 13.38
01F5: $PLAYER_ACTOR = create_player_actor $PLAYER_CHAR
07AF: $PLAYER_GROUP = player $PLAYER_CHAR group
0373: set_camera_directly_behind_player
01B6: set_weather 0
0001: wait 0 ms
087B: set_player $PLAYER_CHAR clothes_texture "PLAYER_FACE" model "HEAD" body_part 1
087B: set_player $PLAYER_CHAR clothes_texture "JEANSDENIM" model "JEANS" body_part 2
087B: set_player $PLAYER_CHAR clothes_texture "SNEAKERBINCBLK" model "SNEAKER" body_part 3
087B: set_player $PLAYER_CHAR clothes_texture "VEST" model "VEST" body_part 0
070D: rebuild_player $PLAYER_CHAR
01B4: toggle_player $PLAYER_CHAR can_move 1
016A: fade 1 time 0
04BB: select_interior 0
0629: change_integer_stat 181 to 4
016C: restart_if_wasted_at 2027.77 -1420.52 15.99 angle 137.0 town_number 0
016D: restart_if_busted_at 1550.68 -1675.49 14.51 angle 90.0 town_number 0
0180: set_on_mission_flag_to $ONMISSION // Note: your missions have to use the variable defined here
03E6: remove_text_box
004F: create_thread @STARTEX
004E: end_thread

:STARTEX
03A4: name_thread 'STARTEX'
00D6: if and
0038:   $ONMISSION == 0
0256:   player $PLAYER_CHAR defined
004D: jump_if_false @STARTEX_159
0226: 0@ = actor $PLAYER_ACTOR health
00D6: if
8039:   not  0@ == 0
004D: jump_if_false @STARTEX_170
0926: $Script_Status = external_script_status 0 (MILITIA)
00D6: if
0038:   $Script_Status == 0
004D: jump_if_false @STARTEX_159
08A9: load_external_script 0 (MILITIA)
00D6: if
08AB:   external_script 0 (MILITIA) loaded
004D: jump_if_false @STARTEX_159
0615: define_AS_pack_begin 5@
05DE: AS_actor -1 walk_around_ped_path
0616: define_AS_pack_end 5@
04C4: store_coords_to 2@ 3@ 4@ from_actor $PLAYER_ACTOR with_offset 1.0 3.0 -0.9
04C4: store_coords_to 7@ 8@ 9@ from_actor $PLAYER_ACTOR with_offset 1.0 -3.0 -0.9
061D: create_AS_origin_at 7@ 8@ 9@ Z_angle 60.0 unknown_angle 300.0 AS_pack 5@ handle_as 6@
0621: create_actor_pedtype 6 model #NULL at_AS_origin 6@ task 1502 handle_as 10@
009A: 1@ = create_actor_pedtype 6 model #MALE01 at 2@ 3@ 4@
0913: run_external_script 0 (MILITIA) 1@
0913: run_external_script 0 (MILITIA) 10@

:STARTEX_159
0001: wait 0 ms
0002: jump @STARTEX

:STARTEX_170
090F: end_external_script 0 (MILITIA)
0001: wait 0 ms
0002: jump @STARTEX

//-------------External script 0 (MILITIA)---------------

:MILITIA
03A4: name_thread 'MILITIA'
0006: 2@ = 0

:MILITIA_18
00D6: if
8248:   not model #COLT45 available
004D: jump_if_false @MILITIA_46
0247: load_model #COLT45
0002: jump @MILITIA_18

:MILITIA_46
00D6: if
8118:   not actor 0@ dead
004D: jump_if_false @MILITIA_145
01B2: give_actor 0@ weapon 22 ammo 99999999 // Load the weapon model before using this
01B9: set_actor 0@ armed_weapon_to 0
00D6: if
0491:   actor 0@ has_weapon 3
004D: jump_if_false @MILITIA_106
0555: remove_weapon 3 from_actor 0@

:MILITIA_106
02E2: set_actor 0@ weapon_accuracy_to 80
0978: copy_decision_maker 65537 to $9538
0708: add_decision_maker $9538 event 27
0708: add_decision_maker $9538 event 48
060B: set_actor 0@ decision_maker_to $9538

:MILITIA_145
0006: 4@ = 0

:MILITIA_152
0001: wait 0 ms
00D6: if and
8118:   not actor 0@ dead
0256:   player $PLAYER_CHAR defined
004D: jump_if_false @MILITIA_216
00D6: if
810F:   not player $PLAYER_CHAR wanted_level > 0
004D: jump_if_false @MILITIA_551
0050: gosub @MILITIA_230
0002: jump @MILITIA_209

:MILITIA_209
0002: jump @MILITIA_223

:MILITIA_216
0002: jump @MILITIA_717

:MILITIA_223
0002: jump @MILITIA_152

:MILITIA_230
0871: init_jump_table 4@ total_jumps 3 default_jump 0 @MILITIA_549 jumps 0 @MILITIA_293 1 @MILITIA_356 2 @MILITIA_516 -1 @MILITIA_549 -1 @MILITIA_549 -1 @MILITIA_549 -1 @MILITIA_549

:MILITIA_293
062E: unknown_get_actor 0@ task 1502 status_store_to 2@ // ret 7 if not found
00D6: if
04A4:   2@ == 7 // @ == any
004D: jump_if_false @MILITIA_349
05DE: AS_actor 0@ walk_around_ped_path
0006: 33@ = 0
0006: 6@ = 5000
000A: 4@ += 1

:MILITIA_349
0002: jump @MILITIA_549

:MILITIA_356
00D6: if
002D:   33@ >= 6@ // (int)
004D: jump_if_false @MILITIA_509
0209: 2@ = random_int_in_ranges 1 10
00D6: if
0019:   2@ > 5
004D: jump_if_false @MILITIA_453
062E: unknown_get_actor 0@ task 1481 status_store_to 2@ // ret 7 if not found
00D6: if
04A4:   2@ == 7 // @ == any
004D: jump_if_false @MILITIA_446
05C9: AS_actor 0@ on_guard -1 ms
0006: 6@ = 5000

:MILITIA_446
0002: jump @MILITIA_495

:MILITIA_453
062E: unknown_get_actor 0@ task 1502 status_store_to 2@ // ret 7 if not found
00D6: if
04A4:   2@ == 7 // @ == any
004D: jump_if_false @MILITIA_495
05DE: AS_actor 0@ walk_around_ped_path
0006: 6@ = 5000

:MILITIA_495
0006: 33@ = 0
000A: 4@ += 1

:MILITIA_509
0002: jump @MILITIA_549

:MILITIA_516
00D6: if
002D:   33@ >= 6@ // (int)
004D: jump_if_false @MILITIA_542
0006: 4@ = 1

:MILITIA_542
0002: jump @MILITIA_549

:MILITIA_549
0051: return

:MILITIA_551
0001: wait 0 ms
00D6: if and
8118:   not actor 0@ dead
0256:   player $PLAYER_CHAR defined
004D: jump_if_false @MILITIA_703
00D6: if
02E0:   actor $PLAYER_ACTOR aggressive
004D: jump_if_false @MILITIA_650
01B9: set_actor 0@ armed_weapon_to 22
062E: unknown_get_actor 0@ task 1588 status_store_to 5@ // ret 7 if not found
00D6: if
04A4:   5@ == 7 // @ == any
004D: jump_if_false @MILITIA_643
0634: AS_actor 0@ attack_using_weapon_actor $PLAYER_ACTOR unknown 1 unknown 4000 unknown 60

:MILITIA_643
0002: jump @MILITIA_696

:MILITIA_650
062E: unknown_get_actor 0@ task 1506 status_store_to 5@ // ret 7 if not found
00D6: if
04A4:   5@ == 7 // @ == any
004D: jump_if_false @MILITIA_696
07FE: set_actor 0@ fighting_style_to 7 6
05E2: AS_actor 0@ kill_actor $PLAYER_ACTOR

:MILITIA_696
0002: jump @MILITIA_710

:MILITIA_703
0002: jump @MILITIA_717

:MILITIA_710
0002: jump @MILITIA_551

:MILITIA_717
065C: remove_references_to_decision_maker $9538
01C2: remove_references_to_actor 0@ // Like turning an actor into a random pedestrian
004E: end_thread


// This file was decompiled using SASCM.INI published by Seemann (http://sannybuilder.com/files/SASCM.rar) on 23.02.2007
DEFINE OBJECTS 1
DEFINE OBJECT SANNY BUILDER v. 2.99F

DEFINE MISSIONS 0

DEFINE EXTERNAL_SCRIPTS 1 // Use -1 in order not to compile AAA script
DEFINE SCRIPT MILITIA AT @MILITIA      // 0

DEFINE UNKNOWN_EMPTY_SEGMENT 0

DEFINE UNKNOWN_THREADS_MEMORY 0

{$VERSION 3.1.0020}

//-------------MAIN---------------
03A4: name_thread 'MAIN'
01F0: set_max_wanted_level_to 6
0111: toggle_wasted_busted_check 0
00C0: set_current_time_hours_to 8 minutes_to 0
04E4: unknown_refresh_game_renderer_at 2488.56 -1666.84
03CB: set_rendering_origin_at 2488.56 -1666.84 13.38
0053: $PLAYER_CHAR = create_player #NULL at 2488.56 -1666.84 13.38
01F5: $PLAYER_ACTOR = create_player_actor $PLAYER_CHAR
07AF: $PLAYER_GROUP = player $PLAYER_CHAR group
0373: set_camera_directly_behind_player
01B6: set_weather 0
0001: wait 0 ms
087B: set_player $PLAYER_CHAR clothes_texture "PLAYER_FACE" model "HEAD" body_part 1
087B: set_player $PLAYER_CHAR clothes_texture "JEANSDENIM" model "JEANS" body_part 2
087B: set_player $PLAYER_CHAR clothes_texture "SNEAKERBINCBLK" model "SNEAKER" body_part 3
087B: set_player $PLAYER_CHAR clothes_texture "VEST" model "VEST" body_part 0
070D: rebuild_player $PLAYER_CHAR
01B4: toggle_player $PLAYER_CHAR can_move 1
016A: fade 1 time 0
04BB: select_interior 0
0629: change_integer_stat 181 to 4
016C: restart_if_wasted_at 2027.77 -1420.52 15.99 angle 137.0 town_number 0
016D: restart_if_busted_at 1550.68 -1675.49 14.51 angle 90.0 town_number 0
0180: set_on_mission_flag_to $ONMISSION // Note: your missions have to use the variable defined here
03E6: remove_text_box
004F: create_thread @STARTEX
004E: end_thread

:STARTEX
03A4: name_thread 'STARTEX'
00D6: if and
0038:   $ONMISSION == 0
0256:   player $PLAYER_CHAR defined
004D: jump_if_false @STARTEX_173
0226: 10@ = actor $PLAYER_ACTOR health
00D6: if
8039:   not  10@ == 0
004D: jump_if_false @STARTEX_185
0926: $Script_Status = external_script_status 0 (MILITIA)
00D6: if
0038:   $Script_Status == 0
004D: jump_if_false @STARTEX_173
08A9: load_external_script 0 (MILITIA)
00D6: if
08AB:   external_script 0 (MILITIA) loaded
004D: jump_if_false @STARTEX_173
0913: run_external_script 0 (MILITIA) 1 2482.72 -1658.665 13.3372

:STARTEX_173
0001: wait 250 ms
0002: jump @STARTEX

:STARTEX_185
090F: end_external_script 0 (MILITIA)
0001: wait 0 ms
0002: jump @STARTEX

//-------------External script 0 (MILITIA)---------------

:MILITIA
03A4: name_thread 'MILITIA'
0006: 5@ = 0
00D6: if
0039:   5@ == 1
004D: jump_if_false @MILITIA_36

:MILITIA_36
009A: 4@ = create_actor_pedtype 4 model 0@ at 1@ 2@ 3@    //pedtype 0,1- вылетает

:MILITIA_55
0001: wait 0 ms
00D6: if
8118:   not actor 4@ dead
004D: jump_if_false @MILITIA_119
062E: unknown_get_actor 4@ task 1506 status_store_to 5@ // ret 7 if not found
00D6: if
04A4:   5@ == 7 // @ == any
004D: jump_if_false @MILITIA_55
05E2: AS_actor 4@ kill_actor $PLAYER_ACTOR
0002: jump @MILITIA_55

:MILITIA_119
01C2: remove_references_to_actor 4@ // Like turning an actor into a random pedestrian
004E: end_thread


{
  use macro (Ctrl+J) "headsa"
  to insert a file header
}
{$VERSION 3.0.0000}
thread 'Main'
var
$PLAYER_CHAR: Player
end // var
01F0: set_max_wanted_level_to 6
set_wb_check_to 0
00C0: set_current_time 8 0
04E4: unknown_refresh_game_renderer_at 2488.5601 -1666.84
Camera.SetAtPos(2488.5601, -1666.84, 13.38)
$PLAYER_CHAR = Player.Create(#NULL, 2488.5601, -1666.84, 13.38)
$PLAYER_ACTOR = Actor.EmulateFromPlayer($PLAYER_CHAR)
Camera.SetBehindPlayer
set_weather 0
wait 0 ms
$PLAYER_CHAR.SetClothes("PLAYER_FACE", "HEAD", Head)
$PLAYER_CHAR.SetClothes("JEANSDENIM", "JEANS", Legs)
$PLAYER_CHAR.SetClothes("SNEAKERBINCBLK", "SNEAKER", Shoes)
$PLAYER_CHAR.SetClothes("VEST", "VEST", Torso)
$PLAYER_CHAR.Build
$PLAYER_CHAR.CanMove = True
fade 1 (out) 0 ms
select_interior 0
0629: change_stat 181 (islands unlocked) to 4
016C: restart_if_wasted at 2027.77 -1420.52 15.99 angle 137.0 unknown 0
016D: restart_if_busted at 1550.68 -1675.49 14.51 angle 90.0 unknown 0
0180: set_on_mission_flag_to $ONMISSION
// put your create_thread commands here
create_thread @JumpT  // создаём поток
end_thread

// put your mission mods here

:JumpT
03A4: name_thread 'JumpT'
03DE: set_pedestrians_density_multiplier_to 0.0
$CHECK = 0

:JumpT_1
wait 0 ms
04C4: create_coordinate $X $Y $Z from_actor $PLAYER_ACTOR offset 1.0 3.0 0.0
$Z -=1.1
00BE: text_clear_all
054C: use_GXT_table 'FARLIE3'
00BC: text_highpriority 'DRI2_12' 5000 ms 1  // ~s~ Kill those ~r~goons.
gosub @Jump_table
wait 1000
actor.Create($Actor,7,$MODEL,$X, $Y, $Z)
actor.Health($Actor)= 1000
07FE: set_actor $Actor fighting_style_to 22@ 6
if
$CHECK ==3
jf @JumpT_2
01B2: give_actor $Actor weapon 5 ammo 3000 // Load the weapon model before using this

:JumpT_2
05E2: actor $Actor kill_actor $PLAYER_ACTOR

:JumpT_3
wait 0 ms
if
actor.Dead($Actor)
jf @JumpT_3
wait 2000 ms
actor.DestroyInstantly($Actor)
$CHECK +=1

:JumpT_4
wait 0 ms
if
4 > $CHECK
jf @JumpT_5
wait 1000 ms
jump @JumpT_1

:JumpT_5
03DE: set_pedestrians_density_multiplier_to 1.0
model.Destroy(#VHMYELV)
model.Destroy(#VWMYBOX)
model.Destroy(#WMYCR)
model.Destroy(#OMYKARA)
model.Destroy(#BAT)
end_thread

:Jump_table
0871: init_jump_table $CHECK total_jumps 4 0 @EXIT_JT jumps 0 @JUMP_0 1 @JUMP_1 2 @JUMP_2 3 @JUMP_3 -1 @EXIT_JT -1 @EXIT_JT -1 @EXIT_JT

:JUMP_0
model.Load(#VHMYELV)
038B: load_requested_models

:JUMP_0_1
wait 0 ms
if
model.Available(#VHMYELV)
jf @JUMP_0_1
04AE: $MODEL = 82
22@ = 5
jump @EXIT_JT

:JUMP_1
model.Load(#VWMYBOX)
038B: load_requested_models

:JUMP_1_1
wait 0 ms
if
model.Available(#VWMYBOX)
jf @JUMP_1_1
04AE: $MODEL = 81
22@ = 6
jump @EXIT_JT

:JUMP_2
model.Load(#WMYCR)
038B: load_requested_models

:JUMP_2_1
wait 0 ms
if model.Available(#WMYCR)
jf @JUMP_2_1
04AE: $MODEL = 100
22@ = 7
jump @EXIT_JT

:JUMP_3
model.Load(#OMYKARA)
model.Load(#BAT)
038B: load_requested_models

:JUMP_3_1
wait 0 ms
if and
model.Available(#OMYKARA)
model.Available(#BAT)
jf @JUMP_3_1
04AE: $MODEL = 203
22@ = 8
jump @EXIT_JT

:EXIT_JT
return


// This file was decompiled using sascm.ini published by Seemann (http://sannybuilder.com/files/SASCM.rar) on 23.02.2007
DEFINE OBJECTS 1
DEFINE OBJECT SANNY BUILDER v. 2.99f

DEFINE MISSIONS 3
DEFINE MISSION 0 AT @INITIAL           // Initial 1
DEFINE MISSION 1 AT @FIRST             // Initial 2
DEFINE MISSION 2 AT @SECOND            // Intro

DEFINE EXTERNAL_SCRIPTS 0 // Use -1 in order not to compile AAA script

DEFINE UNKNOWN_EMPTY_SEGMENT 0

DEFINE UNKNOWN_THREADS_MEMORY 0

{$VERSION 3.1.0020}

//-------------MAIN---------------
thread 'MAIN'
01F0: set_max_wanted_level_to 6
set_wb_check_to 0
00C0: set_current_time_hours_to 8 minutes_to 0
04E4: unknown_refresh_game_renderer_at 2488.56 -1666.84
Camera.SetAtPos(2488.56, -1666.84, 13.38)
$PLAYER_CHAR = Player.Create(#NULL, 2493.376, -1666.84, 13.38)
$PLAYER_ACTOR = Actor.EmulateFromPlayer($PLAYER_CHAR)
07AF: $PLAYER_GROUP = player $PLAYER_CHAR group
Camera.SetBehindPlayer
set_weather 0
wait 0
Player.SetClothes($PLAYER_CHAR, "PLAYER_FACE", "HEAD", Head)
Player.SetClothes($PLAYER_CHAR, "JEANSDENIM", "JEANS", Legs)
Player.SetClothes($PLAYER_CHAR, "SNEAKERBINCBLK", "SNEAKER", Shoes)
Player.SetClothes($PLAYER_CHAR, "VEST", "VEST", Torso)
Player.Build($PLAYER_CHAR)
Player.CanMove($PLAYER_CHAR) = True
$NEW_TOTAL_PASSED_MISSIONS = 0
select_interior 0
0629: change_integer_stat 181 to 4
016C: restart_if_wasted_at 2027.77 -1420.52 15.99 angle 137.0 town_number 0
016D: restart_if_busted_at 1550.68 -1675.49 14.51 angle 90.0 town_number 0
0180: set_on_mission_flag_to $ONMISSION // Note: your missions have to use the variable defined here
03E6: remove_text_box
fade 0 500

:MAIN_297
if
fading
jf @MAIN_325
wait 0
00BE: text_clear_all
03E6: remove_text_box
jump @MAIN_297

:MAIN_325
wait 0
start_mission INITIAL // Initial
// Запускаем миссию INITIAL из главного потока
end_thread

:STARTER
thread 'STARTER'

:STARTER_11
wait 250
if
  $NEW_TOTAL_PASSED_MISSIONS == 2
// Количество сюжетных миссий у нас равно 2
// если  $NEW_TOTAL_PASSED_MISSIONS == 2, то закрываем поток
jf @STARTER_36
end_thread

:STARTER_36
if
   Player.Defined($PLAYER_CHAR)
jf @STARTER_352
if
  $ONMISSION == 0
jf @STARTER_352
if
   Player.Controllable($PLAYER_CHAR)
jf @STARTER_352
if
  $NEW_TOTAL_PASSED_MISSIONS == 0
jf @STARTER_219
if
00FF:   actor $PLAYER_ACTOR sphere 0 in_sphere 2498.228 -1647.457 13.5479 radius 1.2 1.2 2.0 on_foot
jf @STARTER_352
Marker.Disable($Marker_Sweet_House)
$ONMISSION = 1
00BA: show_text_styled GXT 'SWEET_1' time 1000 style 2  // Tagging up Turf
fade 0 500

:STARTER_187
if
fading
jf @STARTER_215
wait 0
00BE: text_clear_all
03E6: remove_text_box
jump @STARTER_187

:STARTER_215
start_mission FIRST

:STARTER_219
if
  $NEW_TOTAL_PASSED_MISSIONS == 1
jf @STARTER_352
if
00FF:   actor $PLAYER_ACTOR sphere 0 in_sphere 2468.632 -1650.888 13.4716 radius 1.2 1.2 2.0 on_foot
jf @STARTER_352
Marker.Disable($Marker_Sweet_House)
$ONMISSION = 1
00BA: show_text_styled GXT 'SWEET1B' time 1000 style 2  // Cleaning the Hood
fade 0 500

:STARTER_320
if
fading
jf @STARTER_348
wait 0
00BE: text_clear_all
03E6: remove_text_box
jump @STARTER_320

:STARTER_348
start_mission SECOND

:STARTER_352
jump @STARTER_11

:T_START
// Поток будет запущен только в том случае если миссия INITIAL провалена
thread 'T_START'
wait 0
1@ = Marker.CreateIconAndSphere(36, 2490.768, -1669.816, 13.3359)

:T_START_37
wait 250
if and
   Player.Defined($PLAYER_CHAR)
0102:   actor $PLAYER_ACTOR in_sphere 2490.7 -1669.8 13.4 radius 2.0 2.0 1.0 sphere 1 stopped_on_foot
jf @T_START_37
Marker.Disable(1@)
00BA: show_text_styled GXT 'SWEET_3' time 1000 style 2  // Drive-thru
fade 0 500
wait 500
start_mission INITIAL // Initial
end_thread

//-------------Mission 0---------------
// Originally: Initial

:INITIAL
thread 'INITIAL'
gosub @INITIAL_49
if
wasted_or_busted
jf @INITIAL_38
gosub @INITIAL_162

:INITIAL_38
$ONMISSION = 0
mission_cleanup
end_thread

:INITIAL_49
increment_mission_attempts
$ONMISSION = 1
wait 1000
fade 1 1000

// ----код миссии

:INITIAL_100
wait 2000
030C: progress_made += 1
0318: set_latest_mission_passed 'SWEET_1'  // Tagging up Turf
01E3: show_text_1number_styled GXT 'M_PASSS' number 200 time 5000 style 1  // MISSION PASSED!~n~~w~$~1~~n~~w~RESPECT +
0998: add_respect 3
Player.Money($PLAYER_CHAR) += 200
Player.ClearWantedLevel($PLAYER_CHAR)
0394: play_music 1
$Marker_Sweet_House = Marker.CreateIconAndSphere(16, 2498.228, -1647.457, 13.5479)
// создаем маркер миссии FIRST
create_thread @STARTER
// Запускаем стартер сюжетных миссий
return

:INITIAL_162
00BE: text_clear_all
00BA: show_text_styled GXT 'M_FAIL' time 5000 style 1  // ~r~MISSION FAILED!
create_thread @T_START
// Если миссия провалена, то запускаем стартер миссии INITIAL
return

//-------------Mission 1---------------
// Originally: FIRST

:FIRST
thread 'FIRST'
gosub @FIRST_49
if
wasted_or_busted
jf @FIRST_38
gosub @FIRST_165

:FIRST_38
$ONMISSION = 0
mission_cleanup
end_thread

:FIRST_49
increment_mission_attempts
$ONMISSION = 1
wait 1000
fade 1 1000

// ----код миссии

:FIRST_100
wait 2000
Camera.Restore_WithJumpCut
Camera.SetBehindPlayer
$Marker_Sweet_House = Marker.CreateIconAndSphere(52, 2468.632, -1650.888, 13.4716)
// создаем маркер миссии SECOND
030C: progress_made += 1
0318: set_latest_mission_passed 'FIRST'  // 1st
01E3: show_text_1number_styled GXT 'M_PASSS' number 200 time 5000 style 1  // MISSION PASSED!~n~~w~$~1~~n~~w~RESPECT +
0998: add_respect 3
Player.Money($PLAYER_CHAR) += 200
Player.ClearWantedLevel($PLAYER_CHAR)
0394: play_music 1
$NEW_TOTAL_PASSED_MISSIONS += 1
return

:FIRST_165
00BA: show_text_styled GXT 'M_FAIL' time 5000 style 1  // ~r~MISSION FAILED!
return

//-------------Mission 2---------------
// Originally: SECOND

:SECOND
thread 'SECOND'
gosub @SECOND_49
if
wasted_or_busted
jf @SECOND_38
gosub @SECOND_139

:SECOND_38
$ONMISSION = 0
mission_cleanup
end_thread

:SECOND_49
increment_mission_attempts
$ONMISSION = 1
wait 1000
fade 1 1000

// ----код миссии

:SECOND_100
wait 2000
030C: progress_made += 1
0318: set_latest_mission_passed 'SWEET_1'  // Tagging up Turf
01E3: show_text_1number_styled GXT 'M_PASSS' number 200 time 5000 style 1  // MISSION PASSED!~n~~w~$~1~~n~~w~RESPECT +
0998: add_respect 3
Player.Money($PLAYER_CHAR) += 200
Player.ClearWantedLevel($PLAYER_CHAR)
0394: play_music 1
$NEW_TOTAL_PASSED_MISSIONS += 1
return

:SECOND_139
00BA: show_text_styled GXT 'M_FAIL' time 5000 style 1  // ~r~MISSION FAILED!
$Marker_Sweet_House = Marker.CreateIconAndSphere(52, 2468.632, -1650.888, 13.4716)
return


// This file was decompiled using sascm.ini published by Seemann (http://sannybuilder.com/files/SASCM.rar) on 23.02.2007
DEFINE OBJECTS 1
DEFINE OBJECT SANNY BUILDER v. 2.99f

DEFINE MISSIONS 1
DEFINE MISSION 0 AT @MISSION           // Initial 1

DEFINE EXTERNAL_SCRIPTS 0 // Use -1 in order not to compile AAA script

DEFINE UNKNOWN_EMPTY_SEGMENT 0

DEFINE UNKNOWN_THREADS_MEMORY 0

{$VERSION 3.1.0020}

//-------------MAIN---------------
thread 'MAIN'
fade 0 0
01F0: set_max_wanted_level_to 6
030D: set_total_mission_points_to 187
set_wb_check_to 0
00C0: set_current_time_hours_to 8 minutes_to 0
04E4: unknown_refresh_game_renderer_at 2488.56 -1666.84
Camera.SetAtPos(2488.56, -1666.84, 13.38)
$PLAYER_CHAR = Player.Create(#NULL, 2473.376, -1669.84, 13.38)
$PLAYER_ACTOR = Actor.EmulateFromPlayer($PLAYER_CHAR)
07AF: $PLAYER_GROUP = player $PLAYER_CHAR group
Camera.SetBehindPlayer
set_weather 0
09BA: show_entered_zone_name 0
wait 0
Player.SetClothes($PLAYER_CHAR, "PLAYER_FACE", "HEAD", Head)
Player.SetClothes($PLAYER_CHAR, "JEANSDENIM", "JEANS", Legs)
Player.SetClothes($PLAYER_CHAR, "SNEAKERBINCBLK", "SNEAKER", Shoes)
Player.SetClothes($PLAYER_CHAR, "VEST", "VEST", Torso)
Player.Build($PLAYER_CHAR)
Player.CanMove($PLAYER_CHAR) = True
$NEW_TOTAL_PASSED_MISSIONS = 0
fade 1 0
select_interior 0
0629: change_integer_stat 181 to 4
016C: restart_if_wasted_at 2027.77 -1420.52 15.99 angle 137.0 town_number 0
016D: restart_if_busted_at 1550.68 -1675.49 14.51 angle 90.0 town_number 0
0180: set_on_mission_flag_to $ONMISSION // Note: your missions have to use the variable defined here
03E6: remove_text_box
create_thread @START
end_thread

:START
thread 'START'
wait 0
1@ = Marker.CreateIconAndSphere(36, 2490.768, -1669.816, 13.3359)

:START_37
wait 250
if and
   Player.Defined($PLAYER_CHAR)
0102:   actor $PLAYER_ACTOR in_sphere 2490.7 -1669.8 13.4 radius 2.0 2.0 1.0 sphere 1 stopped_on_foot
jf @START_37
Marker.Disable(1@)
00BA: show_text_styled GXT 'STAD_04' time 1000 style 2  //
fade 0 500
wait 500
start_mission MISSION // Initial 1
end_thread

//-------------Mission 0---------------
// Originally: Initial 1

:MISSION
thread 'MISSION'
gosub @MissionStart
if
wasted_or_busted
jf @MissionCleanup
gosub @MissionFailed

:MissionCleanup
$ONMISSION = 0
mission_cleanup
end_thread

:MissionStart
Model.Load(#BFINJECT)
038B: load_requested_models

:MissionStart_27
wait 0
if
   Model.Available(#BFINJECT)
jf @MissionStart_27
01EB: set_traffic_density_multiplier_to 0.0
03DE: set_pedestrians_density_multiplier_to 0.0
Player.CanMove($PLAYER_CHAR) = False
02A3: toggle_widescreen 1
$car = Car.Create(#BFINJECT, 2636.431, -1730.885, 10.7281)
Car.Angle($car) = 89.3845
Actor.PutAt($PLAYER_ACTOR, 2634.789, -1722.628, 10.8984)
Actor.Angle($PLAYER_ACTOR) = 179.9178
04E4: unknown_refresh_game_renderer_at 2634.789 -1722.628
Camera.SetAtPos(2634.789, -1722.628, 11.8984)
Camera.SetBehindPlayer
wait 500
fade 1 500

:MissionStart_37
wait 0
054C: use_GXT_table 'GARAGE1'
00BC: show_text_highpriority GXT 'GAR1_22' time 3000 flag 1  // ~s~Get inside the ~b~car~s~.
wait 5000
03D5: remove_text 'GAR1_22'  // ~s~Get inside the ~b~car~s~.
054C: use_GXT_table 'BLOOD'
00BC: show_text_highpriority GXT 'BLOD_01' time 5000 flag 1  // ~s~Drive through the checkpoints to increase your overall time.
wait 5000
03D5: remove_text 'BLOD_01'  // ~s~Drive through the checkpoints to increase your overall time.
00BC: show_text_highpriority GXT 'BLOD_02' time 5000 flag 1  // ~s~You will lose if your overall time reaches zero.
wait 5000
03D5: remove_text 'BLOD_02'  // ~s~You will lose if your overall time reaches zero.
Player.CanMove($PLAYER_CHAR) = True
02A3: toggle_widescreen 0

:MissionStart_39
wait 0
if
   Actor.InCar($PLAYER_ACTOR, $car)
jf @MissionStart_39
Car.LockInCurrentPosition($car) = True
wait 2000
$TIME = 20000
03C3: set_timer_to $TIME type 1 GXT 'TIMER' // global_variable  // TIME
06D5: $racing_checkpoint = create_racing_checkpoint_at 2192.036 -1732.899 13.0168 point_to 0.0 0.0 0.0 type 1 radius 6.0
018A: $checkpoint = create_checkpoint_at 2192.036 -1732.899 13.0168
01EB: set_traffic_density_multiplier_to 1.0
03DE: set_pedestrians_density_multiplier_to 1.0
Car.LockInCurrentPosition($car) = False

:MissionStart_45
wait 0
if
  $TIME > 0
jf @MissionFailed
if
0100:   actor $PLAYER_ACTOR in_sphere 2192.036 -1732.899 13.0168 radius 6.0 6.0 6.0 sphere 0 in_car
jf @MissionStart_45
wait 50
Car.LockInCurrentPosition($car) = True
014F: stop_timer $TIME
06D6: disable_racing_checkpoint $racing_checkpoint
Marker.Disable($checkpoint)
Model.Destroy(#BFINJECT)
Car.RemoveReferences($car)
Car.LockInCurrentPosition($car) = False
jump @MissionPassed

:MissionPassed
01E3: show_text_1number_styled GXT 'M_PASSS' number 2000 time 5000 style 1  // MISSION PASSED!~n~~w~$~1~~n~~w~RESPECT +
0998: add_respect 3
Player.Money($PLAYER_CHAR) += 2000
0394: play_music 1
return

:MissionFailed
00BA: show_text_styled GXT 'M_FAIL' time 5000 style 1  // ~r~MISSION FAILED!
014F: stop_timer $TIME
06D6: disable_racing_checkpoint $racing_checkpoint
Marker.Disable($checkpoint)
Model.Destroy(#BFINJECT)
Car.RemoveReferences($car)
create_thread @START
return


DEFINE OBJECTS 0
DEFINE MISSIONS 1
DEFINE MISSION 0 at @MyMission
DEFINE EXTERNAL_SCRIPTS -1 // Use -1 to not write AAA script
DEFINE UNKNOWN_EMPTY_SEGMENT 0
DEFINE UNKNOWN_THREADS_MEMORY 0

// --------------------
// THE STRIPPED MAIN THREAD
// contains initial info
// --------------------
thread 'Main'
var
$PLAYER_CHAR: Player
end // var
01F0: set_max_wanted_level_to 6
set_wb_check_to 0
00C0: set_current_time 8 0
04E4: unknown_refresh_game_renderer_at 2488.5601 -1666.84
Camera.SetAtPos(2488.5601, -1666.84, 13.38)
$PLAYER_CHAR = Player.Create(#NULL, 2488.5601, -1666.84, 13.38)
$PLAYER_ACTOR = Actor.EmulateFromPlayer($PLAYER_CHAR)
Camera.SetBehindPlayer
set_weather 0
wait 0 ms
$PLAYER_CHAR.SetClothes("PLAYER_FACE", "HEAD", Head)
$PLAYER_CHAR.SetClothes("JEANSDENIM", "JEANS", Legs)
$PLAYER_CHAR.SetClothes("SNEAKERBINCBLK", "SNEAKER", Shoes)
$PLAYER_CHAR.SetClothes("VEST", "VEST", Torso)
$PLAYER_CHAR.Build
$PLAYER_CHAR.CanMove = True
fade 1 (out) 0 ms
select_interior 0
0629: change_stat 181 (islands unlocked) to 4
016C: restart_if_wasted at 2027.77 -1420.52 15.99 angle 137.0 unknown 0
016D: restart_if_busted at 1550.68 -1675.49 14.51 angle 90.0 unknown 0
0180: set_on_mission_flag_to $ONMISSION
// put your create_thread commands here

create_thread @MyTrigger
end_thread

// put your mission mods here

:MyTrigger
thread "MyTrigger"
$TrigMarker = Marker.CreateIconAndSphere(15, 2489.0591, -1682.2808, 13.3358)
while $MyMission_Passed == 0
wait 250
if Player.Defined($PLAYER_CHAR)
 then
  if $ONMISSION == 0 // integer values
   then
    if 00FF: actor $PLAYER_ACTOR 0 2489.0591 -1682.2808 13.3358 radius 1.0 1.0 2.0
     then
      if Player.Controllable($PLAYER_CHAR)
       then
      $ONMISSION = 1 // integer values
      00BA: text_styled 'INTRO_1' 1000 ms 2 // Big Smoke
      Marker.Disable($TrigMarker)
      start_mission MyMission
      end // if1
     end // if2
    end // if3
  end // if4
end // while
end_thread

:MyMission
thread "MyMission"
gosub @MissionStart
if
  wasted_or_busted
 then
  gosub @MissionFailed
end
gosub @MissionCleanup
end_thread

:MissionStart
gosub @MissionPassed
return

:MissionPassed
01E3: text_1number_styled 'M_PASSD' 0 5000 ms 1 // MISSION PASSED!
$MyMission_Passed = 1
return

:MissionFailed
00BA: text_styled 'M_FAIL' 5000 ms 1 // ~r~MISSION FAILED!
return

:MissionCleanup
$ONMISSION = 0 // integer values
mission_cleanup
return


{$CLEO}

// Hooks the OTB mission, setting new values of wager

10@ = 50
11@ = 250
12@ = 1000
13@ = 5000
14@ = 20000
15@ = 50000
16@ = 250000

while true
    wait 250
    0AAA: 0@ = thread 'OTB' pointer
    if
        0@ > 0 // true if mission 'OTB' is running
    then

        0@ = 0x00A48960 // Mission Locals address v1
        8AA9:    not is_game_version_original
        jf @setloop
        0@ = 0x00A4AFE0 // Mission Locals address v1.1

        :setloop
        inc(0@, 356) // TLS.89@
        for 1@ = 0 to 6
            0A8C: write_memory 0@ size 4 value 10@(1@,8i) virtual_protect 0
            inc(0@, 4)
        end
    end
end


{
  use macro (Ctrl+J) "headsa"
  to insert a file header
}
{$VERSION 3.0.0000}
thread 'Main'
var
$PLAYER_CHAR: Player
end // var
01F0: set_max_wanted_level_to 6
set_wb_check_to 0
00C0: set_current_time 8 0
04E4: unknown_refresh_game_renderer_at 2488.5601 -1666.84
Camera.SetAtPos(2488.5601, -1666.84, 13.38)
$PLAYER_CHAR = Player.Create(#NULL, 2488.5601, -1666.84, 13.38)
$PLAYER_ACTOR = Actor.EmulateFromPlayer($PLAYER_CHAR)
Camera.SetBehindPlayer
set_weather 0
wait 0 ms
$PLAYER_CHAR.SetClothes("PLAYER_FACE", "HEAD", Head)
$PLAYER_CHAR.SetClothes("JEANSDENIM", "JEANS", Legs)
$PLAYER_CHAR.SetClothes("SNEAKERBINCBLK", "SNEAKER", Shoes)
$PLAYER_CHAR.SetClothes("VEST", "VEST", Torso)
$PLAYER_CHAR.Build
$PLAYER_CHAR.CanMove = True
fade 1 (out) 0 ms
select_interior 0
0629: change_stat 181 (islands unlocked) to 4
016C: restart_if_wasted at 2027.77 -1420.52 15.99 angle 137.0 unknown 0
016D: restart_if_busted at 1550.68 -1675.49 14.51 angle 90.0 unknown 0
0180: set_on_mission_flag_to $ONMISSION
// put your create_thread commands here
create_thread @PickUps // создаём поток
end_thread

// put your mission mods here

:PickUps
wait 0
// командой "model.load" описываем нужные для загрузки модели
model.load(#teargas)
model.load(#molotov)
model.load(#desert_eagle)
model.load(#sawnoff)
model.load(#micro_uzi)
model.load(#ak47)
model.load(#m4)
model.load(#sniper)
model.load(#heatseek)
model.load(#flame)
model.load(#minigun)
model.load(#nvgoggles)
038B: load_requested_models
 // загружаем модели,которые были описаны командой "model.load"

:PickUps_2
wait 0
// весь label PickUps_2 представляет собой проверку на загрузку
if and
model.Available(#teargas)
model.Available(#molotov)
model.Available(#desert_eagle)
model.Available(#sawnoff)
model.Available(#micro_uzi)
model.Available(#ak47)
model.Available(#m4)
jf @PickUps_2
if and
model.Available(#sniper)
model.Available(#heatseek)
model.Available(#flame)
model.Available(#minigun)
model.Available(#nvgoggles)
jf @PickUps_2

:PickUps_3 // В label'е PickUps_3 сначало создаются пикапы .
032B: $Weap[0] = create_weapon_pickup #teargas type 15 ammo 999999 at 2504.5488 -1680.08 13.384
032B: $Weap[1] = create_weapon_pickup #molotov type 15 ammo 999999 at 2504.5488 -1678.08 13.384
032B: $Weap[2] = create_weapon_pickup #desert_eagle type 15 ammo 999999 at 2504.55 -1676.1 13.4
032B: $Weap[3] = create_weapon_pickup #sawnoff type 15 ammo 999999 at 2504.5488 -1674.08 13.384
032B: $Weap[4] = create_weapon_pickup #micro_uzi type 15 ammo 999999 at 2504.5488 -1672.08 13.384
032B: $Weap[5] = create_weapon_pickup #ak47 type 15 ammo 999999 at 2504.5488 -1670.08 13.384
032B: $Weap[6] = create_weapon_pickup #m4 type 15 ammo 999999 at 2504.5488 -1668.08 13.384
032B: $Weap[7] = create_weapon_pickup #sniper type 15 ammo 999999 at 2504.5488 -1666.08 13.384
032B: $Weap[8] = create_weapon_pickup #heatseek type 15 ammo 999999 at 2504.5488 -1664.08 13.384
032B: $Weap[9] = create_weapon_pickup #minigun type 15 ammo 999999 at 2504.5488 -1662.08 13.384
032B: $Weap[10] = create_weapon_pickup #nvgoggles type 15 ammo 1 at 2504.5488 -1660.08 13.384
032B: $Weap[11] = create_weapon_pickup #flame type 15 ammo 999999 at 2504.5488 -1658.08 13.384
wait 100
// делаем небольшую задержку,на всякий случай.
Model.Destroy(#teargas)
//командой Model.Destroy(#MODEl) удаляем модель из памяти.
Model.Destroy(#molotov)
//  Если мы не будем писать эту команду,то модели останутся в памяти,
Model.Destroy(#desert_eagle)
// может,если у вас достаточно мощьный компьютер,вы и не заметите
Model.Destroy(#sawnoff type)
// никаких тормозов.Честно говоря,я сам принадлежу к числу
Model.Destroy(#micro_uzi)
// любителей не проверять модели на загруженность и не выгружать их
Model.Destroy(#ak47)
// в конце потока,но я делаю и то и другое,чтобы уже не было того,к чему
Model.Destroy(#m4)
// могут придраться другие и просто на всякий случай,так что - пишите!
Model.Destroy(#sniper)
Model.Destroy(#heatseek)
Model.Destroy(#minigun)
Model.Destroy(#nvgoggles)
Model.Destroy(#flame)
end_thread


// shows a save screen if pressing F4

{$CLEO}
0000:

while true
  wait 250
  if
    0AB0:   key_pressed 0x73
  then
    03D8: show_save_screen
  end
end


{
  use macro (Ctrl+J) "headsa"
  to insert a file header
}
{$VERSION 3.0.0000}
thread 'Main'
var
$PLAYER_CHAR: Player
end // var
01F0: set_max_wanted_level_to 6
set_wb_check_to 0
00C0: set_current_time 8 0
04E4: unknown_refresh_game_renderer_at 2488.5601 -1666.84
Camera.SetAtPos(2488.5601, -1666.84, 13.38)
$PLAYER_CHAR = Player.Create(#NULL, 2488.5601, -1666.84, 13.38)
$PLAYER_ACTOR = Actor.EmulateFromPlayer($PLAYER_CHAR)
Camera.SetBehindPlayer
set_weather 0
wait 0 ms
$PLAYER_CHAR.SetClothes("PLAYER_FACE", "HEAD", Head)
$PLAYER_CHAR.SetClothes("JEANSDENIM", "JEANS", Legs)
$PLAYER_CHAR.SetClothes("SNEAKERBINCBLK", "SNEAKER", Shoes)
$PLAYER_CHAR.SetClothes("VEST", "VEST", Torso)
$PLAYER_CHAR.Build
$PLAYER_CHAR.CanMove = True
fade 1 (out) 0 ms
select_interior 0
0629: change_stat 181 (islands unlocked) to 4
016C: restart_if_wasted at 2027.77 -1420.52 15.99 angle 137.0 unknown 0
016D: restart_if_busted at 1550.68 -1675.49 14.51 angle 90.0 unknown 0
0180: set_on_mission_flag_to $ONMISSION
// put your create_thread commands here
create_thread @SuperCar // создаём поток
end_thread

// put your mission mods here

:SuperCar
wait 5000
if and
player.defined($Player_char)
actor.driving($Player_actor)
jf @SuperCar
03C0: $Car = actor $PLAYER_ACTOR car
car.SetImmunities($Car,1,1,1,1,1)
car.DoorStatus($Car) = 2
wait 2000

:SuperCar_2
wait 0
if
not actor.driving($Player_actor)
jf @SuperCar_2
car.DoorStatus($Car) = 0
car.SetImmunities($Car,0,0,0,0,0)
car.RemoveReferences($Car)
jump @SuperCar


{$CLEO}

// this opcodes is used to make this thread to be executed once
0A95: enable_thread_saving

// calculates absolute address of the text (opcode 0900) in game memory
0A9F: 0@ = current_thread_pointer
0@ += 0x10
0A8D: 0@ = read_memory 0@ size 4 virtual_protect 0
0@ -= @TEXT_PTR  // as all offsets are local (with negative values)

// skips 0900 and datatype bytes, 0@ points directly to the text
0@ += 4

// call ShowTextBox script
0A92: "ShowTextBox.s" 0@
0A93: end_custom_thread

// custom text
:TEXT_PTR
0900: "if you see this message, CLEO 3 works normally!"

// just a null-terminator
0000: NOP


{$CLEO}

// car camera angle is positioned a little higher, like in VC

0000:

while true
    wait 250
    if
        Player.Defined($PLAYER_CHAR)
    then
        if
            Actor.Driving($PLAYER_ACTOR)
        then
            03C0: 0@ = actor $PLAYER_ACTOR car
            0441: 1@ = car 0@ model
            09EF: set_behind_camera_autoposition_mode_for_car_model 1@ distance 1.0 altitude_multiplier 1.0 angle_X 0.18
        end
    end
 end