function Spell_Filter takes nothing returns boolean return IsPlayerEnemy(GetOwningPlayer(GetTriggerUnit()), GetOwningPlayer(GetFilterUnit())) and GetWidgetLife(GetFilterUnit()) > 0.405 and not IsUnitType(GetFilterUnit(), UNIT_TYPE_STRUCTURE) and not IsUnitType(GetFilterUnit(), UNIT_TYPE_FLYING) endfunction
function Spell_Expired takes nothing returns nothing local boolexpr b = Condition(function Spell_Filter) local group g = CreateGroup() local unit f if(LoadInteger(udg_Hash, GetHandleId(GetExpiredTimer()), 2) == 81) then call FlushChildHashtable(udg_Hash, GetHandleId(GetExpiredTimer())) call DestroyTimer(GetExpiredTimer()) else call SetUnitPosition(LoadUnitHandle(udg_Hash, GetHandleId(GetExpiredTimer()), 1), GetUnitX(LoadUnitHandle(udg_Hash, GetHandleId(GetExpiredTimer()), 1)) + 10. * Cos(GetUnitFacing(LoadUnitHandle(udg_Hash, GetHandleId(GetExpiredTimer()), 1)) * bj_DEGTORAD), GetUnitY(LoadUnitHandle(udg_Hash, GetHandleId(GetExpiredTimer()), 1)) + 10. * Sin(GetUnitFacing(LoadUnitHandle(udg_Hash, GetHandleId(GetExpiredTimer()), 1)) * bj_DEGTORAD)) call GroupEnumUnitsInRange(g, GetUnitX(LoadUnitHandle(udg_Hash, GetHandleId(GetExpiredTimer()), 1)), GetUnitY(LoadUnitHandle(udg_Hash, GetHandleId(GetExpiredTimer()), 1)), 120., b) call SaveInteger(udg_Hash, GetHandleId(GetExpiredTimer()), 2, LoadInteger(udg_Hash, GetHandleId(GetExpiredTimer()), 2) + 1) loop set f = FirstOfGroup(g) exitwhen f == null call UnitDamageTarget(LoadUnitHandle(udg_Hash, GetHandleId(GetExpiredTimer()), 1), f, 500., true, false, ATTACK_TYPE_NORMAL, DAMAGE_TYPE_MAGIC, null) call GroupRemoveUnit(g, f) endloop endif call DestroyGroup(g) call DestroyBoolExpr(b) set b = null set f = null set g = null endfunction
function Spell_Actions takes nothing returns nothing local unit u = CreateUnit(GetOwningPlayer(GetTriggerUnit()), SPELL_DUMMY, GetUnitX(GetTriggerUnit()), GetUnitY(GetTriggerUnit()), 0.) local timer t = CreateTimer() call SetUnitPathing(u, false) call SetUnitFacing(u, GetUnitFacing(GetTriggerUnit())) call TimerStart(t, .05, true, function Spell_Expired) call SaveAgentHandle(udg_Hash, GetHandleId(t), 1, u) set t = null set u = null endfunction
//=========================================================================== function InitTrig_Spell takes nothing returns nothing local unit u = CreateUnit(Player(0), SPELL_DUMMY, 0., 0., 0.) call UnitAddAbility(u, SPELL_RAWCODE) call SetUnitAbilityLevel(u, SPELL_RAWCODE, SPELL_LLEVEL) call RemoveUnit(u) set u = null set gg_trg_Spell = CreateTrigger() call TriggerRegisterAnyUnitEventBJ(gg_trg_Spell, EVENT_PLAYER_UNIT_SPELL_EFFECT) call TriggerAddCondition(gg_trg_Spell, Condition(function Spell_Conditions)) call TriggerAddAction(gg_trg_Spell, function Spell_Actions) endfunction
Собстно сам вопрос как после истечения таймера пикнуть всех вокруг юнита u, учитывая что GetTriggerUnit() в филтре уже не работает И 2 мини вопрос только у меня уникумный tesh, который не подсвечивает SaveAgentHandle?
И 2 мини вопрос только у меня уникумный tesh, который не подсвечивает SaveAgentHandle?
у меня такой функции ваще нет, так что радуйся по сабжу сохранить кастера в хеш на таймер, создать глобалку типа юнит, перед фильтром назначить ей значение необходимого юнита, выполнить фильтер, заменив triggeringunit на глобалку, и не забыть проделать тоже самое везде перед вызовом фильтра однако это плохой костыль, я делаю всё на массивах с 12 ячейками, соответствующими 12ти героям, массив героев, массив урона, массив оставшегося времени и т.д., однако с некоторыми спеллами приходится делать двумерные массивы
[SeKtOR], Перед boolexpr, записывай своего триггерюнита в глобалку, а после boolexpr очисть е на всякий случай. В фильтре ее используй. Хотя в принципе, ты и так используешь loop, почему не откажешься от фильтра вообще? запихай в свой loop, if()then
[SeKtOR], зачем ты boolexpr создаёшь, Condition(func) насколько я понял не создаёт утечек при множественном использовании, он вернёт указатель на одну и ту же функцию, поэтому просто везде пиши Condition(func)
[SeKtOR], Перед boolexpr, записывай своего триггерюнита в глобалку, а после boolexpr очисть е на всякий случай. В фильтре ее используй. Хотя в принципе, ты и так используешь loop, почему не откажешься от фильтра вообще? запихай в свой loop, if()then
Примерно понял, но лучше пример (желательно на основе моего)
Quote (Hexing)
сохранить кастера в хеш на таймер, создать глобалку типа юнит, перед фильтром назначить ей значение необходимого юнита, выполнить фильтер, заменив triggeringunit на глобалку, и не забыть проделать тоже самое везде перед вызовом фильтра однако это плохой костыль, я делаю всё на массивах с 12 ячейками, соответствующими 12ти героям, массив героев, массив урона, массив оставшегося времени и т.д., однако с некоторыми спеллами приходится делать двумерные массивы
Как вариант.
Добавлено (08 Сентября 2012, 16:08:14) --------------------------------------------- А нет понял, щас попробую
function Spell_Expired takes nothing returns nothing local group g = CreateGroup() local unit f local unit u = LoadUnitHandle(udg_Hash, GetHandleId(GetExpiredTimer()), 1) if(LoadInteger(udg_Hash, GetHandleId(GetExpiredTimer()), 2) == 81) then call FlushChildHashtable(udg_Hash, GetHandleId(GetExpiredTimer())) call DestroyTimer(GetExpiredTimer()) else call SetUnitPosition(u, GetUnitX(u) + 10. * Cos(GetUnitFacing(u) * bj_DEGTORAD), GetUnitY(u) + 10. * Sin(GetUnitFacing(u) * bj_DEGTORAD)) call GroupEnumUnitsInRange(g, GetUnitX(u), GetUnitY(u), 120., null) call SaveInteger(udg_Hash, GetHandleId(GetExpiredTimer()), 2, LoadInteger(udg_Hash, GetHandleId(GetExpiredTimer()), 2) + 1) loop set f = FirstOfGroup(g) exitwhen f == null if(IsPlayerEnemy(GetOwningPlayer(u), GetOwningPlayer(f)) and GetWidgetLife(f) > 0.405 and not IsUnitType(f, UNIT_TYPE_STRUCTURE) and not IsUnitType(f, UNIT_TYPE_FLYING)) then call UnitDamageTarget(u, f, 500., true, false, ATTACK_TYPE_NORMAL, DAMAGE_TYPE_MAGIC, null) call GroupRemoveUnit(g, f) endif endloop endif call DestroyGroup(g) set u = null set f = null set g = null endfunction
function Spell_Actions takes nothing returns nothing local unit u = CreateUnit(GetOwningPlayer(GetTriggerUnit()), SPELL_DUMMY, GetUnitX(GetTriggerUnit()), GetUnitY(GetTriggerUnit()), 0.) local timer t = CreateTimer() call SetUnitPathing(u, false) call SetUnitFacing(u, GetUnitFacing(GetTriggerUnit())) call TimerStart(t, .05, true, function Spell_Expired) call SaveAgentHandle(udg_Hash, GetHandleId(t), 1, u) set t = null set u = null endfunction
//=========================================================================== function InitTrig_Spell takes nothing returns nothing local unit u = CreateUnit(Player(0), SPELL_DUMMY, 0., 0., 0.) call UnitAddAbility(u, SPELL_RAWCODE) call RemoveUnit(u) set u = null set gg_trg_Spell = CreateTrigger() call TriggerRegisterAnyUnitEventBJ(gg_trg_Spell, EVENT_PLAYER_UNIT_SPELL_EFFECT) call TriggerAddCondition(gg_trg_Spell, Condition(function Spell_Conditions)) call TriggerAddAction(gg_trg_Spell, function Spell_Actions) endfunction
Работает! Но и тут напряг, когда оно пикает юнитов вокруг юнита u из-за условия мягко скажем "лагает", есть ли пути решения?
а ясно, странный способ создания эффекта, в любом случае опиши спелл, хочу повторить, а то понять из кода ничего не могу а это триггер инициализации, тогда ясно
Hexing, preload dummy и способности. Когда в игре впервые появляется юнит нового типа либо добавляется заклинание (триггерно), происходит лаг. Его можно убрать, создав юнита при ините.
loop set f = FirstOfGroup(g) exitwhen f == null if(IsPlayerEnemy(GetOwningPlayer(u), GetOwningPlayer(f)) and GetWidgetLife(f) > 0.405 and not IsUnitType(f, UNIT_TYPE_STRUCTURE) and not IsUnitType(f, UNIT_TYPE_FLYING)) then call UnitDamageTarget(u, f, 500., true, false, ATTACK_TYPE_NORMAL, DAMAGE_TYPE_MAGIC, null) call GroupRemoveUnit(g, f) endif endloop
При нахождении невраждебного юнита получается бесконечный цикл, который крутится достаточно долго (заставляя игру подвиснуть), а потом завершается из-за лимита операций в потоке. Если бы не это, игра бы висла намертво.
Добавлено (08 Сентября 2012, 16:29:06) --------------------------------------------- Кстати, группа должна быть только одна - глобальная. Создание и удаление каждые .05 секунд тоже оказывает вияние на быстродействие.
Ну а как иначе, если учитывать что положение юнита u меняется и нужно брать всех юнитов вокруг него в радиусе 120. и дамажить, пока таймер не закончится нужное кол-во раз?
Основные лаги из-за первой ошибки - GroupRemoveUnit нужно вынести из блока if. Дополнительную оптимизацию можно провести, рассчитав 10. * Cos(a) и 10. * Sin(a) в момент запуска и сохранив их в хэш.