Skip to content

Posts from Scripts

4.8 (8 ratings)
User Avatar
Auto-translated
question for experienced scripters: what is the best way (with the minimum amount of code) to create a handler for building visits, such as a Necropolis, for example? My ideas are limited to a method – by enabling/disabling a check constant in the trigger for a new day with the conditions I need. But maybe there is a more efficient way?
Карты для Heroes V: Повелители орды:
Multiplayer: Господство, Извечное противостояние, Война за Магию, Торговая империя, Анатомия войны, Эксперимент
SingleScenario: Последний Рубеж, Трон, Элиралис, Вернуться домой!, Лабиринты разума
Campaign: Колонизация
User Avatar
Auto-translated
KioM, please provide a more detailed description of what you need, because as I understand it, the "building visit handler" is a function that triggers when a building is visited. In that case, it's unclear what the problem is if there's already a trigger for touching an object.
In reply to Jack_of_shadows
User Avatar
Auto-translated
Jack_of_shadows
KioM, please describe in more detail what you need, because as I understand it, the "building visitation handler" is a function that triggers when a building is visited. In that case, it's unclear what the problem is if there's a trigger for touching the object.

almost) I need: there's a Temple (a unique one). When activated, a script runs, a battle takes place, etc. Then, I want to make it so that when it's visited, say, in the following few days, until the start of a new week, it displays a message and denies access (this is also clear). But how can I best check whether it has already been visited by a player or multiple players? The idea was to use a state indicator in the new day function through a trigger, but maybe there's a simpler and more universal feature for such things? For similar buildings, that would transmit information that it has already been looted.
Карты для Heroes V: Повелители орды:
Multiplayer: Господство, Извечное противостояние, Война за Магию, Торговая империя, Анатомия войны, Эксперимент
SingleScenario: Последний Рубеж, Трон, Элиралис, Вернуться домой!, Лабиринты разума
Campaign: Колонизация
User Avatar
Auto-translated
It's slightly easier during activation to save the current date in a variable and, when the object is touched, compare the date with that variable. If the behavior is the same for all players, there is one variable; if it's different for each player, there is a table of variables.
If you need to visually indicate on the object whether it has been looted or has already been refreshed, then you can only do this through a trigger for the new day; there are no other ways.
In reply to Jack_of_shadows
User Avatar
Auto-translated
Jack_of_shadows
It might be slightly easier to save the current date in a variable during activation, and then compare the date with this variable when the object is touched.
Thank you, this is exactly what I needed.
Карты для Heroes V: Повелители орды:
Multiplayer: Господство, Извечное противостояние, Война за Магию, Торговая империя, Анатомия войны, Эксперимент
SingleScenario: Последний Рубеж, Трон, Элиралис, Вернуться домой!, Лабиринты разума
Campaign: Колонизация
User Avatar
Auto-translated
The following code is available:
local NHF_Trigger_env = {trig = {}}
print("T1:");
NHF_Trigger_env.Trigger = Trigger
function NHF_Trigger_env.tostring(a)
return a and (a.."" ~= a and a or '"'..a..'"') or "nil"
end;
function NHF_Trigger_env.emptytable(t)
print("T2:");
for k,v in t do
if v then return nil end
end
return 1
end;
function NHF_Trigger_env.hasparam(i)
print("T3:");
return i ~= 0 and i ~= 10 and i ~= 11
end;
function __HANDLER(trigtype, param)
print("T4:");
print("T5:");
local h = %NHF_Trigger_env.trig[trigtype]
if not h then return end
local NHF_Trigger_env = %NHF_Trigger_env
return function(a, b, c, d)
a = %NHF_Trigger_env.tostring(a)
b = %NHF_Trigger_env.tostring(b)
c = %NHF_Trigger_env.tostring(c)
d = %NHF_Trigger_env.tostring(d)
local args = "(" .. a .. "," .. b .. "," .. c .. "," .. d .. ")"
print("T6:");
for sender, tab in %h do
if sender ~= 0 then
local handler = %NHF_Trigger_env.hasparam(%trigtype) and tab and tab[%param] or tab
if handler then
startThread(parse(handler .. args))
end
end
end
local tab = %h[0]
print("T7:");
if tab then
local handler = %NHF_Trigger_env.hasparam(%trigtype) and tab and tab[%param] or tab
if handler then
print("T8:");
startThread(parse(handler .. args))
end
end
end
end;
function Trigger(sender, trig, par, handler)
print("T9:");
if sender .. "" ~= sender then
print("T10:");
sender, trig, par, handler = 0, sender, trig, par
end
if not %NHF_Trigger_env.hasparam(trig) then
print("T11:");
par, handler = nil, par
end
local need_disable = handler ~= nil
if handler then
print("T12:");
%NHF_Trigger_env.trig[trig] = %NHF_Trigger_env.trig[trig] or {}
if par then
print("T13:");
%NHF_Trigger_env.trig[trig][sender] = %NHF_Trigger_env.trig[trig][sender] or {}
%NHF_Trigger_env.trig[trig][sender][par] = handler
else
print("T14:");
%NHF_Trigger_env.trig[trig][sender] = handler
end
else
print("T15:");
if %NHF_Trigger_env.trig[trig] then
if %NHF_Trigger_env.trig[trig][sender] then
if par then
print("T16:");
%NHF_Trigger_env.trig[trig][sender][par] = nil
need_disable = %NHF_Trigger_env.emptytable(%NHF_Trigger_env.trig[trig][sender])
if need_disable then %NHF_Trigger_env.trig[trig][sender] = nil end
else
%NHF_Trigger_env.trig[trig][sender] = nil
end
need_disable = %NHF_Trigger_env.emptytable(%NHF_Trigger_env.trig[trig])
if need_disable then %NHF_Trigger_env.trig[trig] = nil end
end
end
end
if not need_disable then return end
if par then
print("T17:");
%NHF_Trigger_env.Trigger(trig, par, handler and "__HANDLER(" .. trig .. "," .. %NHF_Trigger_env.tostring(par) .. ")")
else
%NHF_Trigger_env.Trigger(trig, handler and "__HANDLER(" .. trig .. ")")
end
print("T18:end");
end;

