Типы переменных
Существуют три типа переменных в скриптах TES: короткие (short), длинные (long) и с плавающей точкой (float). Им могут быть присвоены следующие значения:
Short -32,768 to 32,767 (целочисленное со знаком)
Long -2,147,483,648 to 2,147,483,647 (длинное целочисленное со знаком)
Float 3.4E +/- 38 (с плавающей точкой, 7 разрядов)
Границы типа long верны только отчасти.
В TES CS максимальное значение, которое вы можете задать, равняется 2147483520 (Информация с форумов / Argent).
Теоретически должны также быть еще и строковые переменные, но, по моим данным, они не включены в редактор.
К сожалению, нет типа переменных, в которых бы можно было сохранить идентификаторы объектов, что ограничивает язык скриптов до определенной степени.
Переменные могут быть сгруппированы как локальные переменные (действительны только в том скрипте, где они объявлены) и глобальные переменные (действительны во всех скриптах).
Примечание: Глобальная переменная типа long на самом деле имеет тип float!
В локальном скрипте переменная типа long имеет 32 бита. Но если использовать ее как глобальную, то количество битов падает до 24, как у типа float.
Открыл это Mental Elf, когда пытался использовать “упаковку битов”, чтобы получить 32 флага из глобальной переменной типа long. (Информация с форумов / mental elf).
Локальные переменные
Локальные переменные должны быть объявлены в скрипте:
Float floatvarname
Short shortvarname
Long longvarname
Локальные переменные уникальны в пределах данного экземпляра скрипта.
То есть одинаковые локальные переменные на разных объектах не влияют друг на друга.
Длина имени переменной не ограничена, но запрещено использовать имена функций (будут ошибки в игре) и зарезервированные знаки (напр. -, +, /, *, =, ", и т.д.).
Это просто не даст скомпилировать скрипт.
Т.е. "variable-1" не подходит для имени переменной.
Знак подчеркивания допускаются (“my_variable”).
Точки в именах использовать нельзя (см. ниже «Использование переменных в других локальных скриптах»).
Глобальные переменные
Чтобы объявить глобальную переменную, зайдите в меню Gameplay и выберете Globals.
Нажмите New, задайте имя и начальное значение глобальной переменнойПочему-то при установке GFM 4.00 глобальные переменные в игре не устанавливаются в то значание, которое вы поставили в редакторе. Так что рекомендую использовать стартовый глобальный скрипт и уже в нем явно указать начальное значение переменной. (Прим. Gwathlobal).
По умолчанию оно равно 0.
Глобальные переменные полезны в квестах, когда вам нужно отследить события, удаленные в пространстве и времени.
Также это простой способ обмена информацией между скриптами.
Примечание.
Обращайте внимание, что глобальная переменная записывается в сохранение и после отключения плагина привносившего оную, будут возникать критические ошибки.
По этому, всячески старайтесь обходиться без Глобальных переменных!
И если игра (случайно) поменяет значение оной, опять же, могут случится неизвестного рода оказии.
Примечание: если вы объявили локальную переменную с тем же именем, что и глобальная переменная, глобальная переменная не будет использоваться в вашем скрипте.
Использование переменных в других локальных скриптах и объектах
Set … to
Если уникальный объект имеет скрипт на себе, то вы можете изменять переменные на нем извне следующим образом:
Set MyObject.variable to 100
или
Set MyObject.variable to local_variable
Этот метод изменяет локальную переменную в скрипте объекта.
Объект должен при этом иметь скрипт на себе, и конечно, он должен быть активен (то есть локальный скрипт должен быть в той же ячейке).
Примечание: Скриптовая система использует только первый объект в базе данных, поэтому вы должны иметь только одну копию объекта.
Отметьте, что обратный метод не работает:
Set local_variable to MyObject.variable ; Это не работает!
Используйте глобальную переменную, чтобы перемещать информацию, или установите local_variable из другого скрипта, используя вышеприведенный пример.
if ( anotherobject.x > 0 )
работает.
Более того, недавно я осознал, что подобный синтаксис работает и для глобальных скриптов:
set Global_script_name.variable to 1
Это полезно, чтобы избежать большого количества глобальных переменных или для отладки глобальных скриптов в консоли.
МСФД 9 добавило сюда это:
Note: If your object or global script starts with a number, you need to put quotes around it.
"11NPC01".RemoteVar ;---Good
"11NPC01.RemoteVar" ;---BAD
11NPC01.RemoteVar ;---BAD
A caution when setting variables from outside the script (DinkumThinkum):
If you recompile the target script (i.e., the local script on 'MyObject'), it's a good idea to also recompile any scripts that reference variables in that script.
Reason: if the target 'variable' winds up in a different position in the target script's list of variables, then any scripts trying to set that variable will break if they're not recompiled.
I.e., if 'variable' is the 14th variable declared in the local script on 'MyObject', and you add a new variable ahead of it so that 'variable' is now the 15th variable declared, other scripts will need to be recompiled in order to find 'variable' in its new position, otherwise the script will end up changing the wrong variable, leading to very strange bugs.
One way to reduce the chances of this tripping you up is declare variables referenced by other scripts first, before other variables that aren't referenced externally. Then just be careful to only add or remove variables after the block of externally referenced variables. However (to be safe), it's still a good idea to recompile scripts that reference variables in other scripts any time you've added or removed variables in the other scripts.
Использование переменных в функциях
К сожалению, одним из ограничений скриптов TES является то, что только некоторые функции принимают переменные в качестве параметров.
Тип аргументов, которые принимают функции, указан в списке функций ниже.
Примечание: Для некоторых функция, где возможны Get-функции and Set-функции, работа может быть построена, используя функцию while.
В мсфд 9 был добавлен новый параграф:
A Note about Floats:
Floating point numbers in a computer are stored in a format similar to that used for scientific or engineering notation.
The number is rounded off to a fixed number of significant digits, any leading or trailing zeros are dropped, and an exponent is added to indicate the correct location of the decimal or binary point.
The number 2385901045 would be stored similar to this:
2.385901x109
In fitting the number into a fixed number of bytes, we have lost the end 3 digits, so the number is no longer quite what you set it to.
If you set a float to a small number, like 5.5, it would still be stored as 5.5, because as it doesn't take up much room, no numbers need to be cut off.
The advantage of this format is that a wide range of values can be expressed using a relatively small number of digits or bytes. The disadvantage is that the rounding off means floating point numbers don't have the precision of an integer, so they shouldn't be used when you need to make exact comparisons or keep track of exact counts.
For example, a floating point variable is fine if you just need to check if a distance is greater or less than a certain value. But if you need to check if the player has specific number of some item in their inventory, then you want to use a long or short integer variable for the count.
(Forum info / DinkumThinkum)
An example by BungaDunga shows that when doing math with floats, the answer isn't always what you expect:
Float num1
Float num2
Float num3
Set num1 to ( 1 / 3 )
;num1 is now 0.3333333
Set num2 to 3
;num2 is now 3
set num3 to num1 * num2
;num3 is now 0.9999999, rather than what you would expect, 1.
if ( num3 == 1 )
; Never happens.
endif
A lot of functions return float values (e.g. GetDistance, GetScale, GetSecondsPassed…): the same thing applies.
Test a range, not an exact value! E.g.:
if ( ( GetPos x ) == 500 )
;will be false if it's 499.9999, or 500.0001, etc
endif
but this will work:
if ( ( GetPos x ) > 499.5 )
if ( ( GetPos x ) < 500.5 )
;it's close enough for me
endif
endif
Another common mistake is to check if the GameHour is an exact number.
As the Gamehour variable is increased every frame, and every frame is a slightly diffrent length, the Gamehour variable soon ends up with a value like this, 10.12853.
So never test if the gamehour is exatly equal to a value, as it is very unlikley to happen, test if it is greater than or equal to a value.