As is known, the developers of "Heroes of Might and Magic V", while embedding the Lua scripting language into their creation, decided for reasons unknown to anyone to do without standard function libraries and not include them in the game. It was a mistake, as the creators of Lua warn in the manual: "If you have not included this library in your application, you must carefully check whether these capabilities are indeed not required."
Fortunately, it turned out that some functions can be written in Lua itself, which is what I did. Yes, in terms of efficiency and functionality they are far from the originals, but meanwhile, they provide a wealth of new possibilities.
The format describing the arguments and return values of functions in this manual looks like this:
return_values = function (parameters, [optional_parameters])
********** BASIC FUNCTIONS **********
value = assert (value, [message])Raises an error and displays the message message (default - "assertion failed!"), if value == nil; otherwise returns value.
error ([message])Raises an error and displays the message message (default - "unknown error").
vartype = type (value)Determines the variable type: "nil", "number", "string", "table", "function".
vartypetable = types (values)Creates a new table that is a copy of the passed table, where all values are replaced by strings describing the variable types (see type).
index, element = next (table, indexprev)Gets the index and corresponding value following indexprev in table. If indexprev == nil, it returns the first index and value.
results = pcall (func, [...])Calls function func with parameters ... in protected mode and returns the result. That is, if an error occurs in the called function, it is not passed further, no error message is displayed, and pcall returns nil. If the function completes without errors, pcall will return the results from the function in a table with field n (see table.pack).
parsed_function = loadstring (chunk, [env])Similar to parse: interprets the passed string chunk as the body of a Lua function and returns this function. But unlike parse, loadstring returns a function that can accept parameters like a function with an undefined number of parameters, i.e., via the arg table (arg[1] - first argument, arg[2] - second, ..., arg[arg.n] - last). You can also set one external local variable named env (accessed as %env). If env is a table, it becomes possible to change its fields (for example, %env.n = %env.n + 1), but the variable itself cannot be changed in any case (%env = 1 will raise an error).
selected = select (index, ...)If index is a number, the function returns the element from the list of passed arguments ... at the specified position (negative numbers mean counting from the end of the list). Otherwise, index must be the string "#", in which case the function will return the number of passed parameters (excluding index).
converted = tonumber (v)Tries to convert the passed value into a number. This is only possible if the value is already a number or a string that can be converted to a number by standard rules. Otherwise, it returns nil.
converted = tostring (v)Converts a value to a string. nil, numbers and strings are passed literally; tables and functions are replaced by markers "" and "[function]" respectively.
hideerror (hide)Disables or enables the output of script errors to the console. If parameter hide == nil or is not specified, errors are displayed; otherwise, they are not.
_VERSIONA string describing the current version of Lua. Currently, value = "Lua 4.0"
********** TABLE HANDLING **********
package = table.pack (...)Accepts any number of values and returns them packed into a table. The table has field n - the number of elements.
... = table.unpack (table, [i, [j]])Unpacks table, returning multiple values. i and j set the index of the first and last element of the table; however, the function cannot return more than 100 values. By default i=1, j=length of array.
length = table.getn (table)If table has field n, it returns the value of this field. Otherwise, it returns the length of the array - the index of the last non-nil element in the sequence.
Example:
t={2,4,8,nil,32,nil}
print(table.getn(t)) --> 3
max = table.maxn (table)Returns the index with the largest numerical value. If the table has fields where the index is not a number or string, an error occurs. Example:
-- t from previous example
print(table.maxn(t)) --> 5
table.insert (table, value, [pos])Inserts value into table at position pos, shifting up all subsequent elements. If pos is not specified, the value is inserted at the end of the table.
removedvalue = table.remove (table, [pos])Removes element from position pos, shifting down all subsequent elements. If pos is not specified, it removes the last element of the array. Returns the value of the removed field.
table.sort (table, [comp])Sorts an array using a comparison function comp. comp must be a function that returns nil for two elements if the first is greater than the second. Also, comp can be a string "<" or ">", in which case the array will be sorted in ascending or descending order respectively.
joined = table.concat (table, [sep, [begin, [end]]])Joins all values of array table into a string, separating each element by string sep, from element begin to end. Default values: sep="", begin=1, end=table.getn(table). Values within this range must be numbers or strings.
returned = table.foreach (table, function)Calls the function for each element of table, passing it the index and value. If the function returns any value other than nil, the loop is interrupted and table.foreach returns that value.
returned = table.foreachi (table, function)Calls the function for each element of array table in order, passing it a numerical index and value. If the function returns any value other than nil, the loop is interrupted and table.foreachi returns that value.
table2 = table.copy(table1, [table2])Copies all elements of table table1 into table table2. Creates a new table if the second parameter is not specified. Returns table2 (or the new table).
In particular
list = table:copy() -- same as table.copy(table)
will create a new table containing all functions of table. This makes it possible to use the table in an object-oriented style: list:insert(...), list:unpack(), list:concat(", ") etc.
********** STRING OPERATIONS **********
charset = string.spread (string, [mode, [limit]])Returns an array where each element corresponds to a separate character of the string string. It is possible to limit the number of processed characters by specifying the third parameter; this is necessary to speed up the process, as the function can slow down significantly when processing strings longer than 1000 characters. By default, the limit is 1000, but it can also be changed by assigning string.limit a desired value. A limit above several thousand followed by long string processing may cause the game to crash. Tables can be memoized for further use by string library functions. This is handled by field string.mode (and optional parameter mode), which can take one of the following string values: "#*", "#+", "*", "+". The # symbol means that if the required table exists, a new one will not be created; the absence of this symbol means a new character table for the string will be created every time. If the table was not found in the buffer or the mode does not contain #, a new one is created. In this case, it will be written to the buffer only if the mode contains +. The default mode is "#*".
string.clearbuf ()Clears the buffer of all saved strings.
capture, begin, end = string.match (string, pattern, [init])Searches for string pattern in string string, starting from position init (or the beginning if absent). Returns the found substring and occurrence indices - where the searched substring starts and ends. Search patterns are supported.
length = string.len (string)Returns the length (number of characters) of the string.
byte = string.byte (string, i)Returns the numerical code of the i-th character of string string.
string.bytesA table containing 256 pairs, where the key is 1 character and the value is the code of that character.
string = string.char (bytetable)Returns a string in which each element of table bytetable corresponds to a character with that code. For example:
string.char{97, 98, 99} --> "abc"
string.charsA table containing 256 pairs, where the key is a number from 0 to 255 and the value is the character with that code.
substring = string.sub (string, [begin, [end]])Returns a substring of string string, starting from character number begin and ending with character number end. Negative values are interpreted as indices from the end of the string. Default values: 1 and -1, i.e., the whole string.
converted, changes = string.gsub (string, pattern, repl, [max])Replaces all occurrences of string pattern in string string with repl. repl must be a table containing fields f, t, s. First, function f is called with parameters: found substring, start index, end index. If the field is missing or the function returns nil, then table t is checked. The found substring is passed to it as an index. If field t is missing or there is no requested value in the table, string s is substituted. In the absence of string s, the substring remains unchanged. The number of replacements can be limited by an optional fourth parameter. The function returns the modified string and the number of replacements made.
Example:
string.gsub("choose(_HERO, _HUT, _OWNER)", "_%u+", {t={_HERO='"'..hero..'"', _HUT=[["hut3"]], _OWNER=GetObjectOwner(hero)}}) --> 'choose("Brem", "hut3", 1)', 3
matchtable = string.gmatch (string, pattern)Returns an array with all occurrences of pattern in string string. Therefore, the construction
for i, matched in string.gmatch(string, pattern) do
-- ...
end
will execute the loop body for all substrings. If order is important, you should use the construction
local matchtable = string.gmatch(string, pattern)
for i=1,table.getn(matchtable) do
local matched = matchtable[i]
-- ...
end
Example:
for i, objective in string.gmatch(GetAllNames(3), "%S+") do
if GetObjectiveState(objective) ~= OBJECTIVE_COMPLETED then
print("Task \"", objective, "\" not completed")
end
end
********** PATTERNS **********Character class:
A character class is used to represent a set of characters. The following combinations are allowed in the description of a character class:
x - Here x can be any non-reserved characters: ^$()%.[]*+-?. Represents the character x directly.
%a - Represents all letters.
%c - Represents all control characters.
%d - Represents all digits.
%g - Represents all printable characters except space.
%l - Represents all lowercase letters.
%p - Represents all punctuation characters.
%s - Represents all whitespace characters.
%u - Represents all uppercase letters.
%w - Represents all alphanumeric characters.
%x - Represents all hexadecimal digits.
%x - Here x specifies any non-alphanumeric character. Represents the character x. This is the standard way to escape control special characters. It is better to ensure that any punctuation character (even a non-control one!) is preceded by % when used in a pattern.
[char-set] - Represents a class that is the union of all characters in char-set. A range of characters can be defined by separating the end characters of the range with a hyphen (-). All %x classes described above can also be used as components in char-set. All other characters in char-set are represented as is. For example, [%w_] (or [_%w]) represents all alphanumeric characters plus the underscore character, [0-7] represents octal digits, and [0-7%l%-] represents octal digits plus lowercase letters plus the hyphen character. Interaction between ranges and classes is undefined. Consequently, patterns like [%a-z] or [a-%%] have no meaning.
[^char-set] - Represents the inversion of char-set, where char-set is interpreted as above.
For all classes represented by single characters (%a, %c, ...), the corresponding uppercase letter represents the complement of the class. For example, %S represents all non-whitespace characters.
Definitions of character, space, etc., depend on the current locale. In particular, the class [a-z] may not be equivalent to %l. The latter form should be preferred for portability. (Current locale - Russia [Russian_Russia.1251]).
Pattern element:
A pattern element can be:
A single character class, which matches any single character in the class.
A single character class followed by *, which matches 0 or more repetitions of characters in the class. These repetition elements will always match the longest possible sequence.
A single character class followed by +, which matches 1 or more repetitions of characters in the class. These repetition elements will always match the longest possible sequence.
A single character class followed by ?, which matches 0 or 1 occurrence of a character in the class.
Patterns:
A pattern is a sequence of pattern elements.
********** MATHEMATICAL LIBRARY **********
modul = math.abs (num)Returns the absolute value of a number.
rem = math.fmod (x, y)Returns the remainder of dividing x by y. Unlike the built-in mod function, it does not raise an error if the second parameter is zero.
ceil = math.ceil (num)Rounds a number up.
floor = math.floor (num)Rounds a number down.
rounded = math.round (num, [precision])Rounds number num to precision place (or to an integer). Using positive precision values is not recommended due to the inaccuracy of representing numbers themselves.
val = math.pow (x, y)Raises x to the power of y. y must be an integer.
val = math.root (x, root)Calculates the root of degree root from number x.
intg, frac = math.modf (num)Returns two values: the integer and fractional part of a number.
random = math.random ([x], [y])If called without parameters, returns a random number in the range [0; 1). If one parameter is passed - it returns a random integer in the range [1; x]; if two are passed, then in the range [x; y]. Works independently of the built-in random function. The function operates on a linear congruential PRNG with a period of 65536.
math.randomseed (seed)Sets the "seed" for generating the sequence of random numbers. Identical seeds determine the same sequence. By default, seed = 0 is always set.
min = math.min (arg, ...)Returns the minimum of its arguments. All arguments must be of the same type - all numbers or all strings.
max = math.max (arg, ...)Returns the maximum of its arguments. See note for math.min.
rad = math.rad (deg)Converts an angle given in degrees to radians.
deg = math.deg (rad)Converts an angle given in radians to degrees.
sin = math.sin (rad)Calculates the sine of an angle given in radians.
cos = math.cos (rad)Calculates the cosine of an angle given in radians.
tg = math.tan (rad)Calculates the tangent of an angle given in radians.
factorial = math.fact (n)Calculates the factorial of number n, which must be a non-negative integer.