Добавлен Rare
Мне нужно было выбрать группу юнитов в радиусе 600 вокруг кастующего героя, которая соответствует условиям
- Наземный
- Противник игрока, чей юнит кастует
- Не союзник игрока, чей юнит кастует
- Не владелец кастующего юнита
- Не имеет невосприимчивости к магии
- Не здание
Странность первая:
Если я оставлю только условие "противник", не прописывая "не союзник" и "не владелец", игра добавит в группе вообще всех вокруг, и своих, и чужих. Почему условия "юнит является противником" игре недостаточно, чтобы добавить в отряд только противников? Зачем она от меня требует прописывать дополнительные бесполезные условия?
Если я оставлю только условие "противник", не прописывая "не союзник" и "не владелец", игра добавит в группе вообще всех вокруг, и своих, и чужих. Почему условия "юнит является противником" игре недостаточно, чтобы добавить в отряд только противников? Зачем она от меня требует прописывать дополнительные бесполезные условия?
Странность вторая (её было б удобнее скринами показать, но почему-то сайт не даёт их вставить сюда):
Добавление в группу делается двумя способами.
Почему 1й вариант игра игнорирует?
Добавление в группу делается двумя способами.
- Можно или взять действие "выбрать всех юнитов вокруг кастующего героя, соответствующих условию" и прописать все условия там
- Можно взять действие "выбрать всех юнитов вокруг кастующего героя", а уже после через if/then/else прописать в if все условия
Почему 1й вариант игра игнорирует?
Принятый ответ
Все оказалось куда проще, чем я думала. (PS: rsfghd уже это же и написал, но ты его не понял)
В первом варианте у тебя "Units in range matching condition", к ней подсказка
Use 'Matching Unit' to refer to the unit on whom the comparison is being performed.
А ты использовал (Picked unit)! Почему так нельзя? Потому что, matching condition = значит там Filter внутри, а внутри фильтра используется функция GetFilterUnit т.е. (matching unit).
из triggerstrings.txt:GetEnumUnitHint="When using the 'Pick Every Unit...' action, this refers to each unit as it is picked."GetFilterUnitHint="Use this to refer to the unit being considered for 'Units Matching Condition' functions."
А вот (Picked unit) можно использовать, когда просто есть проход по группе, как в твоем втором варианте.
Я тут вытащила код триггера из карты из war3map.j
Сгенерированный код триггера
===========================================================================
Trigger: IshillUltimte
===========================================================================
function Trig_IshillUltimte_Conditions takes nothing returns boolean
if ( not ( GetSpellAbilityId() == 'A001' ) ) then
return false
endif
return true
endfunction
Trigger: IshillUltimte
===========================================================================
function Trig_IshillUltimte_Conditions takes nothing returns boolean
if ( not ( GetSpellAbilityId() == 'A001' ) ) then
return false
endif
return true
endfunction
function Trig_IshillUltimte_Func002Func001Func002C takes nothing returns boolean
if ( not ( IsUnitType(GetEnumUnit(), UNIT_TYPE_STRUCTURE) == false ) ) then
return false
endif
if ( not ( IsUnitType(GetEnumUnit(), UNIT_TYPE_GROUND) == true ) ) then
return false
endif
if ( not ( IsUnitType(GetEnumUnit(), UNIT_TYPE_MAGIC_IMMUNE) == false ) ) then
return false
endif
if ( not ( IsUnitAlly(GetEnumUnit(), GetOwningPlayer(GetSpellAbilityUnit())) == false ) ) then
return false
endif
if ( not ( IsUnitEnemy(GetEnumUnit(), GetOwningPlayer(GetSpellAbilityUnit())) == true ) ) then
return false
endif
if ( not ( GetOwningPlayer(GetEnumUnit()) != GetOwningPlayer(GetSpellAbilityUnit()) ) ) then
return false
endif
return true
endfunction
if ( not ( IsUnitType(GetEnumUnit(), UNIT_TYPE_STRUCTURE) == false ) ) then
return false
endif
if ( not ( IsUnitType(GetEnumUnit(), UNIT_TYPE_GROUND) == true ) ) then
return false
endif
if ( not ( IsUnitType(GetEnumUnit(), UNIT_TYPE_MAGIC_IMMUNE) == false ) ) then
return false
endif
if ( not ( IsUnitAlly(GetEnumUnit(), GetOwningPlayer(GetSpellAbilityUnit())) == false ) ) then
return false
endif
if ( not ( IsUnitEnemy(GetEnumUnit(), GetOwningPlayer(GetSpellAbilityUnit())) == true ) ) then
return false
endif
if ( not ( GetOwningPlayer(GetEnumUnit()) != GetOwningPlayer(GetSpellAbilityUnit()) ) ) then
return false
endif
return true
endfunction
function Trig_IshillUltimte_Func002Func001C takes nothing returns boolean
if ( not Trig_IshillUltimte_Func002Func001Func002C() ) then
return false
endif
return true
endfunction
if ( not Trig_IshillUltimte_Func002Func001Func002C() ) then
return false
endif
return true
endfunction
function Trig_IshillUltimte_Func002A takes nothing returns nothing
if ( Trig_IshillUltimte_Func002Func001C() ) then
call GroupAddUnitSimple( GetEnumUnit(), udg_UltimateIshillEffect )
else
endif
endfunction
if ( Trig_IshillUltimte_Func002Func001C() ) then
call GroupAddUnitSimple( GetEnumUnit(), udg_UltimateIshillEffect )
else
endif
endfunction
function Trig_IshillUltimte_Func003A takes nothing returns nothing
call EnableTrigger( gg_trg_IshillPoison )
call UnitAddAbilityBJ( 'A000', GetEnumUnit() )
endfunction
call EnableTrigger( gg_trg_IshillPoison )
call UnitAddAbilityBJ( 'A000', GetEnumUnit() )
endfunction
function Trig_IshillUltimte_Func005A takes nothing returns nothing
call DisableTrigger( gg_trg_IshillPoison )
call UnitRemoveAbilityBJ( 'A000', GetEnumUnit() )
endfunction
call DisableTrigger( gg_trg_IshillPoison )
call UnitRemoveAbilityBJ( 'A000', GetEnumUnit() )
endfunction
function Trig_IshillUltimte_Actions takes nothing returns nothing
call QuestMessageBJ( GetPlayersAll(), bj_QUESTMESSAGE_UPDATED, "TRIGSTR_019" )
call ForGroupBJ( GetUnitsInRangeOfLocAll(600.00, GetUnitLoc(GetSpellAbilityUnit())), function Trig_IshillUltimte_Func002A )
call ForGroupBJ( udg_UltimateIshillEffect, function Trig_IshillUltimte_Func003A )
call TriggerSleepAction( 20.00 )
call ForGroupBJ( udg_UltimateIshillEffect, function Trig_IshillUltimte_Func005A )
call GroupClear( udg_UltimateIshillEffect )
endfunction
call QuestMessageBJ( GetPlayersAll(), bj_QUESTMESSAGE_UPDATED, "TRIGSTR_019" )
call ForGroupBJ( GetUnitsInRangeOfLocAll(600.00, GetUnitLoc(GetSpellAbilityUnit())), function Trig_IshillUltimte_Func002A )
call ForGroupBJ( udg_UltimateIshillEffect, function Trig_IshillUltimte_Func003A )
call TriggerSleepAction( 20.00 )
call ForGroupBJ( udg_UltimateIshillEffect, function Trig_IshillUltimte_Func005A )
call GroupClear( udg_UltimateIshillEffect )
endfunction
===========================================================================
function InitTrig_IshillUltimte takes nothing returns nothing
set gg_trg_IshillUltimte = CreateTrigger( )
call TriggerRegisterAnyUnitEventBJ( gg_trg_IshillUltimte, EVENT_PLAYER_UNIT_SPELL_CAST )
call TriggerAddCondition( gg_trg_IshillUltimte, Condition( function Trig_IshillUltimte_Conditions ) )
call TriggerAddAction( gg_trg_IshillUltimte, function Trig_IshillUltimte_Actions )
endfunction
function InitTrig_IshillUltimte takes nothing returns nothing
set gg_trg_IshillUltimte = CreateTrigger( )
call TriggerRegisterAnyUnitEventBJ( gg_trg_IshillUltimte, EVENT_PLAYER_UNIT_SPELL_CAST )
call TriggerAddCondition( gg_trg_IshillUltimte, Condition( function Trig_IshillUltimte_Conditions ) )
call TriggerAddAction( gg_trg_IshillUltimte, function Trig_IshillUltimte_Actions )
endfunction
Маленькие оптимизации:
- IsUnitAlly+GetOwningPlayer(GetSpellAbilityUnit()) и IsUnitEnemy по идее взаимоисключающие, хватило бы только IsUnitEnemy(...)
call ForGroupBJ( GetUnitsInRangeOfLocAll(600.00, GetUnitLoc(GetSpellAbilityUnit())), function Trig_IshillUltimte_Func002A )
- Тут утечка локации, потому что GetUnitLoc создает новую, но она потом не удаляется. Решение в ГУИ: записать GetUnitLoc в глобальную (или локальную) переменную, пройтись по группе, и удалить локацию (DestroyLocation).
Проблема: у тебя, как называется в местном жаргоне, триггер не MUI. То есть он работает только с одним юнитом одновременно, если два юнита используют заклинание, то оно сломается.
Посмотри на Trig_IshillUltimte_Actions. Ты там используешь udg_UltimateIshillEffect до засыпания на 20с и после. Что будет если в этот промежуток времени кто-нибудь снова вызовет триггер? Ацская сотона. Я не знаю как принято, но по-моему единственный выход - это локально создать группу, чтобы она у кастующего юнита была своя, а в конце триггера её удалять.
Посмотри на Trig_IshillUltimte_Actions. Ты там используешь udg_UltimateIshillEffect до засыпания на 20с и после. Что будет если в этот промежуток времени кто-нибудь снова вызовет триггер? Ацская сотона. Я не знаю как принято, но по-моему единственный выход - это локально создать группу, чтобы она у кастующего юнита была своя, а в конце триггера её удалять.
Прочитай пару туториалов про локальные переменные и утечки. Если не прозреешь - перепишу всё на кастомный код за тебя, чтобы как пример был наглядный.
`
ОЖИДАНИЕ РЕКЛАМЫ...
Чтобы оставить комментарий, пожалуйста, войдите на сайт.
На втором скрине должно нормально работать, и можно спокойно убрать проверку на союзника и на юнита который кастует, оставив только проверку на здание, наземность и противника
Отредактирован Lasto4ka
Trigger: IshillUltimte
===========================================================================
function Trig_IshillUltimte_Conditions takes nothing returns boolean
if ( not ( GetSpellAbilityId() == 'A001' ) ) then
return false
endif
return true
endfunction
if ( not ( IsUnitType(GetEnumUnit(), UNIT_TYPE_STRUCTURE) == false ) ) then
return false
endif
if ( not ( IsUnitType(GetEnumUnit(), UNIT_TYPE_GROUND) == true ) ) then
return false
endif
if ( not ( IsUnitType(GetEnumUnit(), UNIT_TYPE_MAGIC_IMMUNE) == false ) ) then
return false
endif
if ( not ( IsUnitAlly(GetEnumUnit(), GetOwningPlayer(GetSpellAbilityUnit())) == false ) ) then
return false
endif
if ( not ( IsUnitEnemy(GetEnumUnit(), GetOwningPlayer(GetSpellAbilityUnit())) == true ) ) then
return false
endif
if ( not ( GetOwningPlayer(GetEnumUnit()) != GetOwningPlayer(GetSpellAbilityUnit()) ) ) then
return false
endif
return true
endfunction
if ( not Trig_IshillUltimte_Func002Func001Func002C() ) then
return false
endif
return true
endfunction
if ( Trig_IshillUltimte_Func002Func001C() ) then
call GroupAddUnitSimple( GetEnumUnit(), udg_UltimateIshillEffect )
else
endif
endfunction
call EnableTrigger( gg_trg_IshillPoison )
call UnitAddAbilityBJ( 'A000', GetEnumUnit() )
endfunction
call DisableTrigger( gg_trg_IshillPoison )
call UnitRemoveAbilityBJ( 'A000', GetEnumUnit() )
endfunction
call QuestMessageBJ( GetPlayersAll(), bj_QUESTMESSAGE_UPDATED, "TRIGSTR_019" )
call ForGroupBJ( GetUnitsInRangeOfLocAll(600.00, GetUnitLoc(GetSpellAbilityUnit())), function Trig_IshillUltimte_Func002A )
call ForGroupBJ( udg_UltimateIshillEffect, function Trig_IshillUltimte_Func003A )
call TriggerSleepAction( 20.00 )
call ForGroupBJ( udg_UltimateIshillEffect, function Trig_IshillUltimte_Func005A )
call GroupClear( udg_UltimateIshillEffect )
endfunction
function InitTrig_IshillUltimte takes nothing returns nothing
set gg_trg_IshillUltimte = CreateTrigger( )
call TriggerRegisterAnyUnitEventBJ( gg_trg_IshillUltimte, EVENT_PLAYER_UNIT_SPELL_CAST )
call TriggerAddCondition( gg_trg_IshillUltimte, Condition( function Trig_IshillUltimte_Conditions ) )
call TriggerAddAction( gg_trg_IshillUltimte, function Trig_IshillUltimte_Actions )
endfunction
Посмотри на Trig_IshillUltimte_Actions. Ты там используешь udg_UltimateIshillEffect до засыпания на 20с и после. Что будет если в этот промежуток времени кто-нибудь снова вызовет триггер? Ацская сотона. Я не знаю как принято, но по-моему единственный выход - это локально создать группу, чтобы она у кастующего юнита была своя, а в конце триггера её удалять.
Lasto4ka: