Рейтинг - 4.2 (4)

Привет всем пользователям нашего сайта! Пришло время для очередного урока! Сегодня мы вернёмся файлам, а точнее будет записывать и считывать форматированный текст. Этот способ отличается от работы с ini-файлами по всем статьям, но прочтя этот урок вы многое узнаете и, надеюсь, будете активно использовать в своих скриптах.

Прежде всего нам нужно настроить наш Санник, так как именно настройка (а точнее неправильная настройка) не давала мне писать скрипты изучаемым сегодня методом. Как оказалось, всё дело в регистре букв, который компилятор использует по умолчанию. Давайте откроем настройки и перейдём во вкладку "Форматирование" и обратим внимание на радио-кнопку "Регист букв":


Как видим, по умолчанию у нас стоит ВЕРХНИЙ регист. Так как режим открытия файла должен обязательно компилироваться в нижнем регистре, то меняет радиокнопку на Как есть(нижний - тоже неплохой вариант, это уже наш вкус, но главное, что бы не стоял верхний регистр). После этого нажимаем ОК.

В отличии от ini-режима, в этом режиме нет никаких ключевых слов или секций. Как и Cleo - считывание происходит построчно. Существует 6 основных режимов открытия файла:
Режим
Описание
rt
Открыть ТЕКСТОВЫЙ файл для чтения (файл должен существовать!)
rb
Открыть БИНАРНЫЙ файл для чтения (файл должен существовать!)
wt
Открыть ТЕКСТОВЫЙ файл для записи (файл создастся автоматически, если таково нету)
wb
Открыть БИНАРНЫЙ файл для чтения (файл создастся автоматически, если таково нету)
at
Открыть ТЕКСТОВЫЙ файл для записи (файл создастся автоматически, если таково нету)
ab
Открыть БИНАРНЫЙ файл для чтения (файл создастся автоматически, если таково нету)
Таблица 1.
Рассмотрим опкод, для открытия файла:
  • 0A9A: $hFILE = openfile "Cleo\config.txt" mode "rb" // IF and SET
Здесь:
$hFILE - хендл нашего файла
"Cleo\config.txt" - путь у нашему файлу относительно директории GTA SA
"rb" - режим открытия (см. Таблица 1)

Этот опокод является так же и условным, по этому советую использовать его в блоке условий if...jf.

После того, так работа с файлом завершена, обязательно нужно закрыть его опкодом:
  • 0A9B: closefile $hFILE
Обращаю ваше внимание, что прежде чем открывать файл, нужно убедится в том, что он не открыт в каком то другом приложении. Если в ini-файле можно было динамически менять значения, то этим методом так не получится.

Так так тема нашего урока форматированное считывание и запись, то мы обязаны рассмотреть какие идентификаторы есть, которые пишутся в опкод в зависимости от типа принимаемых значений:
Идентификатор
Описание
%d
Идентификатор целого числа
%f
Идентификатор дробного числа (по умолчанию число и остаток с шестью символами после запятой)
%s
Идентификатор строки
%c
Идентификатор символа (номер символа)
Таблица 2.
Здесь:
% - специальный идентификатор, который указывает компилятору какой тип данных нужно записывать или читать. Они стоят в том порядке, который мы задали в файле, или планируем записать.
d, f, c, s - собственно и есть типы


Давайте рассмотрим 2 опкода, которые позволяют осуществлять запись и считывание:
  • 0AD9: write_formatted_text "Записать %d значений" in_file $hFILE 2
  • 0ADA: 0@ = scan_file $hFile format "Считать %d" 1@