It produces an error:


Do you have any guesses as to what might be wrong here?
Attachments 1
1 file attached • Total size: 21.3 KB
Моды для HeroesV:
NHF 0.90 : NHF - группа в VK

Карты для HeroesV:
Путешествие , Условие крови , Рука судьбы.Часть 1: В поход , Рука судьбы.Часть 2: Отчаянье , Рука судьбы.Часть 3: Восхождение , Стойкость
Абсолютная власть , Иду на Вы! , Корона Ургаша , На задворках
Мир надо уничтожить... Чтобы создать свой...
In reply to Dyrman
User Avatar
Auto-translated
Dyrman
The following code is provided:
local NHF_Trigger_env = {trig = {}}
print("T1:");
NHF_Trigger_env.Trigger = Trigger
function NHF_Trigger_env.tostring(a)
return a and (a.."" ~= a and a or '"'..a..'"') or "nil"
end;
function NHF_Trigger_env.emptytable(t)
print("T2:");
for k,v in t do
if v then return nil end
end
return 1
end;
function NHF_Trigger_env.hasparam(i)
print("T3:");
return i ~= 0 and i ~= 10 and i ~= 11
end;
function __HANDLER(trigtype, param)
print("T4:");
print("T5:");
local h = %NHF_Trigger_env.trig[trigtype]
if not h then return end
local NHF_Trigger_env = %NHF_Trigger_env
return function(a, b, c, d)
a = %NHF_Trigger_env.tostring(a)
b = %NHF_Trigger_env.tostring(b)
c = %NHF_Trigger_env.tostring(c)
d = %NHF_Trigger_env.tostring(d)
local args = "(" .. a .. "," .. b .. "," .. c .. "," .. d .. ")"
print("T6:");
for sender, tab in %h do
if sender ~= 0 then
local handler = %NHF_Trigger_env.hasparam(%trigtype) and tab and tab[%param] or tab
if handler then
startThread(parse(handler .. args))
end
end
end
local tab = %h[0]
print("T7:");
if tab then
local handler = %NHF_Trigger_env.hasparam(%trigtype) and tab and tab[%param] or tab
if handler then
print("T8:");
startThread(parse(handler .. args))
end
end
end
end;
function Trigger(sender, trig, par, handler)
print("T9:");
if sender .. "" ~= sender then
print("T10:");
sender, trig, par, handler = 0, sender, trig, par
end
if not %NHF_Trigger_env.hasparam(trig) then
print("T11:");
par, handler = nil, par
end
local need_disable = handler ~= nil
if handler then
print("T12:");
%NHF_Trigger_env.trig[trig] = %NHF_Trigger_env.trig[trig] or {}
if par then
print("T13:");
%NHF_Trigger_env.trig[trig][sender] = %NHF_Trigger_env.trig[trig][sender] or {}
%NHF_Trigger_env.trig[trig][sender][par] = handler
else
print("T14:");
%NHF_Trigger_env.trig[trig][sender] = handler
end
else
print("T15:");
if %NHF_Trigger_env.trig[trig] then
if %NHF_Trigger_env.trig[trig][sender] then
if par then
print("T16:");
%NHF_Trigger_env.trig[trig][sender][par] = nil
need_disable = %NHF_Trigger_env.emptytable(%NHF_Trigger_env.trig[trig][sender])
if need_disable then %NHF_Trigger_env.trig[trig][sender] = nil end
else
%NHF_Trigger_env.trig[trig][sender] = nil
end
need_disable = %NHF_Trigger_env.emptytable(%NHF_Trigger_env.trig[trig])
if need_disable then %NHF_Trigger_env.trig[trig] = nil end
end
end
end
if not need_disable then return end
if par then
print("T17:");
%NHF_Trigger_env.Trigger(trig, par, handler and "__HANDLER(" .. trig .. "," .. %NHF_Trigger_env.tostring(par) .. ")")
else
%NHF_Trigger_env.Trigger(trig, handler and "__HANDLER(" .. trig .. ")")
end
print("T18:end");
end;

