да просто почти все карты на гуи имеют на одно и тоже событие (например юнит атакован) около 50 триггеров
а во всяких петробалансах вообще лютейшая дичь, тупо событие на вход в регион имеет около двухста триггеров
Ну и даже если у тебя 10к+ строк кода, этот код же можно нормально структурировать, а не тупо приписывать в Map Custom Script каждый раз внизу.
так я и не говорил что нельзя переписывать)
я прямо так и подчеркнул что с нуля
структурировать надо код всегда
и по возможности на каждый вид события один триггер
иначе при дальнейших модификациях карты будет получаться всё более жесткое месиво из кода
и в один день настанет момент когда уже нереально будет контроллировать ~10к строк перемешанного кода, всплывет вопрос об оптимизации
любой человек без склонностей к мазохизму придет к выводу что надо переписывать с нуля всё хотяяяя, оно тоже мазохизм, но меньший)))
блин, да почему я путаю всё сегодня
вот заново примеры:
1
Регистрируется событие на "Горного короля" когда он начинает применять способность
Так же записываются условия и действия
Далее я жму любую из его способностей
Срабатывает событие
Вызывается первая функция-условие Condition1, она возвращает true - значит всё нормально
так же у Condition2
Далее на экран выводится текст:
text1
text2
Т.е сработали функции Action1 и Action2
function Action1 takes nothing returns nothing
call BJDebugMsg("text1")
endfunction
function Action2 takes nothing returns nothing
call BJDebugMsg("text2")
endfunction
function Condition1 takes nothing returns boolean
return true
endfunction
function Condition2 takes nothing returns boolean
return true
endfunction
function InitTrig_s takes nothing returns nothing
local trigger trg = CreateTrigger( )
call TriggerRegisterUnitEvent(trg, gg_unit_Hmkg_0001, EVENT_UNIT_SPELL_CHANNEL )
call TriggerAddCondition(trg, Condition(function Condition1))
call TriggerAddCondition(trg, Condition(function Condition2))
call TriggerAddAction(trg, function Action1)
call TriggerAddAction(trg, function Action2)
endfunction
2
я жму любую из его способностей
Срабатывает событие
Вызывается первая функция-условие Condition1, она возвращает true - значит всё нормально
а вот Condition2 возвращает false - значит действия триггера не будут выполняться и на экран ничего не выведется
function Action1 takes nothing returns nothing
call BJDebugMsg("text1")
endfunction
function Action2 takes nothing returns nothing
call BJDebugMsg("text2")
endfunction
function Condition1 takes nothing returns boolean
return true
endfunction
function Condition2 takes nothing returns boolean
return false
endfunction
function InitTrig_s takes nothing returns nothing
local trigger trg = CreateTrigger( )
call TriggerRegisterUnitEvent(trg, gg_unit_Hmkg_0001, EVENT_UNIT_SPELL_CHANNEL )
call TriggerAddCondition(trg, Condition(function Condition1))
call TriggerAddCondition(trg, Condition(function Condition2))
call TriggerAddAction(trg, function Action1)
call TriggerAddAction(trg, function Action2)
endfunction
3
тоже самое как в первом примере
function Action1 takes nothing returns nothing
call BJDebugMsg("text1")
endfunction
function Condition1 takes nothing returns boolean
return true
endfunction
function InitTrig_s takes nothing returns nothing
local trigger trg = CreateTrigger( )
call TriggerRegisterUnitEvent(trg, gg_unit_Hmkg_0001, EVENT_UNIT_SPELL_CHANNEL )
call TriggerAddCondition(trg, Condition(function Condition1))
call TriggerAddAction(trg, function Action1)
endfunction
Регистрируется событие на "Горного короля" когда он начинает применять способность
Так же записываются условия и действия
Далее я жму любую из его способностей
Срабатывает событие
Вызывается первая функция-условие Condition1, она возвращает true - значит всё нормально
так же у Condition2
Далее на экран выводится текст:
text1
text2
Т.е сработали функции Action1 и Action2
function Action1 takes nothing returns nothing
call BJDebugMsg("text1")
endfunction
function Action2 takes nothing returns nothing
call BJDebugMsg("text2")
endfunction
function Condition1 takes nothing returns boolean
return true
endfunction
function Condition2 takes nothing returns boolean
return true
endfunction
function InitTrig_s takes nothing returns nothing
local trigger trg = CreateTrigger( )
call TriggerRegisterUnitEvent(trg, gg_unit_Hmkg_0001, EVENT_UNIT_SPELL_CHANNEL )
call TriggerAddCondition(trg, Condition(function Condition1))
call TriggerAddCondition(trg, Condition(function Condition2))
call TriggerAddAction(trg, function Action1)
call TriggerAddAction(trg, function Action2)
endfunction
2
я жму любую из его способностей
Срабатывает событие
Вызывается первая функция-условие Condition1, она возвращает true - значит всё нормально
а вот Condition2 возвращает false - значит действия триггера не будут выполняться и на экран ничего не выведется
function Action1 takes nothing returns nothing
call BJDebugMsg("text1")
endfunction
function Action2 takes nothing returns nothing
call BJDebugMsg("text2")
endfunction
function Condition1 takes nothing returns boolean
return true
endfunction
function Condition2 takes nothing returns boolean
return false
endfunction
function InitTrig_s takes nothing returns nothing
local trigger trg = CreateTrigger( )
call TriggerRegisterUnitEvent(trg, gg_unit_Hmkg_0001, EVENT_UNIT_SPELL_CHANNEL )
call TriggerAddCondition(trg, Condition(function Condition1))
call TriggerAddCondition(trg, Condition(function Condition2))
call TriggerAddAction(trg, function Action1)
call TriggerAddAction(trg, function Action2)
endfunction
3
тоже самое как в первом примере
function Action1 takes nothing returns nothing
call BJDebugMsg("text1")
endfunction
function Condition1 takes nothing returns boolean
return true
endfunction
function InitTrig_s takes nothing returns nothing
local trigger trg = CreateTrigger( )
call TriggerRegisterUnitEvent(trg, gg_unit_Hmkg_0001, EVENT_UNIT_SPELL_CHANNEL )
call TriggerAddCondition(trg, Condition(function Condition1))
call TriggerAddAction(trg, function Action1)
endfunction
Но я вот, что хотел всегда понять ещё: несколько событий могут быть написаны на одного юнита? То есть, чтоб что-то сработало, когда юнит и атакованный, к примеру, и входящий в зону.
И ещё такое понятие: условие триггера
В пищевой цепочке оно примерно так лежит
Событие => Условие => Действие
Условие тоже является функцией (на 3 скрине самая верхняя)
Если функция-условие вернет true - значит триггер начнет вызывать функции-действия
Если вернет false - значит не будет вызывать
Ну можно ещё записать функцию в действия триггера, тогда при срабатывании события триггер вызовет эту функцию
События триггера это к примеру когда вы регистрируете событие ЮНИТ-АТАКОВАН
И при атаке вашего юнита - в триггере сработает событие и он вызовет функции из действий
DopaMine, если вам нужно вызвать функцию через время - то да, это делается через таймер
если моментально, можно даже сказать в том же потоке выполнения, то достаточно команды call
Ну можно ещё записать функцию в действия триггера, тогда при срабатывании события триггер вызовет эту функцию
DopaMine, ну так в первом триггере нужная информация записывается в хеш-таблицу по идентификатору юнита
и потом та же информация во втором триггере берется по идентификатору юнита из хеш-таблицы
GetHandleId возвращает число, грубо говоря индекс юнита (к примеру 1092431)
Нужная вам информация сохраняется в хеш-таблицу под индексом 1092431
Далее во втором триггере информация берется по индексу юнита из той же хештаблицы и если индекс юнита будет 1092431, то вы получите записанную в первом триггере информацию
Будет другой юнит - будет другой индекс
DopaMine, в jass есть такое понятие как "поток выполнения":
к примеру каждое событие триггера создает новый поток и в этом потоке хранится информация типа GetSpellAbilityUnit/GetTriggerUnit
Вызывая функцию GetSpellAbilityUnut() вы берете из потока информацию которую заложило в него событие триггера
А вот таймер создает свой поток, в котором уже нету той информации от события триггера, поэтому нужно сохранять эту информацию по идентификатору таймера
Т.е функция CheckTimer уже будет выполняться в другом потоке
Пример:
1
myFunc2 - это действия триггера
function myFunc1 takes nothing returns nothing
call BJDebugMsg(GetUnitName(GetTriggerUnit()))
//на экран будет выведено имя юнита
endfunction
function myFunc2 takes nothing returns nothing
call myFunc1
endfunction
2
myFunc2 - это действия триггера
т.е поток выполнения начинается с функции myFunc2, запускается таймер, поток выполнения заканчивается
проходит 1 секунда
таймер создает свой поток выполнения, который начинается с функции myFunc1
function myFunc1 takes nothing returns nothing
call BJDebugMsg(GetUnitName(GetTriggerUnit()))
//на экран ничего не выведется, т.к поток совсем другой и в нем нету информации от события триггера
endfunction
function myFunc2 takes nothing returns nothing
call TimerStart(CreateTimer(), 1.00, false, function myFunc1)
endfunction
DopaMine, теперь точка записывается по идентификатору юнита (чтобы можно было использовать на 3 скрине)
код
function CheckTimer takes nothing returns nothing
local timer t = GetExpiredTimer()
local integer h = GetHandleId(t)
local unit caster = LoadUnitHandle (udg_hash, h, 0) //Загружаем юнита по идентификатору таймера
//Удаляем таймер и то что было записано в хеш-таблице
call FlushChildHashtable(udg_hash, h)
call DestroyTimer(t)
//Таймер завершил отсчет и теперь его можно будет заново создавать и запускать
call SaveBoolean(udg_hash, GetHandleId(caster), StringHash("check"), false)
set caster = null
set p = null
set t = null
endfunction
function Attack takes nothing returns nothing
local unit caster = GetSpellAbilityUnit()
local timer t
local integer h = GetHandleId(caster)
local boolean check = LoadBoolean(udg_hash, h, StringHash("check")) //Для того, чтобы знать запущен ли таймер
if( not check ) then
//Таймер запущен
call SaveBoolean(udg_hash, h, StringHash("check"), true)
//Удаляем точку
call RemoveLocation(LoadLocationHandle(udg_hash, h, StringHash("point")))
//Сохраняем точку по идентификатору юнита
call SaveLocationHandle(udg_hash, h, StringHash("point"), GetSpellTargetLoc())
set t = CreateTimer() //Создаем таймер
set h = GetHandleId(t) //Берем идентификатор таймера
call SaveUnitHandle (udg_hash, h, 0, caster ) //Сохраняем юнита по идентификатору таймера
call TimerStart(t, 1.00, false, function CheckTimer)
endif
set caster = null
set t = null
endfunction
и зачем на втором скриншоте в действиях триггера записаны обе функции: Attack и CheckTimer?
function CheckTimer takes nothing returns nothing
local timer t = GetExpiredTimer()
local integer h = GetHandleId(t)
local unit caster = LoadUnitHandle (udg_hash, h, 0) //Загружаем юнита по идентификатору таймера
local location p = LoadLocationHandle(udg_hash, h, 1) //Загружаем точку по идентификатору таймера
//Удаляем таймер и то что было записано в хеш-таблице
call FlushChildHashtable(udg_hash, h)
call DestroyTimer(t)
//Таймер завершил отсчет и теперь его можно будет заново создавать и запускать
call SaveBoolean(udg_hash, GetHandleId(caster), StringHash("check"), false)
//Удаляем точку
call RemoveLocation(p)
set caster = null
set p = null
set t = null
endfunction
function Attack takes nothing returns nothing
local unit caster = GetSpellAbilityUnit()
local timer t
local integer h = GetHandleId(caster)
local boolean check = LoadBoolean(udg_hash, h, StringHash("check")) //Для того, чтобы знать запущен ли таймер
if( not check ) then
call SaveBoolean(udg_hash, h, StringHash("check"), true) //Таймер запущен
set t = CreateTimer() //Создаем таймер
set h = GetHandleId(t) //Берем идентификатор таймера
call SaveUnitHandle (udg_hash, h, 0, caster ) //Сохраняем юнита по идентификатору таймера
call SaveLocationHandle(udg_hash, h, 1, GetSpellTargetLoc()) //Сохраняем точку по идентификатору таймера
call TimerStart(t, 1.00, false, function CheckTimer)
endif
set caster = null
set t = null
endfunction
Че то случайно обнаружил косяк
В структуре файла триггеров 1.31 какое то изменение (не знаю каким образом у меня редактор 1.26 открыл карту, но ща обновлю ресурс и добавлю фишку чтобы .wtg/.wct удалялись)
» WarCraft 3 / Бета версия Warcraft III Reforged 1.32
» WarCraft 3 / Бета версия Warcraft III Reforged 1.32
» WarCraft 3 / Бета версия Warcraft III Reforged 1.32
Ред. Hodor
» WarCraft 3 / Бета версия Warcraft III Reforged 1.32
» WarCraft 3 / Бета версия Warcraft III Reforged 1.32
» WarCraft 3 / War 3 Reforged Beta
» WarCraft 3 / CreateTimer
ладно всё, я ушёл
Ред. Hodor
» WarCraft 3 / CreateTimer
а во всяких петробалансах вообще лютейшая дичь, тупо событие на вход в регион имеет около двухста триггеров
я прямо так и подчеркнул что с нуля
ладно, пойду посплю
Ред. Hodor
» WarCraft 3 / CreateTimer
и по возможности на каждый вид события один триггер
иначе при дальнейших модификациях карты будет получаться всё более жесткое месиво из кода
и в один день настанет момент когда уже нереально будет контроллировать ~10к строк перемешанного кода, всплывет вопрос об оптимизации
любой человек без склонностей к мазохизму придет к выводу что надо переписывать с нуля всё
хотяяяя, оно тоже мазохизм, но меньший)))
» WarCraft 3 / CreateTimer
» WarCraft 3 / CreateTimer
вот заново примеры:
Так же записываются условия и действия
Срабатывает событие
Вызывается первая функция-условие Condition1, она возвращает true - значит всё нормально
так же у Condition2
text1
text2
Срабатывает событие
Вызывается первая функция-условие Condition1, она возвращает true - значит всё нормально
а вот Condition2 возвращает false - значит действия триггера не будут выполняться и на экран ничего не выведется
Ред. Hodor
» WarCraft 3 / CreateTimer
Так же записываются условия и действия
Срабатывает событие
Вызывается первая функция-условие Condition1, она возвращает true - значит всё нормально
так же у Condition2
text1
text2
Срабатывает событие
Вызывается первая функция-условие Condition1, она возвращает true - значит всё нормально
а вот Condition2 возвращает false - значит действия триггера не будут выполняться и на экран ничего не выведется
» WarCraft 3 / CreateTimer
» WarCraft 3 / CreateTimer
функций условий может быть несколько
Ща примеры подгоню
» WarCraft 3 / CreateTimer
В пищевой цепочке оно примерно так лежит
Событие => Условие => Действие
Условие тоже является функцией (на 3 скрине самая верхняя)
Если функция-условие вернет true - значит триггер начнет вызывать функции-действия
Если вернет false - значит не будет вызывать
» WarCraft 3 / CreateTimer
События триггера это к примеру когда вы регистрируете событие ЮНИТ-АТАКОВАН
И при атаке вашего юнита - в триггере сработает событие и он вызовет функции из действий
Ред. Hodor
» WarCraft 3 / CreateTimer
Триггер = приводящий нечто в действие элемент
Ред. Hodor
» WarCraft 3 / CreateTimer
если моментально, можно даже сказать в том же потоке выполнения, то достаточно команды call
Ну можно ещё записать функцию в действия триггера, тогда при срабатывании события триггер вызовет эту функцию
» WarCraft 3 / CreateTimer
и потом та же информация во втором триггере берется по идентификатору юнита из хеш-таблицы
GetHandleId возвращает число, грубо говоря индекс юнита (к примеру 1092431)
Нужная вам информация сохраняется в хеш-таблицу под индексом 1092431
Далее во втором триггере информация берется по индексу юнита из той же хештаблицы и если индекс юнита будет 1092431, то вы получите записанную в первом триггере информацию
Будет другой юнит - будет другой индекс
Ред. Hodor
» WarCraft 3 / CreateTimer
к примеру каждое событие триггера создает новый поток и в этом потоке хранится информация типа GetSpellAbilityUnit/GetTriggerUnit
Вызывая функцию GetSpellAbilityUnut() вы берете из потока информацию которую заложило в него событие триггера
А вот таймер создает свой поток, в котором уже нету той информации от события триггера, поэтому нужно сохранять эту информацию по идентификатору таймера
Т.е функция CheckTimer уже будет выполняться в другом потоке
Пример:
Ред. Hodor
» WarCraft 3 / CreateTimer
и зачем на втором скриншоте в действиях триггера записаны обе функции: Attack и CheckTimer?
» WarCraft 3 / CreateTimer
» WarCraft 3 / Конвертер карты в 1.26
Ред. Hodor
» WarCraft 3 / Критует редактор при открытии старых карт
Ну или хотябы war3map.wtg/war3map.wct
» WarCraft 3 / Конвертер карты в 1.26
В структуре файла триггеров 1.31 какое то изменение (не знаю каким образом у меня редактор 1.26 открыл карту, но ща обновлю ресурс и добавлю фишку чтобы .wtg/.wct удалялись)