Для того, чтобы Cleo-скрипт получился качественным и при работе не приводил к различным конфликтам и ошибкам с последующим вылетом, нужно соблюдать следующие простые правила:
1. Загрузка моделей Перед тем, как создавать актёра, транспорт или объект, необходимо загрузить в память соответствующую модель командой model.load(ID_number), где ID_number – уникальный номер модели в игре (целое число). Вместо номера можно писать и название модели с решеткой (#Model_name), но здесь существует вероятность того, что при компиляции скрипта появится отчёт об ошибке. В версии 3.04 программы SannyBuilder предусмотрена возможность конвертации ИД номера в имя модели и обратно – для этого нужно вставить текстовый курсор между любыми двумя буквами имени (или цифрами номера) и нажать Ctrl+Alt+H.
Если загружается одновременно несколько моделей, то после блока команд model.load рекомендуется написать опкод:
038B: load_requested_models Следует помнить, что модели загружаются в память не одномоментно, поэтому нельзя писать команду создания актёра (транспорта, объекта) сразу после команд загрузки моделей. Если модель ещё не загружена в память, а игра уже пытается что-то создать, то произойдёт ошибка с вылетом. Поэтому перед тем, как создавать что-либо нужно проверять, загружена ли в память соответствующая модель опкодом model.Available(ID_number). После того, как актёр (транспорт, объект) создан, то модель уже больше не нужна – следует удалить её из памяти командой model.Destroy(ID_number). Рекомендуется загружать модели непосредственно перед использованием, а удалять из памяти сразу после того, как актёр (объект, транспорт) создан и модели уже больше не нужны. Пример создания нескольких автомобилей выглядит так (для актёров и объектов алгоритм будет тот же, отличаться будут только команды создания): model.Load(528) model.Load(601) 038B: load_requested_models while true wait 0 if and model.Available(528) model.Available(601) then break end end car.Create(0@ 528 -2029.8625, 140.4657, 28.8359) model.Destroy(528) car.Create(1@ 601 -2023.8625, 140.4657, 28.8359) model.Destroy(601) Предварительно загружать нужно не только модели. При использовании звуков, анимаций и т.п. также может понадобиться предварительная загрузка. 2. Отличия CLEO-кодинга от редактирования main.scm Первое отличие в командах окончания кода. Если скрипт не зациклен (не выполняется бесконечно), то во избежание вылетов следует завершать код командой окончания потока. Завершающая команда в Cleo-скрипте: 0A93: end_custom_thread
В Cleo-миссиях, как и в потоках main.scm завершающей командой будет являться 004E: end_thread
Второе отличие – в Cleo-скрипте не применяется команда создания потока create_thread. Третье отличие – в Cleo-скриптах (и миссиях) не применяются глобальные переменные ($0, $1…). Исключение составляют глобальные переменные из файла CustomVariables.ini - $PLAYER_CHAR, $PLAYER_ACTOR и др. Зато Вы можете свободно использовать локальные переменные (0@ - 33@ в Cleo скриптах и 0@ - 1023@ в Cleo миссиях. Переменные 32@ и 33@ являются таймерами – значение, записанное в них, увеличивается с каждой миллисекундой на единицу. Понятно, что бессмысленно применять переменные-таймеры для других целей). Некоторые опкоды могут применяться только в миссиях, и их применение в потоках может вызвать ошибку. В этом случае к опкоду прилагается соответствующий комментарий – Mission only (если опкод найден в Поиске опкодов). 3. 0A95 Если в скрипте создаётся объект, пикап или парковочный генератор то следует добавить в код команду: 0A95: enable_thread_saving Вообще данная команда делает так, что при сохранении игры значения, записанные в локальных переменных данного скрипта, сохраняются в отдельном Cleo-сэйве. Если, например, скрипт создаёт объекты, а данная команда в код не добавлена, то при сохранении игры сохранятся и объекты. И тогда, если скрипт будет удалён из клео-папки, то на карте объект всё равно останется, а если скрипт удалён не будет, то в игре при запуске появятся 2 одинаковых объекта. То же самое касается и парковочных генераторов, и пикапов. Например, код клео-скрипта, создающего парковочный генератор, должен выглядеть так: {$CLEO} 0a95: enable_thread_saving 014B: 0@ = init_parked_car_generator 528 color -1 -1 1 alarm 0 door_lock 0 0 10000 at -2029.1075 179.1367 28.8359 angle 90.0 014C: set_parked_car_generator 0@ cars_to_generate_to 101 0A93: end_custom_thread 4. Проверки на существование Перед проведением какого-либо действия (проверка, команда) над актёром, транспортом или объектом необходимо делать проверку на существование. Актер (транспорт, объект) может быть удалён не только из того скрипта, которым он был создан, но и другим скриптом или игрой, а попытка произвести действие над несуществующим игровым объектом ведёт к вылету. Проверки на существование машины, актёра и объекта выглядят следующим образом: 056D: actor 0@ defined 056E: car 0@ defined 03CA: object $2727 exists Для проверки существования игрока (CJ) есть особая проверка: 0256: player $PLAYER_CHAR defined Пример применения проверки: If 056E: car 0@ defined then 02AC: set_car 0@ immunities BP 1 FP 1 EP 1 CP 1 MP 1 end 5. Remove References Если вы создадите в скрипте транспорт (или актёра, объект) с помощью команды create, то он будет иметь "уникальный” статус (references). Уникальный транспорт, в отличие от обычного, не удаляется игрой в тех случаях, когда игрок отходит на большое расстояние от него. Уникальный статус может иметь не только машина, созданная скриптом. Если, например, "поймать” созданную игрой машину с помощью опкода: 0327: $TEMPVAR_ACTOR_CAR = get_random_car_with_model -1 in_rectangle_cornerA $111 $112 cornerB $114 $115 то у данной машины будет включен флаг уникальности, и она уже не исчезнет, даже если игрок отойдёт от неё на большое расстояние. Превратить машину из уникальной в обычную (убрать флаг уникальности) можно командой: 01C3: remove_references_to_car $IMPORT_CAR // Like turning a car into any random car Данную команду можно применять для всех видов транспорта кроме поездов (для поездов есть отдельная команда). Подобные команды есть и для других типов игровых объектов: актёров, объектов, эффектов частиц и др. При превращении игрового объекта из уникального в обычный с указателем, записанным в переменную, ничего не происходит (как и при удалении). После отключения флага уникальности над машиной (актёром, объектом) по-прежнему можно производить различные действия – до тех пор, пока машина (актёр, объект) не будет удалена. Наличие или отсутствие флага уникальности не зависит от того, записан ли указатель на игровой объект в каком-то скрипте или нет. Поэтому, если у игрового объекта будет убран уникальный статус или игровой объект будет удалён, то это действие произойдёт независимо от того, в скольких скриптах указатель на данный игровой объект записан в переменную. Существуют лимиты на количество транспорта (или актёров), которые одновременно могут существовать в игре. Так как уникальные игровые объекты игра самостоятельно не удаляет, то, если вы создаёте много транспортных средств или актёров, вы должны удалять старые машины или актёров перед созданием новых (или убирать у них флаги уникальности). И последнее в данном вопросе. Некоторые считают, что команда remove_references "безопасна” и перед её выполнением не обязательно делать проверку на существование того, к чему применяем команду. Мой опыт показывает, что это не так – были случаи вылетов игры, когда в скриптах проверка отсутствовала. 6. Ожидание Существует опкод 0001: wait 0 ms , который приостанавливает выполнение скрипта на указанное время в миллисекундах (1 с = 1000 мс). С данной командой связано следующее правило: если выполнение скрипта начинается с какой-то метки, а потом возвращается наверх – на эту же метку, то за это время должно быть выполнено хотя бы одно ожидание, иначе игра зависнет. Вы можете применять ожидание и в других случаях – например, для приостановки работы скрипта на определённое время. Если же особой нужды в ожидании нет, то применять эту команду не следует – даже нулевое ожидание замедляет работу кода. Дело в том, что все установленные скрипты выполняются по очереди, а при опкоде wait происходит переключение на следующий скрипт в очереди. По этой же причине нельзя вставлять wait между проверкой на существование и последующей командой – то, к чему применялась проверка, может быть удалено другим скриптом или игрой и произведённая проверка окажется бесполезной.
Как искать ошибки в скриптах?
Облегчить поиск ошибок в скриптовых файлах может Cleo-плагин ScmLog (взять можно на sannybuilder.com). Установка плагина проста – для этого нужно скопировать файлы scmlog.ini и scmlog.cleo в папку CLEO. Если плагин установлен, то после выхода из игры (или вылета при ошибке) в папке CLEO будет создан файл scmlog.txt, в котором будет приведён список опкодов (лог), выполненных всеми установленными скриптами. Если игра вылетела, то последним в логе будет указан опкод, при выполнении которого возникла ошибка (название скрипта тоже будет указано).
Источник: http://gameshaker.ucoz.ru/ |