It produces an error:


Do you have any idea what might be wrong here?
With what parameters was the overridden Trigger called?
Карты для Героев Меча и Магии 5
Одиночные: Завеса срывается, Посол, Последний рывок, Эхо Пустоты
Кампания: Империя Единорога

Существа NCF
Орден Порядка: 1
Нейтралы: 1 2 3 4
In reply to RedHeavenHero
User Avatar
Auto-translated
RedHeavenHero
What parameters were used when the overridden Trigger was called?

Type: OBJECT_TOUCH_TRIGGER
There is a check for the existence of a hero and a monster.
function __HANDLER(trigtype, param)
print("T4:"..trigtype);
print("T5:"..param);


By calling each trigger in a separate thread and using the necessary delays depending on whether it's a multiplayer map or not, it can be made to work in multiplayer. At least, some of the triggers will work somehow.
Attachments 1
1 file attached • Total size: 111.7 KB
Моды для HeroesV:
NHF 0.90 : NHF - группа в VK

Карты для HeroesV:
Путешествие , Условие крови , Рука судьбы.Часть 1: В поход , Рука судьбы.Часть 2: Отчаянье , Рука судьбы.Часть 3: Восхождение , Стойкость
Абсолютная власть , Иду на Вы! , Корона Ургаша , На задворках
Мир надо уничтожить... Чтобы создать свой...
In reply to Dyrman
User Avatar
Auto-translated
Dyrman
Type: OBJECT_TOUCH_TRIGGER
The check for the existence of a hero and a monster is in place.
function __HANDLER(trigtype, param)
print("T4:"..trigtype);
print("T5:"..param);


With each trigger being called in a separate thread and with the necessary delays depending on whether it's a multiplayer map or not, it can be made to work in multiplayer. At least, some of the triggers will work somehow.
I can't check it right now, but at first glance, you can try replacing

local handler = %NHF_Trigger_env.hasparam(%trigtype) and tab and tab[%param] or tab

with

local handler
if %NHF_Trigger_env.hasparam(%trigtype) then
handler = tab and tab[%param]
else
handler = tab
end

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

Существа NCF
Орден Порядка: 1
Нейтралы: 1 2 3 4
User Avatar
Auto-translated
The error is gone. Now, I need to check the map where there are several triggers.
Моды для HeroesV:
NHF 0.90 : NHF - группа в VK

Карты для HeroesV:
Путешествие , Условие крови , Рука судьбы.Часть 1: В поход , Рука судьбы.Часть 2: Отчаянье , Рука судьбы.Часть 3: Восхождение , Стойкость
Абсолютная власть , Иду на Вы! , Корона Ургаша , На задворках
Мир надо уничтожить... Чтобы создать свой...
User Avatar
Auto-translated
Unfortunately, a trigger on the map does not work if there is a later trigger.
Моды для HeroesV:
NHF 0.90 : NHF - группа в VK

