Skip to content

Posts from Scripts

4.8 (8 ratings)
In reply to RedHeavenHero
User Avatar
Auto-translated
RedHeavenHero
Thank you. No matter how many times I check, the bug doesn't appear; only players in the forum thread wrote about it, so I can't verify it myself.

You can reserve a scripted hero by temporarily placing a mod that unlocks these heroes in the data folder. Alternatively, you can create a non-scripted hero, go to players > player_number > ReservedHeroes (in the property tree), click "..." on the desired hero, and select Shared for the scripted hero.
Battle arenas are objects of type AdventureFlybyScene.

In general, I actually did it a little differently. I placed Kha-Belekh on the map, then went to the map's property tree and created an entry in ReservedHeroes for the desired player. When I clicked on ..., I found my map in the list of single maps, which contained only one file, the name of which consists of many different letters and numbers. I selected it; this is the Kha-Belekh that I placed on the map earlier. Now it is reserved for a specific player. Could it be that StartCombat doesn't recognize it because it's on the map and simultaneously reserved? Will the settings be reset if I delete it?
Кампании для Heroes V 3.1 (Трилогия):

Пробуждение зла
Нашествие из Преисподней
Смена эпох

Скачать все кампании одним архивом: Яндекс.Диск Google.Диск

You can download the set of 3 Campaigns (English version) here


Одиночные сценарии Heroes V 3.1:


Незваные гости
Красный кристалл
Синий кристалл
Закат тьмы

Мультиплеерные карты для Heroes V 3.1:

Легендарная война
Сердце вулкана
Передел мира
In reply to MasteR
User Avatar
Auto-translated
MasteR
Basically, I did it a bit differently. I placed Kha-Beleth on the map, then went into the map properties tree, where I created an entry in ReservedHeroes for the desired player. When I clicked on ..., I found my map in the list of single maps, which contained only one file, the name of which consists of many different letters and numbers. I selected it; this is the Kha-Beleth that I placed earlier. Now it is reserved for a specific player. Perhaps StartCombat doesn't recognize it because it's on the map and simultaneously reserved. Will the settings reset if I delete it?
It would be better to use a verified method. At least because manually created links with "many different letters and numbers" are not saved.
Карты для Героев Меча и Магии 5
Одиночные: Завеса срывается, Посол, Последний рывок, Эхо Пустоты
Кампания: Империя Единорога

Существа NCF
Орден Порядка: 1
Нейтралы: 1 2 3 4
In reply to RedHeavenHero
User Avatar
Auto-translated
RedHeavenHero
It would be better to use a proven method. At least because handwritten links with "many different letters and numbers" are not saved.

Everything worked out, thank you)

Added after 23 hours 25 minutes
How can you "force" an enemy hero to cast a specific spell in a combat script? Moreover, this spell affects the terrain, i.e., you need to calculate the location of the troops.
Кампании для Heroes V 3.1 (Трилогия):

Пробуждение зла
Нашествие из Преисподней
Смена эпох

Скачать все кампании одним архивом: Яндекс.Диск Google.Диск

You can download the set of 3 Campaigns (English version) here


Одиночные сценарии Heroes V 3.1:


Незваные гости
Красный кристалл
Синий кристалл
Закат тьмы

Мультиплеерные карты для Heroes V 3.1:

Легендарная война
Сердце вулкана
Передел мира
User Avatar
Auto-translated
UnitCastAreaSpell(unit, spell_id, x, y) – forces the hero to cast an area-of-effect spell; there must be enough mana.
unit – the name of the combat unit
spell_id – the spell ID
x, y – coordinates

x, y = pos(unit) – returns the coordinates of a unit by its name.
Карты для Героев Меча и Магии 5
Одиночные: Завеса срывается, Посол, Последний рывок, Эхо Пустоты
Кампания: Империя Единорога

Существа NCF
Орден Порядка: 1
Нейтралы: 1 2 3 4
In reply to RedHeavenHero
User Avatar
Auto-translated
RedHeavenHero
UnitCastAreaSpell(unit, spell_id, x, y) -- forces the hero to cast an area-of-effect spell; there must be enough mana.
unit - the name of the combat unit
spell_id - the spell ID
x, y - coordinates

x, y = pos(unit) -- returns the coordinates of a unit by its name

Thank you, it seems I understand everything now, but where can I get the unit name for pos? unitNames() seems to return a string containing all the names, but how can I extract the desired one from this string?
Кампании для Heroes V 3.1 (Трилогия):

Пробуждение зла
Нашествие из Преисподней
Смена эпох

Скачать все кампании одним архивом: Яндекс.Диск Google.Диск

You can download the set of 3 Campaigns (English version) here


Одиночные сценарии Heroes V 3.1:


Незваные гости
Красный кристалл
Синий кристалл
Закат тьмы

Мультиплеерные карты для Heroes V 3.1:

Легендарная война
Сердце вулкана
Передел мира
User Avatar
Auto-translated
creatures = GetCreatures(side)
Returns an array containing the names of the creatures fighting for side side (0 or 1).
Карты для Героев Меча и Магии 5
Одиночные: Завеса срывается, Посол, Последний рывок, Эхо Пустоты
Кампания: Империя Единорога

