Работа с магазинами
В этом уроке мы будем учится работать с файлом "shopping.dat" и рассмотрим основные опкоды для работы с ним.
Привет, друзья! Наконец-то нашел время написать новый урок. На очереди у нас обзор опкодов для работы с файлом "shopping.dat". Прежде чем приступить к написанию скриптов по этой теме, сначала разберёмся с форматом данного файла, так как опкоды во многом зависят от данных, которые находятся внутри.
Внутри файла есть две основные секции (в начале идёт название "section"): prices и shops. В первой секции идёт описание товаров (предметов), а во второй — описание магазинов, в которых и будут эти товары.
Секция "prices"
Секция "prices" дополнительно разделена на типы, используя тоже ключевое слово "section". Эти типы группируют товары по определённому признаку. По умолчанию используются 6 типов: "CarMods", "Clothes", "Haircuts", "Tattoos", "Food" и "Weapons". Есть ещё 3 пустые секции, которые не используются в игре ("Furniture", "Gifts" и "Property").
Формат каждого типа отличается по своей структуре. Давайте разбираться с тем, что есть. Каждый тип гарантировано имеет 7 параметров:
Параметр
Количество
Описание
name
1
Идентификатор предмета
nametag
1
GXT-имя предмета
stats to change
4
На какие характеристики игрока будет влиять покупка (используется не всегда)
price
1
Цена товара
Идентификатор предмета — это уникальное имя. Его мы запомним, так как чуть ниже он будет упомянут. Отдельное внимание нужно обратить на характеристики. Они описаны четырьмя параметрами, но влиять можно только на два стата.
Характеристики описаны в следующей последовательности:
1
ИМЯ_СТАТА_1 ЗНАЧЕНИЕ_СТАТА_1 ИМЯ_СТАТА_2 ЗНАЧЕНИЕ_СТАТА_2
Copied!
Вот таблица статов, которые можно использовать:
Характеристика
Описание
fat
Влияет на вес Карла
health
Влияет на здоровье Карла
calories
Влияет на вес и здоровье Карла
stamina
Влияет на выносливость Карла
respect
Влияет на уважение Карла
sexy
Влияет на привлекательность Карла
Значение стата указывается числом. Если покупка не влияет на характеристику, то используется 0. Если влияет, то положительное число будет увеличивать характеристику, а отрицательное — уменьшать (значения от -128 до 127). Если стат вообще не нужно использовать, то достаточно поставить символ - (вместо имени и значения). Пример:
1
ИМЯ_СТАТА_1 ЗНАЧЕНИЕ_СТАТА_1 - -
2
respect 0 sexy 0
3
respect 0 - -
Copied!
× Примечание: Многие секции содержат статы для изменения, но в реальности только некторые из них действительно их изменяют. Остальные чисто декоративные и никак не реагируют при покупке.
Это основные параметры. Некоторые секции имеют в своём формате дополнительные параметры (extra; встречаются в секицях "тату", "причёски" и "одежда"). Они представлены в виде целых чисел или строк (в скрипте строки конвертируются в число алгоритмом CRC).
Секция "shops"
С товарами разобрались. Перейдём к магазинам. Структура этой секции проще. Она содержит в себе другие секции, которые описывают магазины. Общая структура такова:
1
section NAME
2
type TYPE
3
item ID
4
end
Copied!
Имя секции (NAME) — уникальный идентификатор. Это имя используется в одном из опкодов, поэтому запомним его. Далее "type" — это слово указывает, какие товары будут использованы из секции "prices". Имя типа совпадает с именем секции, которые я описывал ранее. Далее идут предметы (по одному на строку). После слова "item" пишется уникальный идентификатор предмета.
Практика
С теорией мы кое-как разобрались. Давайте теперь посмотрим на опкоды, которые используются для работы с файлом "shopping.dat". Сначала идёт загрузка цен и магазинов:
1
075E: load_shopping_data_PRICES_subsection "ammun1"
2
075D: load_shopping_data_SHOPS_subsection "Weapons"
Copied!
Обратите внимание, что названия опкодов неправильные (на момент написания статьи)! Опкод 075E загружает информацию о магазинах, а 075D — о ценах. Я не увидел разницы в порядке их загрузки. Рекомендую использовать именно представленный мной порядок, именно так их использовали разработчики.
Здесь: "ammun1" - имя (идентификатор) магазина "Weapons" - тип (группа) цен
Как только работа с магазинами завершена, нам нужно выгрузить из памяти эту информацию, используя опкод:
1
087C: release_shopping_data
Copied!
Иногда может быть полезно знать, данные какого магазина сейчас загружены в память. Для этого используем опкод:
1
07B0: get_active_shop_name_to s$CURRENT_SHOP_ID
Copied!
Изначально я думал, что этот опкод получает имя интерьера, но оказалось совсем другое :)
Здесь: s$CURRENT_SHOP_ID - переменная, в которую будет записан ID (имя) загруженного магазина. Возвращает пустую строку, если ничего не загружено.
Давайте посмотрим, что можно сделать после загрузки! Первым на очереди станет опкод:
1
075F: store_shopping_data_entries_number_to $MAX_ITEMS_COUNT
Copied!
Он получает количество товаров, которые есть в магазине. В нашем случае туда будет записано число 16 (это по умолчанию). Запомним переменную $MAX_ITEMS_COUNT и идём дальше:
1
0760: store_shopping_data_index 0 textureCRC_to $ITEM
Copied!
Этот опкод позволяет сохранить идентификатор предмета за указанным индексом. Не обращайте внимания на описание; "textureCRC_to" не соответствует действительности (надеюсь, что это скоро исправят).
Здесь: 0 - индекс $ITEM - сохраняется идентификатор предмета
Индекс — это номер в списке товаров в текущем магазине. Диапазон варьируется в зависимости от количества товаров. Максимальный индекс мы можем получить, отняв единицу от количества товаров (опкод 075F). Таким образом мы можем перебрать весь список товаров, используя этот код:
1
0A8F: $MAX_INDEX = $MAX_ITEMS_COUNT - 1 // int
2
for $CURRENT_INDEX = 0 TO $MAX_INDEX
3
0760: store_shopping_data_index $CURRENT_INDEX textureCRC_to $ITEM
4
// ...
5
end
Copied!
× Примечание: в этом уроке я использую цикл для рисования меню, но это делать не обязательно.
Дальше идут опкоды, которые позволяют извлечь информацию о предмете:
1
0761: get_shopping_item_with_textureCRC $ITEM price_to $PPRICE
2
078C: get_shopping_item_with_textureCRC $ITEM nametag_to s$GXT
Copied!
Опкод 0761 получает цену предмета, а 075F — GXT-ключ с названием товара. Давайте напишем небольшой скрипт, который будет выводить информацию о товаре:
1
// ...
2
075E: load_shopping_data_PRICES_subsection "ammun1"
3
075D: load_shopping_data_SHOPS_subsection "Weapons"
4
075F: store_shopping_data_entries_number_to $MAX_ITEMS_COUNT
5
0A8F: $MAX_INDEX = $MAX_ITEMS_COUNT - 1 // int
6
03F0: enable_text_draw 1
7
while true
8
wait 0
9
if
10
00E1: player 0 pressed_key 15 // k~~VEHICLE_ENTER_EXIT
11
then
12
jump @end
13
end
15
for $CURRENT_INDEX = 0 TO $MAX_INDEX
16
0760: store_shopping_data_index $CURRENT_INDEX textureCRC_to $ITEM
17
0761: get_shopping_item_with_textureCRC $ITEM price_to $PPRICE
18
078C: get_shopping_item_with_textureCRC $ITEM nametag_to s$GXT
19
038E: draw_box_position 320.0 224.0 size 640.0 448.0 RGBA 0 0 0 16
20
0343: set_text_draw_linewidth 640.0
21
033E: set_draw_text_position 20.0 [email protected] GXT s$GXT
22
0343: set_text_draw_linewidth 640.0
23
045A: draw_text_1number 320.0 [email protected] GXT 'DOLLAR' number $PPRICE
25
end
26
end
27
:end
28
087C: release_shopping_data
29
// ...
Copied!
Результат:
title
Неплохо! Давайте двигаться дальше. А тут нас ждут опкоды, связанные с модификаторами цен:
1
08C8: set_shopping_item_with_textureCRC $ITEM price_to 16000
2
08C9: reset_shopping_item $ITEM price
Copied!
Опкод 08C8 устанавливает новую цену на выбранный товар, независимо от настроек в файле. Его можно использовать вне цикла; как только новая цена задана, она используется постоянно. Опкод 08C9, должно быть, сбрасывает цену по умолчанию, однако у меня никакой реакции не происходило (он встречается только в скрипте гардероба). Следует отметить, что новая цена не сохраняется навсегда. Как только мы используем опкод "087C", товары вновь будут иметь старые цены.
Далее рассмотрим опкод, который получает данные об экстра параметре:
1
0783: get_shopping_item_with_textureCRC $ITEM flag 0 store_to $EXTRA1
Copied!
Мы можем получить данные об экстра параметре в любой секции, даже если она не содержит экстр. Если параметра нет, то в переменную $EXTRA1 будет записано число 0.
Здесь: 0 - номер экстра параметра $EXTRA1 - переменная, в которую будет записано значение этого параметра
Максимальное количество экстр: 2 (значения 0 и 1 соответственно). Для типа "Weapons" нет таких параметров но, к моему удивлению, опкод достал данные об экстрах (при 0). Изначально я подумал, что это количество патронов, так как оно присутствует в секции, но результат был совсем другим: были числа, но они не соответствовали моим догадкам (ниже будет пример)!
Следующий опкод осуществляет покупку предмета:
1
0790: charge_money_for_shopping_item_with_textureCRC $ITEM
Copied!
Под "покупкой" имеется ввиду изьятие у игрока денег согласно цене; изменяет характеристики игрока, если секция позволяет это сделать; изменяет статистику игрока, обновляя данные о покупках. В случае с оружием игроку дают дополнительно оружие и патроны к нему.
× ВАЖНО: Необходимо убедиться, что модель купленого оружия загружена! Если этого не сделать, то при выстреле будет происходить вылет! Лучше загрузить все модели до загрузки магазинов и цен.
И последний опкод, который входит в "основную обойму":
1
0942: item_with_textureCRC $ITEM is_clothing
Copied!
Эта проверка возвращает "true" в том случае, если предмет был когда-либо куплен опкодом 0790. Информация о покупке хранится всегда; в сейв-файле (или main.scm, точно не скажу).
Давайте рассмотрим пример с выбором предмета и его покупкой:
1
// ...
2
// загружаем модели оружия
3
075E: load_shopping_data_PRICES_subsection "ammun1"
4
075D: load_shopping_data_SHOPS_subsection "Weapons"
5
075F: store_shopping_data_entries_number_to $MAX_ITEMS_COUNT
6
0A8F: $MAX_INDEX = $MAX_ITEMS_COUNT - 1 // int
7
03F0: enable_text_draw 1
9
while true
10
wait 0
11
if
12
00E1: player 0 pressed_key 15 // k~~VEHICLE_ENTER_EXIT
13
then
14
jump @end
15
end
16
if and
18
0AB0: key_pressed 38 // up
19
then
22
if
23
8029: not [email protected] >= 0
24
then
25
008B: [email protected] = $MAX_INDEX // (int)
26
end
27
end
28
if and
30
0AB0: key_pressed 40 // down
31
then
34
if
35
001F: [email protected] > $MAX_INDEX // (int)
36
then
38
end
39
end
41
for $CURRENT_INDEX = 0 TO $MAX_INDEX
42
0760: store_shopping_data_index $CURRENT_INDEX textureCRC_to $ITEM
43
0761: get_shopping_item_with_textureCRC $ITEM price_to $PPRICE
44
078C: get_shopping_item_with_textureCRC $ITEM nametag_to s$GXT
45
0783: get_shopping_item_with_textureCRC $ITEM flag 0 store_to $EXTRA1
46
0783: get_shopping_item_with_textureCRC $ITEM flag 1 store_to $EXTRA2
47
038E: draw_box_position 320.0 224.0 size 640.0 448.0 RGBA 0 0 0 16
48
if
49
0942: item_with_textureCRC $ITEM is_clothing
50
then
51
0343: set_text_draw_linewidth 640.0
52
045A: draw_text_1number 5.0 [email protected] GXT 'DOLLAR' number 1
53
end
54
if
55
07D6: [email protected] == $CURRENT_INDEX // @ == $ (int)
56
then
57
0340: set_text_draw_RGBA 0 255 0 255
58
if
59
00E1: player 0 pressed_key 16 // k~~PED_SPRINT
60
then
61
0790: charge_money_for_shopping_item_with_textureCRC $ITEM
62
08C9: reset_shopping_item $ITEM price
63
end
64
end
65
0343: set_text_draw_linewidth 640.0
66
033E: set_draw_text_position 20.0 [email protected] GXT s$GXT
67
0343: set_text_draw_linewidth 640.0
68
045A: draw_text_1number 320.0 [email protected] GXT 'DOLLAR' number $PPRICE
69
0343: set_text_draw_linewidth 640.0
70
045A: draw_text_1number 460.0 [email protected] GXT 'DOLLAR' number $EXTRA1
71
0343: set_text_draw_linewidth 640.0
72
045A: draw_text_1number 500.0 [email protected] GXT 'DOLLAR' number $EXTRA2
74
end
75
end
76
:end
77
087C: release_shopping_data
78
// выгружаем модели оружия
79
// ...
Copied!
Результат:
title
Похожим способом делается покупка для остальных магазинов. Это вся базовая информация, которая у меня есть.
Copy link
Edit on GitHub