Карты для HeroesV:
Путешествие , Условие крови , Рука судьбы.Часть 1: В поход , Рука судьбы.Часть 2: Отчаянье , Рука судьбы.Часть 3: Восхождение , Стойкость
Абсолютная власть , Иду на Вы! , Корона Ургаша , На задворках
Мир надо уничтожить... Чтобы создать свой...
User Avatar
Auto-translated
Is the trigger sender specified as another object?
That is, in the mod, all triggers should have an additional first parameter – the sender.
For example,
Trigger("NHF", OBJECT_TOUCH_TRIGGER, "mob", "handler_function")

Added 2 minutes later
Each unique sender can have its own trigger for this type of event and parameter (object, player, ...).
Карты для Героев Меча и Магии 5
Одиночные: Завеса срывается, Посол, Последний рывок, Эхо Пустоты
Кампания: Империя Единорога

Существа NCF
Орден Порядка: 1
Нейтралы: 1 2 3 4
In reply to RedHeavenHero
User Avatar
Auto-translated
RedHeavenHero
Is the trigger's sender specified as something else?
In other words, should all triggers in the mod have an additional first parameter – the sender?
For example,
Trigger("NHF", OBJECT_TOUCH_TRIGGER, "mob", "handler_function")

Added 2 minutes later
Each unique sender can have its own trigger for a given event type and parameter (object, player, etc.).
Yes, I've tried both ways. The result is the same.
If you override the trigger directly in the map, it works. With a different sender parameter. But you wouldn't rewrite the scripts of existing maps, would you?

Another question is about resetting the trigger, so that only the necessary one is reset. Would this be correct:
Trigger("NHF", OBJECT_TOUCH_TRIGGER, mob, nil);?
But if the trigger is reset in the map itself with Trigger(OBJECT_TOUCH_TRIGGER, mob, nil), wouldn't it affect all of them?

As I understand it, if the first parameter = nil, this is also a unique sender parameter.

I'm investigating delays and threads; they might be influencing things because the code itself seems correct.
Моды для HeroesV:
NHF 0.90 : NHF - группа в VK

Карты для HeroesV:
Путешествие , Условие крови , Рука судьбы.Часть 1: В поход , Рука судьбы.Часть 2: Отчаянье , Рука судьбы.Часть 3: Восхождение , Стойкость
Абсолютная власть , Иду на Вы! , Корона Ургаша , На задворках
Мир надо уничтожить... Чтобы создать свой...
In reply to Dyrman
User Avatar
Auto-translated
Dyrman
Yes, I tried both ways. The result is the same.
If you redefine the Trigger in the map itself, it works. With a different sender parameter. But you won't be rewriting the scripts of ready-made maps...
It is important that the Trigger override occurs before the map script and the mod script are executed.
It is also desirable to add the standard alias for the Trigger function:
SetTrigger = Trigger
to the end of that large piece of code that performs the override.
It is probably used rarely or not at all, but it should still be taken into account.
Another question is about resetting the trigger, so that only the necessary one is reset. Would this be correct:
Trigger("NHF", OBJECT_TOUCH_TRIGGER, mob, nil);?
Yes, that is correct.
And if the Trigger(OBJECT_TOUCH_TRIGGER, mob, nil); is reset in the map itself, will it affect all of them?
No, by default, calling the trigger with standard parameters (from the Manuals) will be interpreted as a call from sender 0 (as a number, not a string). That is, in this case, only the trigger set in the usual way will be reset, and all the "special" ones will remain.
However, emulation via Trigger(0, ...) is not possible, as this is equivalent to Trigger(NEW_DAY_TRIGGER, ...).
As I understand it, if the first parameter = nil, this is also a unique sender parameter.
No, the first parameter must be either a number (standard call), in which case it will be taken as the event type, or a string, in which case it will be taken as the sender. Passing nil as the first parameter will cause an error: attempt to concat a nil value.
If desired, the sender parameter can be placed at the end as an optional parameter, then any value can be sent as the sender, except nil (which will be equivalent to not specifying the parameter) and NaN (which is not indexed in tables because it is not equal to itself). This will require a small code modification.
Карты для Героев Меча и Магии 5
Одиночные: Завеса срывается, Посол, Последний рывок, Эхо Пустоты
Кампания: Империя Единорога

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

Statistics

Welcome our newest member: Emil