Здесь:
- Опкод 0AD9
Записует форматированный текст в файл $hFILE. Будет записан текст, с таким содержимым: "Записать 2 значений". Как видите, в поле строки указываются только идентификаторы, а после опкода идёт перечисление всех значений. То есть, если мы хотим, что бы в файл записало стоку с содержимым "Бокал пива вмещает 0.5 литра" и хотим в скрипте задать к-во пива, то наш скрипт приобретёт следующий вид:
Code
0@ = 0.5
0AD9: write_formatted_text "Бокал пива вмещает %.1f литра" in_file $hFILE 0@
Таким образом мы сами задаём в переменную значение, а за тем размещаем в нужном нам месте текста. Но не нужно забывать, что не все числа нужно объявлять через идентификаторы. Можно обойтись и без них, если он не содержит нужной нам информации:
Code
0@ = 1.25
0AD9: write_formatted_text "В 2 бокала пива вмещается %.2f литра" in_file $hFILE 0@
Соответственно в файл будет записан текст: "В 2 бокала пива вмещается 1.25 литра". То есть если не задать параметр как идентификатор, то он воспринимается как символ, а не как число. Давайте по этом же примере, напишем текст, с использованием 2-х параметров:
Code
0@ = 1.25
1@ = 2
0AD9: write_formatted_text "В %d бокала пива вмещается %.2f литра" in_file $hFILE 1@ 0@
Думаю вы обратили внимание на %.2f. Собственно для чего мы поставили это? Дело в том, что при такой установке в файл будет записываться только 2 символа после запятой. Если мы поставим %.3f, то в файл будет записано 3 символа. Если этого не сделать(напишем просто %f), то число в файл запишет число "1.250000". Эти идентификаторы уже нужно ставить на своё усмотрение, но как минимум %.1f. Иначе если дробное число не будет иметь остатка(например, 1.0), то во многих случаях в файл запишется просто "1", что вызывает проблемы при считывании. Данные выражения с точкой действуют только на дробные цисла!

Что касается записи строк, то здесь всё тоже самое. Указываем стринговую переменную и задаём ей значение. После этого записуем в файл:
Code
1@v = "Привет"
0AD9: write_formatted_text "text %s" in_file $hFILE 1@v
Содержимое файла: "text Привет".

Вот пример простейшего скрипта, который запишет в файл данные:
Code
{$CLEO}
0000:
thread 'WRITE_TEXT'

:WRITE_TEXT
wait 0
if
file.Open(0@, "cleo\text.txt", "wt")
jf @WRITE_TEXT
1@ = 2
2@v = "пива"
3@ = 1.25
0AD9: write_formatted_text "в %d бакалах %s вмещается %.2f литра" in_file 0@ 1@ 2@v 3@
file.Close(0@)
0A93: end_custom_thread
Результат:


ВАЖНО! Если файл имеет какие то записи, то при открытии его режимом "wt" его содержимое теряется(файл перезапишеться)

- Опкод 0ADA
Считывание файла очень похоже на запись, но здесь есть одно примечание, что содержимое строки файла должно точно совпадать с содержимым строки опкода! Если строка файла "Сейчас 16:21 часов", то содержимое строки опкода будет "Сейчас %d:%d часов"(планируется считать 2 значения из файла). Следовательно в конце опкода нужно дописать необходимые параметры:
  • 0ADA: 0@ = scan_file $hFile format "Сейчас %d:%d часов" 1@ 2@
Таким образом в переменные 1@ и 2@ будут записаны числа, считанные из файла. В переменную 0@ запишется количество удачных преобразований. Если оно не совпадёт с параметрами файла, то выражение вернёт false и в переменные1@ и 2@ нифига не запишется =) Это условный опкод, по этому используйте его в условных конструкциях(if ...). Старайтесь правильно указывать идентификаторы. Во многих случаях это и есть решение проблем.

Давайте напишем простой пример скрипта, который будет считывать цвета для автомобиля а за тем задавать их транспорту, в который мы сели:
Code
{$CLEO}
0000:
thread 'READ_TEXT'

:READ_TEXT
wait 0
if
file.Open(0@, "cleo\text.txt", "rt")
jf @READ_TEXT