Существа NCF
Орден Порядка: 1
Нейтралы: 1 2 3 4
In reply to RedHeavenHero
User Avatar
Auto-translated
RedHeavenHero
creatures = GetCreatures(side)
Returns an array with the names of the creatures fighting for side side (0 or 1).

Exactly what I needed! Thank you!
Кампании для Heroes V 3.1 (Трилогия):

Пробуждение зла
Нашествие из Преисподней
Смена эпох

Скачать все кампании одним архивом: Яндекс.Диск Google.Диск

You can download the set of 3 Campaigns (English version) here


Одиночные сценарии Heroes V 3.1:


Незваные гости
Красный кристалл
Синий кристалл
Закат тьмы

Мультиплеерные карты для Heroes V 3.1:

Легендарная война
Сердце вулкана
Передел мира
User Avatar
Auto-translated
Is it possible to trigger effects on the arena using a combat script? `summoncreature` doesn't work for me because the summoned creatures disappear when the main creatures are destroyed, and `addcreature` somehow doesn't have any effect.
Кампании для Heroes V 3.1 (Трилогия):

Пробуждение зла
Нашествие из Преисподней
Смена эпох

Скачать все кампании одним архивом: Яндекс.Диск Google.Диск

You can download the set of 3 Campaigns (English version) here


Одиночные сценарии Heroes V 3.1:


Незваные гости
Красный кристалл
Синий кристалл
Закат тьмы

Мультиплеерные карты для Heroes V 3.1:

Легендарная война
Сердце вулкана
Передел мира
User Avatar
Auto-translated
when the main creatures are destroyed, the summoned creatures disappear
The next argument after x, y, SummonCreature, if equal to nil, creates a real squad.
The second option: do not allow the battle to end automatically until at least one side has a squad. For example, this is how I implemented the battle with a mage in the fifth mission.
function finish()
EnableAutoFinish(nil)
while not combatStarted() do
sleep(20)
end
while GetCreatures(0)[0] and GetCreatures(1)[0] do
sleep(20)
end
EnableAutoFinish(1)
end

startThread(finish)
Карты для Героев Меча и Магии 5
Одиночные: Завеса срывается, Посол, Последний рывок, Эхо Пустоты
Кампания: Империя Единорога

Существа NCF
Орден Порядка: 1
Нейтралы: 1 2 3 4
In reply to RedHeavenHero
User Avatar
Auto-translated
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.

_VERSION
A 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.bytes

A 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.chars

A 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.
Attachments 1
1 file attached • Total size: 7.6 KB
Карты для Героев Меча и Магии 5
Одиночные: Завеса срывается, Посол, Последний рывок, Эхо Пустоты
Кампания: Империя Единорога

Существа NCF
Орден Порядка: 1
Нейтралы: 1 2 3 4
User Avatar
Auto-translated
Epic. I often implemented frequently used functions for myself, such as table.insert/remove, and many mathematical ones, but I still had a long way to go before reaching this scale. I'll gladly read the source code.

Added 26 minutes later
By the way, I've been wondering about something for a while - for deleting an element from a table, the following construct is used:
foo[bar] = nil
I've read about it before, but my own experiments in Heroes showed that the size of the table doesn't change, meaning that if you use, for example, a loop to iterate through the elements:
for index, element in foo do
...
end
the deleted element will still be iterated over. This needs to be taken into account when working with the library (checking for nil), or is my approach to Lua simply too amateurish?
User Avatar
Auto-translated
Assigning `nil` to an element does not remove it from the table. Removing elements in this way is only possible in newer versions of Lua. This needs to be taken into account.
Карты для Героев Меча и Магии 5
Одиночные: Завеса срывается, Посол, Последний рывок, Эхо Пустоты
Кампания: Империя Единорога

Существа NCF
Орден Порядка: 1
Нейтралы: 1 2 3 4
User Avatar
Auto-translated
RedHeavenHero, hello! I think the library will be very useful, although it would be nice to somehow come up with something and still add some new features to the scripting language of Heroes 5 (those that are not feasible through libraries or can be implemented with terrible and complex workarounds). But that's just a dream...
 

К А
Стикеры GBF в Telegram
In reply to Ment
User Avatar
Auto-translated
Ment
RedHeavenHero, that's great! I think the library will be very useful, although it would be nice to somehow come up with something and still add some new features to the scripting language of the fifth game (those that are not feasible through libraries or can be implemented with terrible and complex workarounds). But that's just a dream...
Thank you. So, it turns out that string.spread splits the string into characters using something like this workaround, hence the limitation on the number of characters. The other string.* functions are already based on string.spread. Some other functions, such as type, types, pcall, error, assert, tonumber, tostring, use errors to calculate the result.
Карты для Героев Меча и Магии 5
Одиночные: Завеса срывается, Посол, Последний рывок, Эхо Пустоты
Кампания: Империя Единорога

Существа NCF
Орден Порядка: 1
Нейтралы: 1 2 3 4
In reply to RedHeavenHero
User Avatar
Auto-translated
A new function, **loadstring**, has been added to lualib.
Карты для Героев Меча и Магии 5
Одиночные: Завеса срывается, Посол, Последний рывок, Эхо Пустоты
Кампания: Империя Единорога

Существа NCF
Орден Порядка: 1
Нейтралы: 1 2 3 4

Statistics

Welcome our newest member: Emil