offline
Опыт:
2,508
Активность:
|
Система приоритетов
Собственно, запилил вот такое вот добро. Находит наиболее подходящую цель для данной башни. Часть приоритетов привязана к моей карте, часть универсальна. Больше подробностей в комментариях к коду.
Хотелось бы узнать, где я оплошал, где код лишний и где есть гораздо более простой способ это сделать. В любом случае не хочется применять на практике нечто сырое и несуразное, даже если в своей собственной карте.
» раскрыть
Код:
function Checker_Filter takes nothing returns boolean
return ( GetOwningPlayer( GetFilterUnit() ) == Player(4) ) && ( GetUnitState( GetFilterUnit(), UNIT_STATE_LIFE ) > 0 ) && ( GetUnitTypeId( GetFilterUnit() ) != 'h004' )
endfunction
function Checker_Red takes nothing returns boolean
return ( GetUnitY( GetFilterUnit() ) < BORDER_TOP ) && Checker_Filter()
endfunction
function Checker_Blue takes nothing returns boolean
return ( GetUnitX( GetFilterUnit() ) < BORDER_RIGHT ) && Checker_Filter()
endfunction
function Checker_Teal takes nothing returns boolean
return ( GetUnitY( GetFilterUnit() ) > BORDER_BOTTOM ) && Checker_Filter()
endfunction
function Checker_Purple takes nothing returns boolean
return ( GetUnitX( GetFilterUnit() ) > BORDER_LEFT ) && Checker_Filter()
endfunction
//---------------------------------------------------------------------------------------------------------------------------------------------
//Вначале идут функции для выбора юнита из группы различными способами.
//Затем функция Intersection, используемая для того, чтобы найти пересечение групп допустимых и потенциальных целей.
//Последняя функция, самая большая, служит для выбора конкретного способа нахождения цели и, собственно, находит её.
//Именно последнюю функцию надо использовать для нахождения приоритета.
//Ближайший юнит
function DCheck takes unit tower, group g returns unit
local unit u
local unit cur = FirstOfGroup( g )
local group temp = CreateGroup()
call GroupAddGroup( g, temp )
loop
exitwhen CountUnitsInGroup( temp ) == 0
set u = FirstOfGroup( temp )
if ( SquareRoot( ( GetUnitX( u ) - GetUnitX( tower ) )*( GetUnitX( u ) - GetUnitX( tower ) ) + ( GetUnitY( u ) - GetUnitY( tower ) )*( GetUnitY( u ) - GetUnitY( tower ) ) ) < SquareRoot( ( GetUnitX( cur ) - GetUnitX( tower ) )*( GetUnitX( cur ) - GetUnitX( tower ) ) + ( GetUnitY( cur ) - GetUnitY( tower ) )*( GetUnitY( cur ) - GetUnitY( tower ) ) ) ) then
set cur = u
endif
call GroupRemoveUnit( temp, u )
endloop
call DestroyGroup( temp )
set temp = null
set u = null
return cur
endfunction
//Самый левый
function XCheck_Left takes group g returns unit
local unit u
local unit cur = FirstOfGroup( g )
local group temp = CreateGroup()
call GroupAddGroup( g, temp )
loop
exitwhen CountUnitsInGroup( temp ) == 0
set u = FirstOfGroup( temp )
if ( GetUnitX( u ) < GetUnitX( cur ) ) then
set cur = u
endif
call GroupRemoveUnit( temp, u )
endloop
call DestroyGroup( temp )
set temp = null
set u = null
return cur
endfunction
//Самый правый
function XCheck_Right takes group g returns unit
local unit u
local unit cur = FirstOfGroup( g )
local group temp = CreateGroup()
call GroupAddGroup( g, temp )
loop
exitwhen CountUnitsInGroup( temp ) == 0
set u = FirstOfGroup( temp )
if ( GetUnitX( u ) > GetUnitX( cur ) ) then
set cur = u
endif
call GroupRemoveUnit( temp, u )
endloop
call DestroyGroup( temp )
set temp = null
set u = null
return cur
endfunction
//Самый нижний
function YCheck_Down takes group g returns unit
local unit u
local unit cur = FirstOfGroup( g )
local group temp = CreateGroup()
call GroupAddGroup( g, temp )
loop
exitwhen CountUnitsInGroup( temp ) == 0
set u = FirstOfGroup( temp )
if ( GetUnitY( u ) < GetUnitY( cur ) ) then
set cur = u
endif
call GroupRemoveUnit( temp, u )
endloop
call DestroyGroup( temp )
set temp = null
set u = null
return cur
endfunction
//Самый верхний
function YCheck_Up takes group g returns unit
local unit u
local unit cur = FirstOfGroup( g )
local group temp = CreateGroup()
call GroupAddGroup( g, temp )
loop
exitwhen CountUnitsInGroup( temp ) == 0
set u = FirstOfGroup( temp )
if ( GetUnitY( u ) > GetUnitY( cur ) ) then
set cur = u
endif
call GroupRemoveUnit( temp, u )
endloop
call DestroyGroup( temp )
set temp = null
set u = null
return cur
endfunction
//С наименьших количеством хп
function HCheck_Up takes group g returns unit
local unit u
local unit cur = FirstOfGroup( g )
local group temp = CreateGroup()
call GroupAddGroup( g, temp )
loop
exitwhen CountUnitsInGroup( temp ) == 0
set u = FirstOfGroup( temp )
if ( GetUnitState( u, UNIT_STATE_LIFE ) > GetUnitState( cur, UNIT_STATE_LIFE ) ) then
set cur = u
endif
call GroupRemoveUnit( temp, u )
endloop
call DestroyGroup( temp )
set temp = null
set u = null
return cur
endfunction
//С наибольшим количеством хп
function HCheck_Down takes group g returns unit
local unit u
local unit cur = FirstOfGroup( g )
local group temp = CreateGroup()
call GroupAddGroup( g, temp )
loop
exitwhen CountUnitsInGroup( temp ) == 0
set u = FirstOfGroup( temp )
if ( GetUnitState( u, UNIT_STATE_LIFE ) < GetUnitState( cur, UNIT_STATE_LIFE ) ) then
set cur = u
endif
call GroupRemoveUnit( temp, u )
endloop
call DestroyGroup( temp )
set temp = null
set u = null
return cur
endfunction
function Intersection takes group g1, group g2 returns group
local group temp = CreateGroup()
local group g = CreateGroup()
local unit u
call GroupAddGroup( g1, temp )
loop
exitwhen CountUnitsInGroup( temp ) == 0
set u = FirstOfGroup( temp )
if IsUnitInGroup( u, g2 ) then
call GroupAddUnit( g, u )
endif
call GroupRemoveUnit( temp, u )
endloop
call DestroyGroup( temp )
set u = null
set temp = null
return g
endfunction
//Приоритеты 2 и 3 ищут соответственно первого и последнего юнита в волне.
//Приоритет 4 ищет последнего, только если текущая цель недоступна или умерла.
//Эти приоритеты работают только в циклических ТД вроде CreenCircle, и для них в функциях Checker_Red и т.п. нужно установить константы
//BORDER_TOP, BORDER_RIGHT и т.д. координат внутренних сторон круга. Эти приоритеты будут работать правильно при движении
//противников против часовой стрелки, но наоборот при движении по часовой. Впрочем, чтобы это исправить, достаточно поменять местами
//два участка кода: где выбирается приоритет 2 и где выбираются приоритеты 3 и 4.
//Остальные приоритеты работают в любой карте, даже для движущихся целей.
function Target_Picking takes unit u, unit curTarget, integer state, group targets returns unit
local integer i = 0
local group g = CreateGroup()
local unit target = null
if ( CountUnitsInGroup( targets ) == 0 ) then
return null
endif
//Вычисляем атакующего
if ( state == 2 )
//Выбираем игрока
if ( GetOwningPlayer( u ) == Player(0) )
//Берём всех юнитов после поворота
call GroupEnumUnitsInRange( g, GetUnitX( u ), GetUnitY( u ), GetUnitAcquireRange( u ), Condition( function Checker_Red ) )
set g = Intersection( g, targets )
if ( CountUnitsInGroup( g ) != 0 ) then
//Ищем первого
set target = YCheck_Down( g )
else
//Выбираем остальных и ищем первого
call GroupEnumUnitsInRange( g, GetUnitX( u ), GetUnitY( u ), GetUnitAcquireRange( u ), Condition( function Checker_Filter ) )
set g = Intersection( g, targets )
set target = XCheck_Left( g )
endif
endif
if ( GetOwningPlayer( u ) == Player(1) )
call GroupEnumUnitsInRange( g, GetUnitX( u ), GetUnitY( u ), GetUnitAcquireRange( u ), Condition( function Checker_Blue ) )
set g = Intersection( g, targets )
if ( CountUnitsInGroup( g ) != 0 ) then
set target = XCheck_Left( g )
else
call GroupEnumUnitsInRange( g, GetUnitX( u ), GetUnitY( u ), GetUnitAcquireRange( u ), Condition( function Checker_Filter ) )
set g = Intersection( g, targets )
set target = YCheck_Up( g )
endif
endif
if ( GetOwningPlayer( u ) == Player(2) )
call GroupEnumUnitsInRange( g, GetUnitX( u ), GetUnitY( u ), GetUnitAcquireRange( u ), Condition( function Checker_Teal ) )
set g = Intersection( g, targets )
if ( CountUnitsInGroup( g ) != 0 ) then
set target = YCheck_Up( g )
else
call GroupEnumUnitsInRange( g, GetUnitX( u ), GetUnitY( u ), GetUnitAcquireRange( u ), Condition( function Checker_Filter ) )
set g = Intersection( g, targets )
set target = XCheck_Right( g )
endif
endif
if ( GetOwningPlayer( u ) == Player(3) )
call GroupEnumUnitsInRange( g, GetUnitX( u ), GetUnitY( u ), GetUnitAcquireRange( u ), Condition( function Checker_Purple ) )
set g = Intersection( g, targets )
if ( CountUnitsInGroup( g ) != 0 ) then
set target = XCheck_Right( g )
else
call GroupEnumUnitsInRange( g, GetUnitX( u ), GetUnitY( u ), GetUnitAcquireRange( u ), Condition( function Checker_Filter ) )
set g = Intersection( g, targets )
set target = YCheck_Down( g )
endif
endif
endif
if ( ( state == 3 ) or ( ( state == 4 ) && not ( IsUnitInRange( u, curTarget, GetUnitAcquireRange( u ) ) && GetUnitState( curTarget, UNIT_STATE_LIFE ) > 0 ) ) )
//Выбираем игрока
if ( GetOwningPlayer( u ) == Player(0) )
//Берём всех юнитов до поворота
call GroupEnumUnitsInRange( g, GetUnitX( u ), GetUnitY( u ), GetUnitAcquireRange( u ), Condition( function Checker_Purple ) )
set g = Intersection( g, targets )
if ( CountUnitsInGroup( g ) != 0 ) then
//Ищем последнего
set target = XCheck_Right( g )
else
//Выбираем остальных и ищем последнего
call GroupEnumUnitsInRange( g, GetUnitX( u ), GetUnitY( u ), GetUnitAcquireRange( u ), Condition( function Checker_Filter ) )
set g = Intersection( g, targets )
set target = YCheck_Up( g )
endif
endif
if ( GetOwningPlayer( u ) == Player(1) )
call GroupEnumUnitsInRange( g, GetUnitX( u ), GetUnitY( u ), GetUnitAcquireRange( u ), Condition( function Checker_Red ) )
set g = Intersection( g, targets )
if ( CountUnitsInGroup( g ) != 0 ) then
set target = YCheck_Down( g )
else
call GroupEnumUnitsInRange( g, GetUnitX( u ), GetUnitY( u ), GetUnitAcquireRange( u ), Condition( function Checker_Filter ) )
set g = Intersection( g, targets )
set target = XCheck_Right( g )
endif
endif
if ( GetOwningPlayer( u ) == Player(2) )
call GroupEnumUnitsInRange( g, GetUnitX( u ), GetUnitY( u ), GetUnitAcquireRange( u ), Condition( function Checker_Blue ) )
set g = Intersection( g, targets )
if ( CountUnitsInGroup( g ) != 0 ) then
set target = XCheck_Left( g )
else
call GroupEnumUnitsInRange( g, GetUnitX( u ), GetUnitY( u ), GetUnitAcquireRange( u ), Condition( function Checker_Filter ) )
set g = Intersection( g, targets )
set target = YCheck_Down( g )
endif
endif
if ( GetOwningPlayer( u ) == Player(3) )
call GroupEnumUnitsInRange( g, GetUnitX( u ), GetUnitY( u ), GetUnitAcquireRange( u ), Condition( function Checker_Teal ) )
set g = Intersection( g, targets )
if ( CountUnitsInGroup( g ) != 0 ) then
set target = YCheck_Up( g )
else
call GroupEnumUnitsInRange( g, GetUnitX( u ), GetUnitY( u ), GetUnitAcquireRange( u ), Condition( function Checker_Filter ) )
set g = Intersection( g, targets )
set target = XCheck_Left( g )
endif
endif
endif
if ( state == 5 )
//Ищем ближайшего юнита
call GroupEnumUnitsInRange( g, GetUnitX( u ), GetUnitY( u ), GetUnitAcquireRange( u ), Condition( function Checker_Filter ) )
set g = Intersection( g, targets )
set target = DCheck( u, g )
endif
if ( state == 6 )
//Ищем юнита с наибольшим количеством здоровья
call GroupEnumUnitsInRange( g, GetUnitX( u ), GetUnitY( u ), GetUnitAcquireRange( u ), Condition( function Checker_Filter ) )
set g = Intersection( g, targets )
set target = HCheck_Up( g )
endif
if ( state == 7 )
//Ищем юнита с наименьшим количеством здоровья
call GroupEnumUnitsInRange( g, GetUnitX( u ), GetUnitY( u ), GetUnitAcquireRange( u ), Condition( function Checker_Filter ) )
set g = Intersection( g, targets )
set target = HCheck_Down( g )
endif
call DestroyGroup( g )
set g = null
return target
endfunction
UPD: ещё момент. В карте каждый игрок имеет право строить юнитов только в своём углу. Это позволяет просчитывать некоторые приоритеты, т.к. мы точно знаем, что башня этого игрока будет находиться в конкретном углу. В противном случае пришлось бы считать самому, в каком углу находится башня.
Отредактировано Variecs, 02.07.2013 в 18:15.
|