:READ_TEXT_1
wait 0
if                         
0ADA: 1@ = scan_file 0@ format "Color car: %d, %d" 2@ 3@
jf @READ_TEXT_1
file.Close(0@)

:READ_TEXT_2
wait 0
if
actor.Driving($PLAYER_ACTOR)
jf @READ_TEXT_2
03C0: 5@ = actor $PLAYER_ACTOR car
0229: set_car 5@ primary_color_to 2@ secondary_color_to 3@
0A93: end_custom_thread
В результате наш скрипт прекрасно перекрашивает наш транспорт на заданный в файле цвет.


В большинстве случаев файлы используют для хранения одинаковой по смыслу информации. Затем считывают весь файл и задают параметры для разных субъектов. К примеру, в файле в нас будет хранится информация о транспорте. Считая её мы создадим несколько машин в генераторе транспорта. Сначала рассмотрим опкод для определения количества параметров в строке:
  • 014B: $CAR = init_parked_car_generator #RHINO color -1 -1 1 alarm 0 door_lock 0 0 10000 at 2435.302 -1671.848 12.8007 angle 90.0
Первый параметр будет у нас модель транспорта; Второй параметр пусть будет цена автомобиля; А следующие четыре координаты спавна и угол поворота. Остальные пусть будут по умолчанию. Что бы не терять ваше время, я создал файл с уже готовыми параметрами:
Code
445 5000 2483.021 -1659.0421 12.94315 180.0
446 7000 2477.022 -1659.0422 12.9432 180.0
447 4000 2471.023 -1659.0423 12.9431 180.0
448 8000 2465.024 -1659.0424 12.94321 180.0
491 10000 2459.025 -1659.0425 12.94322 180.0
471 13000 2453.026 -1659.0426 12.94311 180.0
455 20000 2447.027 -1659.0427 12.94314 180.0
438 8000 2441.028 -1659.0428 12.94321 180.0

Дальше уже напишем скрипт:
Code
{$CLEO}
0000:
thread 'READ_TEXT'

var
$CARS: array 8 of car
end

:READ_TEXT
wait 0
if
file.Open(0@, "cleo\text.txt", "rt")
jf @READ_TEXT
$INDEX = 0

while not file.EOF(0@)
    if                         
    0ADA: 1@ = scan_file 0@ format "%d %d %f %f %f %f" 2@ 3@ 4@ 5@ 6@ 7@ // IF AND SET
    then
    014B: $CARS[$INDEX] = init_parked_car_generator 2@ color -1 -1 1 alarm 0 door_lock 0 0 3@ at 4@ 5@ 6@ angle 7@
    014C: set_parked_car_generator $CARS[$INDEX] cars_to_generate_to 101
    $INDEX += 1
    end
wait 0
end
file.Close(0@)
0A93: end_custom_thread
Так как в нас файл содержится из 8 строк, то и массив автомобилей тоже будет 8 машин. Дальше считывая файл мы подставляем считанные значения в опкод, тем самым создаём новый элемент генератора транспорта.

Думаю вы обратили внимание на опкод 0AD6: end_of_file 0@ reached  (он же file.EOF(0@) ). Это проверка "Достигнут ли конец файла 0@?". Используя её мы проходим весь файл очень быстро. В результате мы получили:


Если разобраться, то нет ничего сложного. Используйте файлы и в своих модах. В большинстве случаев, это существенно уменьшает время и код! =)
Вход на сайт

Поиск
Категории раздела
Мини-чат
Пожалуйста, все вопросы по скриптингу задавать на форуме!
Наш опрос
Кто из главных героев GTA 5 круче?
Всего ответов: 5
Активность на сайте
Пожертвования
Кошельки WebMoney:
U859420971000
R407741810602
Z331072372430
E314272616890
Друзья сайта
Полезные ресурсы
Статистика

Онлайн всего: 1
Гостей: 1
Пользователей: 0

Сегодня нас посетили:
Реклама