-
Notifications
You must be signed in to change notification settings - Fork 2
Документация Mассивы.
Sfall вводит новый метод хранения переменных - массивы.
Массив - это в основном контейнер, в котором может храниться переменное количество значений (элементов). Каждый элемент в массиве может быть любого типа. Массивы могут быть чрезвычайно полезны для некоторых более сложных сценариев в сочетании с циклами.
Массивы создаются и управляются с помощью функций массива. Для начала массив должен быть создан с помощью функций create_array
или temp_array
, указав, сколько элементов данных может содержать массив. Вы можете хранить любые типы данных int
, float
или string
в массиве, также можно смешивать все 3 типа в одном массиве.
Идентификатор массива, возвращаемый функциями create_array
или temp_array
, может использоваться в других функциях для доступа к созданному массиву. Массивы являются общими для всех сценариев (т.е. вы можете вызвать "create_array" в одном сценарии, а затем использовать возвращенный идентификатор в совершенно другом сценарии для доступа к массиву).
Массивы также могут быть сохранены в файлах сохранения игры.
Массивы, созданные с помощью temp_array
, будут автоматически удалены в конце кадра выполнения сценария.
create_array
- единственная функция, которая возвращает постоянный массив, все остальные функции, возвращающие массивы (string_split
, list_as_array
и т.д.), создают временные массивы. Вы можете использовать функцию fix_array
, чтобы сделать временный массив постоянным.
Функции массивов полностью безопасны в том смысле, что использование неверного идентификатора или попытки доступа к элементам вне размера массива не приведут к сбою в сценарии.
Доступ к элементам массива осуществляется по индексу или ключу.
Пример:
// this code puts some string in array "list" at index 5:
list[5] := "Value";
В настоящее время доступно 2 различных типа массива:
-
Lists - предоставляет коллекцию значений, определенного размера (количество элементов), где элементы имеют числовые индексы, первый индекс элемента всегда начинается с нуля (0) до конца всей длины массива минус единица.
Пример:
// this creates list with 3 elements. Element "A" has index 0, element "B" has index 1, element "C" - 2 list := ["A", "B", "C"];
Ограничения:
- все индексы являются числовыми, и начинаются с 0
- чтобы присвоить значение элементу списка по определенному индексу, необходимо для сначала изменить размер массива, чтобы список содержал этот индекс
например, если список имеет размер 3 (индексы от 0 до 2), вы не можете присвоить значение по индексу 4, если сначала не измените размер списка на 5
-
Maps - ассоциативные массивы содержат наборы пар key=>value, где все элементы (значения) доступны с помощью соответствующих ключей.
Отличия Maps (карт) от List (списка):
- ассоциативные массивы не имеют определенного размера (для присвоения значений вам не нужно изменять размер массива)
- ключи, как и значения, могут быть любого типа (но избегайте использования -1 в качестве ключей массива, иначе вы не сможете надежно использовать некоторые функции)
Оба типа массива имеют свои плюсы и минусы и подходят для решения различных задач.
В основном массивы реализуются с использованием ряда новых операторов (функций сценариев). Но для удобства использования есть некоторые новые элементы синтаксиса:
- Доступ к элементам. Используйте квадратные скобки:
display_msg(arr[5]);
mymap["price"] := 515.23;
- Альтернативный доступ к картам. Используйте точку:
display_msg(mymap.name);
mymap.price := 232.23;
- Выражения массива. Создавайте и заполняйте массивы просто используя одно выражение:
// create list with 5 values
[5, 777, 0, 3.14, "Cool Value"]
// create map:
{5: "Five", "health": 50, "speed": 0.252}
NOTES:
Обязательно вызовите fix_array
, если вы хотите, чтобы новый массив был доступен в следующем фрейме выполнения сценария, или save_array
, если вы хотите использовать его в течение более длительного периода (подробнее см. следующий раздел).
- Перебор элементов массива в цикле. Используйте ключевое слово
foreach
следующим образом:
foreach (item in myarray) begin
// этот блок выполняется для каждого элемента массива, где "item" содержит текущее значение на каждом шаге итерации
end
// альтернативный синтаксис:
foreach (key: item in myarray) begin
// "key" будет содержать текущий ключ (или числовой индекс, для списков)
end
См.: sslc_readme.txt файл для получения полной информации о новых функциях синтаксиса SSL.
Часть массивов списков и карт разделена по способу их хранения.
Существует 3 типа массивов:
-
Temporary: Они создаются с помощью функции
temp_array
или при использовании выражений массива. Массивы этого типа автоматически удаляются в конце кадра выполнения сценария. Так, например, если у вас есть глобальный сценарий, который выполняется через регулярные промежутки времени, где вы создаетеtemp_array
, то массив не будет доступен при следующем выполнении вашего глобального сценария. -
Permanent: Они создаются с помощью функций
create_array
илиfix_array
(из уже существующего временного массива). Массивы этого типа всегда доступны (по их идентификатору) до тех пор, пока вы не начнете новую игру или не загрузите сохраненную игру (после чего они будут удалены). -
Saved: Если вы хотите, чтобы ваш массив действительно оставался на некоторое время, используйте функцию
save_array
, чтобы сделать любой массив "сохраняемым". Однако они, как и постоянные массивы, "удаляются" из памяти при загрузке игры. Чтобы правильно их использовать, вы должны загружать их из сохраненной игры с помощью "load_array" всякий раз, когда вы хотите их использовать.
Пример:variable savedArray; procedure start begin if game_loaded then begin savedArray := load_array("traps"); end else begin foreach trap in traps begin .... end end end
Используйте массивы для реализации процедур с переменными аргументами:
// define it
procedure give_item(variable critter, variable pidList) begin
foreach (pid: qty in pidList) begin
give_pid_qty(critter, pid, qty);
end
end
// call it:
call give_item(dude_obj, {PID_SHOTGUN: 1, PID_SHOTGUN_SHELLS: 4, PID_STIMPAK: 3});
Создание массивов объектов (карт) для продвинутого скриптинга:
variable traps;
procedure init_traps begin
// just a quick example, there is a better way of doing it...
traps := load_array("traps");
if (traps == 0) then begin
traps := [];
save_array("traps", traps);
end
foreach k: v in traps begin
traps[k] := load_array("trap_"+k); // каждый объект хранится отдельно
end
end
procedure add_trap(variable trapArray) begin
variable index;
index := len_array(traps);
save_array("trap_"+k, trapArray);
array_push(traps, trapArray);
end
// use them:
foreach trap in traps begin
if (self_elevation == trap["elev"] and tile_distance(self_tile, trap["tile"]) < trap["radius"]) then
// kaboom!!!
end
end
- Создает постоянный массив (тип Permanent)
- если аргумент
size
больше или равен 0, то это создает список заданного размера - если аргумент
size
равен -1, то это создает карту (ассоциативный массив) - если аргумент
size
равен -1 а аргументflags
равен 2, то это создает lookup карту (ассоциативный массив), в котором значения существующих ключей доступны только для чтения и не могут быть обновлены. Только этот тип массива позволяет хранить ноль (0) в значение ключа.
ПРИМЕЧАНИЕ: в более ранних версиях (до 4.1.3/3.8.13) аргументflags
не используется, просто используйте 0 - Возвращает идентификатор созданного массива arrayID (действует до тех пор, пока массив не будет удален)
- Работает точно так же, как функция
create_array
, только создает временный массив (тип Temporary)
- Изменяет Temporary массив на Permanent массив (постоянные массивы автоматически не сохраняются в сохраненных играх)
- Устанавливает значение для элемента массива
- если используется массив типа List, то аргумент
key
должен быть числовым и находиться в допустимом диапазоне индексов(0..size-1)
- если используется массив типа Maps, в этом случае аргумент
key
может быть любого типа - чтобы "снять" значение с карты, просто установите для ключа его значение равным нулю (0)
ПРИМЕЧАНИЕ: чтобы установить для ключа значение 0, используйте значение 0.0 с плавающей точкой (типfloat
) - это работает точно так же, как оператор:
array[key] := value;
- Возвращает значение массива по ключу или индексу
- если ключ не существует или индекс не находится в допустимом диапазоне, возвращается 0
- работает точно так же, как выражение:
value := array[key];
- changes array size
- applicable to maps too, but only to reduce elements
- there are number of special negative values of "size" which perform various operations on the array,
use macros
sort_array
,sort_array_reverse
,reverse_array
,shuffle_array
from sfall.h header
- deletes any array
- if array was "saved", it will be removed from a savegame
- searches for a first occurence of given value inside given array
- if value is found, returns it's index (for lists) or key (for maps)
- if value is not found, returns -1 (be careful, as -1 can be a valid key for a map)
- returns number of elements or key=>value pairs in a given array
- if array is not found, returns -1 (can be used to check if given array exist)
- don't use it directly; it is generated by the compiler in foreach loops
- for lists, returns index back (no change)
- for maps, returns a key at the specified numeric index (don't rely on the order in which keys are stored though)
- can be checked if given array is associative or not, by using index (-1): 0 - array is list, 1 - array is map
- don't use it directly; it is used by compiler to create array expressions
- assigns value to a given key in an array, created by last
create_array
ortemp_array
call - always returns 0
- makes the array saveable; it will be saved in sfallgv.sav file when saving the game
-
arrayID
is associated with given "key" - array becomes permanent (if it was temporary) and "saved"
- key can be of any type (int, float or string)
- if you specify 0 as the key for the
arrayID
, it will make the array "unsaved"
- load array from savegame data by the same key provided in
save_array
-
arrayID
is returned or zero (0) if none found
*mixed - means any type
Для тех, кто использовал массивы в своих модах до sfall 3.4:
-
Существует INI параметр ArraysBehavior в Misc разделе файла "ddraw.ini". Если его значение установлено в 0, то все сценарии, которые ранее использовали массивы sfall, должны работать. Это в основном меняет то, что
create_array
создает постоянные массивы, которые "сохраняются" по умолчанию, и их идентификатор также является постоянным. По умолчанию этот параметр равен 1. -
Как обрабатывается совместимость с сохраненными играми?.
Сохраненные массивы хранятся в файле sfallgv.sav (в сохраненной игре) в новом (более гибком) формате сразу после старых массивов. Таким образом, в принципе, когда вы загружаете старую сохраненную игру, sfall загрузит массивы из старого формата и сохранит их в новом формате при следующем сохранении игры. Если вы загрузите сохраненную игру, созданную с помощью sfall 3.4, используя sfall 3.3 (например), игра не должна завершиться сбоем, но все массивы будут потеряны. -
Ранее вам приходилось указывать размер в байтах для элементов массива. Этот параметр теперь игнорируется, и вы можете хранить строки произвольной длины в массивах.