Добавлен , опубликован

Основы Интерфейса

Содержание:
Кастомная меню строительство полностью на фреймах, images, и спецэффекте. Способную полностью заменить стандартную. Стандартную менять нет смысла, только если вы делаете н2еобычные карты путей:
  • локально нельзя отобразить карту путей. у всех она будет общей, если брать из редактора. Вы не сможете отобразить некоторые элементы свечения итд, это уже все в движке.
  • была необходимость реализовать отдельную карту путей с добавлением новых параметров. Этого тоже нельзя увеличить. Доступны вроде 3 параметра: ходить/строить/летать. Если я хочу, допустим под растения, земля с участками запоминалась. Это не сложно делать. Но визуально, это никак не отобразить. Шуры-муры пришлось делать. В результате, я не смог локально делать.
Решил сделать примерчик для статьи. Давно хотел. Было много сложностей. Сначало, я хотел полностью заменить весь интерефейс для примера. Но передумал. Проще показать меню.
пример отклонения координат
сравнивал стандартный и кастомный. И не знаю почему, но стандартный смещается. То ли станд кривой, или координаты неправильно определяются.
там происходит из-за отрицательных координат. пришлось делать правку
вот есть 4x4 клетки. image. создаются специально по координатам мыши. никак не мог избавиться от швов. Но это не так страшно. пример даже на картинке было видно что палец курсора не в центре квадрата
когда подводишь к запрещаемой области, оно закрашивается красным. Мне хотелось попробовать что-то новое. Индивидуально нельзя каждому игроку задать в ро где ему строить. Эти текстуры они общие. К примеру красный может строить, а вот синий нет.
Все выглядело неплохо, у здании можно отключить, или спрятать текстуры. Решил проверить совпадают ли квадратики. Выбрал здание в меню и начал водить мышью. Выглядит ужасно, погрешности. Координаты мыши дают неверные координаты
Я думал что погрешность это у варика. Помните как в старом добром варике, оно не всегда точно. Там какая-то погрешность была. ее можно правками было исправить. Ну нашел я эти погрешности x-16, y-16 так я думал. Пока не попробовал с квадратиком другого размера
вот 6x6
водил мышью. и начал замечать такое
смотри если координаты положительные (>= 0), то все норм. Если координаты отрицательные, то почему то мой квадрат отъезжает в противоположную сторону.
Если карту поделить на 4 зоны как в тригонометрии на четверти делится круг. То можно заметить отклонения. Указательный палец лежит не там. Короче че то с нативки по определению координат дают не точные данные.
первый часть (-x, y) - отклонение влево, вторая (x,y) - норм лежит ровно, третья - (-x, -y) - отклонение влево нижний угол, четвертая - (x,-y) - отклонения вниз.
функции image
--@string file
--@real sizeX
--@real sizeY
--@real x
--@real y
--@integer imagetype
function CreateRectangularImage(file,sizeX,sizeY,x,y,imagetype)
    bj_lastCreatedImage = CreateImage(file, sizeX, sizeY, 0., x, y, 0., sizeX / 2., sizeY / 2., 0., imagetype)
    SetImageRenderAlways(bj_lastCreatedImage, true)
    return bj_lastCreatedImage
end

--@string file
--@real size
--@real x
--@real y
--@integer imagetype
function CreateSquareImage(file,size,x,y,imagetype)
    bj_lastCreatedImage = CreateImage(file, size, size, size, x, y, 0., size / 2., size / 2., 0., imagetype)
    SetImageRenderAlways(bj_lastCreatedImage, true)
    return bj_lastCreatedImage
end

--@player p
--@string file
--@real size
--@real x
--@real y
--@integer imagetype
function CreateSquareImageForPlayer(p,file,size,x,y,imagetype)
    bj_lastCreatedImage = CreateImage(file, size, size, 0., x, y, 0., size / 2., size / 2., 0., imagetype)
    SetImageRenderAlways(bj_lastCreatedImage, GetLocalPlayer() == p)
    return bj_lastCreatedImage
end

--@player p
--@string file
--@real sizeX
--@real sizeY
--@real x
--@real y
--@integer imagetype
function CreateRectangularImageForPlayer(p,file,sizeX,sizeY,x,y,imagetype)
    bj_lastCreatedImage = CreateImage(file, sizeX, sizeY, 0., x, y, 0., sizeX / 2., sizeY / 2., 0., imagetype)
    SetImageRenderAlways(bj_lastCreatedImage, GetLocalPlayer() == p)
    return bj_lastCreatedImage
end
функции выбора


do
    -- returns the local current main selected unit, using it in a sync gamestate relevant manner breaks the game.
    function GetMainSelectedUnitEx()
        return GetMainSelectedUnit(GetSelectedUnitIndex())
    end
   

    local containerFrame
    local frames = {}
    local group
    local units = {}
    local filter = Filter(function()
        local unit = GetFilterUnit()
        local prio = BlzGetUnitRealField(unit, UNIT_RF_PRIORITY)
        local found = false
        -- compare the current unit with allready found, to place it in the right slot
        for index, value in ipairs(units) do
            -- higher prio than this take it's slot
            if BlzGetUnitRealField(value, UNIT_RF_PRIORITY) < prio then
                table.insert(units, index, unit)
                found = true
                break
            -- equal prio and better colisions Value
            elseif BlzGetUnitRealField(value, UNIT_RF_PRIORITY) == prio and GetUnitOrderValue(value) > GetUnitOrderValue(unit) then
                table.insert( units, index, unit)
                found = true
                break
            end
        end
        -- not found add it at the end
        if not found then
            table.insert(units, unit)
        end

        unit = nil
        return false
    end)

    --номер индекса
    function GetSelectedUnitIndex()
        -- local player is in group selection?
        if BlzFrameIsVisible(containerFrame) then
            -- find the first visible yellow Background Frame
            for int = 0, #frames do
                if BlzFrameIsVisible(frames[int]) then
                    return int
                end           
            end
        end

        return nil
    end

    function GetUnitOrderValue(unit)
        --heroes use the handleId
        if IsUnitType(unit, UNIT_TYPE_HERO) then
            return GetHandleId(unit)
        else
        --units use unitCode
        return GetUnitTypeId(unit)
        end
    end

    --выбирает юнита из группы по идексу
    function GetMainSelectedUnit(index)
        if index then
            GroupEnumUnitsSelected(group, GetLocalPlayer(), filter)
            local unit = units[index + 1]
            --clear table
            repeat until not table.remove(units)
            return unit
        else
            GroupEnumUnitsSelected(group, GetLocalPlayer(), nil)
            return FirstOfGroup(group)
        end
    end

    --init
    do
        local real = MarkGameStarted
      function MarkGameStarted()
            real()

        --globals
        ConsoleUI = BlzGetFrameByName("ConsoleUI",0)
        BottomCenterUI = BlzFrameGetChild(ConsoleUI,1)
        groupframe = BlzFrameGetChild(BottomCenterUI, 5)
        
        group = CreateGroup()
        --инициируем фреймы
        function InitFrames_v2()
            containerFrame = BlzFrameGetChild(groupframe, 0)
            -- give this frames a handleId
            for int = 0, BlzFrameGetChildrenCount(containerFrame) - 1 do
                local buttonContainer = BlzFrameGetChild(containerFrame, int)
                frames[int] = BlzFrameGetChild(buttonContainer, 0)
            end
        end
        InitFrames_v2()
      end
    end
end
карта типы паффинга
В варкрафте существует такая механика как определения строительства зданий. Она определяется, где можно или где нельзя.
Существуют 2 строчки, в которых можно указать типы. Первая отвечает, где запрещено строить (пример, у нежити зданиям запрещено строить "не на порче"). Вторая, где рекомендовано.
Третья строчка, это определяет радиус воды поблизости. Без нее не ставятся верфи.
существует 6 типов паффинга. взято из редактора объектов. мало ли картодел захочет сохранить механику, и визуализировать это тоже надо будет. Для общего понимания разберемся. По факту, там 6 галочек, и картодел может несколько галочек включать. У картодела множества вариации по принципу "and". 2^6=64 вариации, но некоторые варианты можно исключить. Мы же не будем рассматривать все 64 случая, верно? и логически они повторяются, и можно исключить. Я добавлю таблицу, где рассматрел несколько случаев, дабы упростить работу.
Внимание: Все типы пронумерованы, они определяют разрядность в двоичном коде.
типразрядпаффинг
ground-pathable ground = 1 PATHING_TYPE_WALKABILITY
air-pathable air = 2 PATHING_TYPE_FLYABILITY
buildable buildable = 3 PATHING_TYPE_BUILDABILITY
unblighted unblighted = 4 PATHING_TYPE_BLIGHTPATHING
sea-pathable sea = 5 PATHING_TYPE_FLOATABILITY
amphibious-pathableamphibious = 6 PATHING_TYPE_AMPHIBIOUSPATHING
Особый паффинг (код)
air and ground and buildable walk/build/fly => PATHING_TYPE_ANY
двоичный кодномер вариацииописание
000000 0 0 Ничего
000001 1 2^0=1 земля, мелководье (где можно ходить)
000010 2 2^1=2 воздух не имеет ограничении, кроме air-blockers и границ
000100 3 2^2=4 только земля (где можно строить)
001000 4 2^3=8 только не порча (пример колодец света не построишь на порче)
010000 5 2^4=16 море, мелководье (где можно плавать)
100000 6 2^5=32 земля, море, мелководье (где можно передвигавться амфибиям)
sea or ground or amphibious
(sea and ground) => строится только на мелководье (игнор земли и моря)
(sea and ground and amphibious) => строится только на мелководье (игнор земли и моря)
воздух является уникальным паффингом, поскольку на него мало воздействии. Кроме air-blockers и карт путей на него сложно повлиять. А взаимодействие с другими практически ничего не дает, только если нужно еще и проверять на air-блок.
уникальный паффинг (мелководье)
двоичный кодномер вариацииописание
010001 1 and 5 2^0 + 2^4 = 17 (sea and ground) => строится только на мелководье (игнор земли и моря)
110001 1 and 5 and 6 2^0 + 2^4 + 2^5 = 49 (sea and ground and amphibious) => строится только на мелководье (игнор земли и моря)
набор паффинга для порчи
двоичный кодномер вариацииописание
001001 1 and 4 2^0 + 2^3 = 9 не испорченные земля, мелководье (где можно ходить)
001010 2 and 4 2^1 + 2^3 = 10 не испорченный воздух
001100 3 and 4 2^2 + 2^3 = 12 не испорченная земля (где можно строить)
011000 4 and 4 2^4 + 2^3 = 24 не испорченные море, мелководье (где можно плавать)
101000 4 and 4 2^4 + 2^3 = 40 не испорченные земля, море, мелководье (где можно передвигавться амфибиям)
это пока что все вариации, которые предусмотрел автор. Пример, мне нужно строить на мелководье, я в таблице прописываю 17 или 49.

Обновление

теперь можно динамично указать несколько флагов, и картоделу не нужно залезать в капот, чтобы внести вправку источник
пример требование строить: флаги
удобно хранить все флаги в одной глобалке. пример, есть требования в варкрафте по строительству здании в определенных типах паффинга:
	--двоичный код
    ground = 1     --ground-pathable PATHING_TYPE_WALKABILITY   
    air = 2        --air-pathable PATHING_TYPE_FLYABILITY          
    buildable = 4  --buildable PATHING_TYPE_BUILDABILITY
    unblighted = 8 --unblighted PATHING_TYPE_BLIGHTPATHING 
    sea = 16        --sea-pathable PATHING_TYPE_FLOATABILITY
    amphibious = 32 --amphibious-pathable PATHING_TYPE_AMPHIBIOUSPATHING

	--инициирую таблицу, где будет забита база данных
	build_pathing_placement_resqures = {}
    --peasant (human)
    build_pathing_placement_resqures[FourCC('htow')]=buildable
    build_pathing_placement_resqures[FourCC('hhou')]=buildable
    build_pathing_placement_resqures[FourCC('hbar')]=buildable
    build_pathing_placement_resqures[FourCC('hbla')]=buildable
    build_pathing_placement_resqures[FourCC('hwtw')]=buildable
    build_pathing_placement_resqures[FourCC('halt')]=buildable
    build_pathing_placement_resqures[FourCC('harm')]=buildable
    build_pathing_placement_resqures[FourCC('hars')]=buildable
    build_pathing_placement_resqures[FourCC('hlum')]=buildable
    build_pathing_placement_resqures[FourCC('hgra')]=buildable
    build_pathing_placement_resqures[FourCC('hvlt')]=buildable
    --peon (orc)
    build_pathing_placement_resqures[FourCC('ogre')]=buildable
    build_pathing_placement_resqures[FourCC('otrb')]=buildable
    build_pathing_placement_resqures[FourCC('obar')]=buildable
    build_pathing_placement_resqures[FourCC('ofor')]=buildable
    build_pathing_placement_resqures[FourCC('oalt')]=buildable
    build_pathing_placement_resqures[FourCC('obea')]=buildable
    build_pathing_placement_resqures[FourCC('osld')]=buildable
    build_pathing_placement_resqures[FourCC('otto')]=buildable
    build_pathing_placement_resqures[FourCC('owtw')]=buildable
    build_pathing_placement_resqures[FourCC('ovln')]=buildable
если нужно указать несколько флагов, то складываем:
	--пример air+buildable=2+4=6
	build_pathing_placement_resqures[FourCC('htow')]=air+buildable
	
	--или пример ground+air+buildable=1+2+4=7
	build_pathing_placement_resqures[FourCC('hhou')]=ground+air+buildable
если нужно проверить флаги, можно использовать спец функцию:
function check_pathing_placement_resqures(x,y,flag) 

	if flag & 1 == 1 then
	   if (IsTerrainPathable(x, y, PATHING_TYPE_WALKABILITY)) then
		   return false
	   end
	end
	if flag & 2 == 2 then
	   if (IsTerrainPathable(x, y, PATHING_TYPE_FLYABILITY)) then
		   return false
	   end
	end
	if flag & 4 == 4 then
	   if (IsTerrainPathable(x, y, PATHING_TYPE_BUILDABILITY)) then
		   return false
	   end
	end
	if flag & 8 == 8 then
	   if not(IsTerrainPathable(x, y, PATHING_TYPE_BLIGHTPATHING)) then
		   return false
	   end
	end
	if flag & 16 == 16 then
	   if (IsTerrainPathable(x, y, PATHING_TYPE_FLOATABILITY)) then
		   return false
	   end
	end
	if flag & 32 == 32 then
	   if (IsTerrainPathable(x, y, PATHING_TYPE_AMPHIBIOUSPATHING)) then
		   return false
	   end
	end
	
	return true
end
запрет строить в опред типе паффинге
аналогично и с запретом строить в определенном месте, как пример у нежити запрещено строить не на порче.
	build_pathing_placement_prevented_by = {}
    --acolyte (undead)
    build_pathing_placement_prevented_by[FourCC('uzig')]=unblighted
    build_pathing_placement_prevented_by[FourCC('usep')]=unblighted
    build_pathing_placement_prevented_by[FourCC('ugrv')]=unblighted
    build_pathing_placement_prevented_by[FourCC('uaod')]=unblighted
    build_pathing_placement_prevented_by[FourCC('utod')]=unblighted
    build_pathing_placement_prevented_by[FourCC('uslh')]=unblighted
    build_pathing_placement_prevented_by[FourCC('ubon')]=unblighted
    build_pathing_placement_prevented_by[FourCC('usap')]=unblighted
    build_pathing_placement_prevented_by[FourCC('utom')]=unblighted
если нужно проверить флаги, можно использовать спец функцию:
function check_pathing_placement_prevented_by(x,y,flag) 

	if flag & 1 == 1 then
	   if not(IsTerrainPathable(x, y, PATHING_TYPE_WALKABILITY)) then
		   return false
	   end
	end
	if flag & 2 == 2 then
	   if not(IsTerrainPathable(x, y, PATHING_TYPE_FLYABILITY)) then
		   return false
	   end
	end
	if flag & 4 == 4 then
	   if not(IsTerrainPathable(x, y, PATHING_TYPE_BUILDABILITY)) then
		   return false
	   end
	end
	if flag & 8 == 8 then
	   if (IsTerrainPathable(x, y, PATHING_TYPE_BLIGHTPATHING)) then
		   return false
	   end
	end
	if flag & 16 == 16 then
	   if not(IsTerrainPathable(x, y, PATHING_TYPE_FLOATABILITY)) then
		   return false
	   end
	end
	if flag & 32 == 32 then
	   if not(IsTerrainPathable(x, y, PATHING_TYPE_AMPHIBIOUSPATHING)) then
		   return false
	   end
	end
	
	return true
end
база данных зданий
здесь хранятся иконки, описание, модели здании итд.
    
    path_icon = "ReplaceableTextures\\CommandButtons\\BTNSelectHeroOn"
	path_active_icon = "ReplaceableTextures\\CommandButtons\\BTN"
	path_disabled_icon = "ReplaceableTextures\\CommandButtonsDisabled\\DISBTN"
    path_icon_human_build = "ReplaceableTextures\\CommandButtons\\BTNHumanBuild"
    path_icon_orc_build = "ReplaceableTextures\\CommandButtons\\BTNBasicStruct"
    path_icon_cancel = "Cancel"
    
    build_menu_text_tip = "Вызывает меню постройки"
    build_menu_text_ubertip = "Показывает весь список здании, который может построить выбранный юнит"
    cancel_text_tip = "Отмена"
    cancel_text_ubertip = "Отменяет выбранный приказ"
    
    
        ToolTipBackground="UI\\Widgets\\ToolTips\\Human\\human-tooltip-background"
        ToolTipBorder="UI\\Widgets\\ToolTips\\Human\\human-tooltip-border"
        ToolTipGoldIcon="UI\\Widgets\\ToolTips\\Human\\ToolTipGoldIcon"
        ToolTipLumberIcon="UI\\Widgets\\ToolTips\\Human\\ToolTipLumberIcon"
        ToolTipStonesIcon="UI\\Widgets\\ToolTips\\Human\\ToolTipStonesIcon"
        ToolTipManaIcon="UI\\Widgets\\ToolTips\\Human\\ToolTipManaIcon"
        ToolTipSupplyIcon="UI\\Widgets\\ToolTips\\Human\\ToolTipSupplyIcon"
        ToolTipHorizontalSeparator="UI\\Widgets\\ToolTips\\Human\\HorizontalSeparator"
        
    
    list_builder = {}
    list_builder[FourCC('hpea')] = {'htow','hhou','hbar','hbla','hwtw','halt','harm','hars','hlum','hgra','hvlt'}
    list_builder[FourCC('opeo')] = {'ogre','otrb','obar','ofor','oalt','obea','osld','otto','owtw','ovln'}
    build_icon = {}
    build_icon[FourCC('htow')]="TownHall"
    build_icon[FourCC('hhou')]="Farm"
    build_icon[FourCC('hbar')]="HumanBarracks"
    build_icon[FourCC('hbla')]="Blacksmith"
    build_icon[FourCC('hwtw')]="HumanWatchTower"
    build_icon[FourCC('halt')]="AltarOfKings"
    build_icon[FourCC('harm')]="Workshop"
    build_icon[FourCC('hars')]="ArcaneSanctum"
    build_icon[FourCC('hlum')]="HumanLumberMill"
    build_icon[FourCC('hgra')]="GryphonAviary"
    build_icon[FourCC('hvlt')]="ArcaneVault"
    
    build_icon[FourCC('ogre')]="Greathall"
    build_icon[FourCC('otrb')]="TrollBurrow"
    build_icon[FourCC('obar')]="Barracks"
    build_icon[FourCC('ofor')]="Forge"
    build_icon[FourCC('oalt')]="AltarOfStorms"
    build_icon[FourCC('obea')]="Beastiary"
    build_icon[FourCC('osld')]="SpiritLodge"
    build_icon[FourCC('otto')]="TaurenTotem"
    build_icon[FourCC('owtw')]="OrcTower"
    build_icon[FourCC('ovln')]="VoodooLounge"
    
    build_model = {}
    build_model[FourCC('htow')]="buildings\\human\\TownHall\\TownHall"
    build_model[FourCC('hhou')]="buildings\\human\\Farm\\Farm"
    build_model[FourCC('hbar')]="buildings\\human\\HumanBarracks\\HumanBarracks"
    build_model[FourCC('hbla')]="buildings\\human\\Blacksmith\\Blacksmith"
    build_model[FourCC('hwtw')]="buildings\\human\\HumanTower\\HumanTower"
    build_model[FourCC('halt')]="buildings\\human\\AltarofKings\\AltarofKings"
    build_model[FourCC('harm')]="buildings\\human\\Workshop\\Workshop"
    build_model[FourCC('hars')]="buildings\\human\\ArcaneSanctum\\ArcaneSanctum"
    build_model[FourCC('hlum')]="buildings\\human\\HumanLumbermill\\HumanLumbermill"
    build_model[FourCC('hgra')]="buildings\\human\\GryphonAviary\\GryphonAviary"
    build_model[FourCC('hvlt')]="buildings\\human\\ArcaneVault\\ArcaneVault"
    
    build_model[FourCC('ogre')]="buildings\\orc\\GreatHall\\GreatHall"
    build_model[FourCC('otrb')]="buildings\\orc\\TrollBurrow\\TrollBurrow"
    build_model[FourCC('obar')]="buildings\\orc\\OrcBarracks\\OrcBarracks"
    build_model[FourCC('ofor')]="buildings\\orc\\WarMill\\WarMill"
    build_model[FourCC('oalt')]="buildings\\orc\\AltarofStorms\\AltarofStorms"
    build_model[FourCC('obea')]="buildings\\orc\\Beastiary\\Beastiary"
    build_model[FourCC('osld')]="buildings\\orc\\SpiritLodge\\SpiritLodge"
    build_model[FourCC('otto')]="buildings\\orc\\TaurenTotem\\TaurenTotem"
    build_model[FourCC('owtw')]="buildings\\orc\\WatchTower\\WatchTower"
    build_model[FourCC('ovln')]="buildings\\orc\\VoodooLounge\\VoodooLounge"
    
    build_size_ground_pathing = {}
    build_size_naval_pathing = {}
    build_size_ground_pathing[FourCC('htow')]=32*16
    build_size_ground_pathing[FourCC('hhou')]=32*4
    build_size_ground_pathing[FourCC('hbar')]=32*12
    build_size_ground_pathing[FourCC('hbla')]=32*8
    build_size_ground_pathing[FourCC('hwtw')]=32*4
    build_size_ground_pathing[FourCC('halt')]=32*10
    build_size_ground_pathing[FourCC('harm')]=32*12
    build_size_ground_pathing[FourCC('hars')]=32*12
    build_size_ground_pathing[FourCC('hlum')]=32*10
    build_size_ground_pathing[FourCC('hgra')]=32*8
    build_size_ground_pathing[FourCC('hvlt')]=32*12
    
    build_size_ground_pathing[FourCC('ogre')]=32*16
    build_size_ground_pathing[FourCC('otrb')]=32*6
    build_size_ground_pathing[FourCC('obar')]=32*12
    build_size_ground_pathing[FourCC('ofor')]=32*6
    build_size_ground_pathing[FourCC('oalt')]=32*10
    build_size_ground_pathing[FourCC('obea')]=32*12
    build_size_ground_pathing[FourCC('osld')]=32*12
    build_size_ground_pathing[FourCC('otto')]=32*12
    build_size_ground_pathing[FourCC('owtw')]=32*4
    build_size_ground_pathing[FourCC('ovln')]=32*12
    
    size_pathing_magenta = {}
    --для декорации
    size_pathing_magenta[FourCC('ATtr')]=32*4
    size_pathing_magenta[FourCC('ATtc')]=32*4
    size_pathing_magenta[FourCC('LTlt')]=32*4
    
    build_text_tip = {}
    build_text_tip[FourCC('htow')]="Построить ратушу"
    build_text_tip[FourCC('hhou')]="Построить ферму"
    build_text_tip[FourCC('hbar')]="Построить казармы"
    build_text_tip[FourCC('hbla')]="Построить кузницу"
    build_text_tip[FourCC('hwtw')]="Построить дозорную башню"
    build_text_tip[FourCC('halt')]="Построить алтарь королей"
    build_text_tip[FourCC('harm')]="Построить мастерскую"
    build_text_tip[FourCC('hars')]="Построить волшебное святилище"
    build_text_tip[FourCC('hlum')]="Построить лесопилку"
    build_text_tip[FourCC('hgra')]="Построить авиарий"
    build_text_tip[FourCC('hvlt')]="Построить волшебное хранилище"
    
    build_text_tip[FourCC('ogre')]="Построить дом вождей"
    build_text_tip[FourCC('otrb')]="Построить землянку"
    build_text_tip[FourCC('obar')]="Построить казармы"
    build_text_tip[FourCC('ofor')]="Построить лесопилку"
    build_text_tip[FourCC('oalt')]="Построить алтарь бури"
    build_text_tip[FourCC('obea')]="Построить зверинец"
    build_text_tip[FourCC('osld')]="Построить обитель духов"
    build_text_tip[FourCC('otto')]="Построить тауренский тотем"
    build_text_tip[FourCC('owtw')]="Построить сторожевую башню"
    build_text_tip[FourCC('ovln')]="Построить лавку вуду"
    
    build_text_ubertip = {}
    build_text_ubertip[FourCC('htow')]="Базовое здание. Обучает работников и хранит добытые ресурсы. Можно улучшить до форта, а затем до замка, чтобы получить доступ к новым зданиям и типам войск."
    build_text_ubertip[FourCC('hhou')]="Предоставляет припасы, увеличивая максимальную численность армии."
    build_text_ubertip[FourCC('hbar')]="Здание для подготовки базовых войск. Обучает пехотинцев, стрелков и рыцарей. |nДает доступ к «Защите», «Длинноствольным мушкетам» и «Дрессировке животных»."
    build_text_ubertip[FourCC('hbla')]="Позволяет улучшать доспехи, оружие и порох."
    build_text_ubertip[FourCC('hwtw')]="Базовая наблюдательная башня. Не может атаковать, но может быть улучшена до сторожевой, магической или орудийной башни. Можно оснастить «Магическим стражем»."
    build_text_ubertip[FourCC('halt')]="Призывает новых и воскрешает павших героев."
    build_text_ubertip[FourCC('harm')]="Строит осадные машины и ветролеты, а также обучает мортирные расчеты. |nДает доступ к осветительным зарядам, картечи, залповому огню, авиабомбам и зенитным орудиям."
    build_text_ubertip[FourCC('hars')]="Обучает жрецов, волшебниц и разрушителей чар. |nДает доступ к улучшениям для жрецов и волшебниц, а также к «Магическому контролю» и «Магическому стражу»."
    build_text_ubertip[FourCC('hlum')]="Хранит добытую древесину. |nДает доступ к новым технологиям добычи древесины и строительства."
    build_text_ubertip[FourCC('hgra')]="Обучает наездников на грифонах и дракондорах. |nДает доступ к «Грозовому молоту» и «Туману»."
    build_text_ubertip[FourCC('hvlt')]="Позволяет покупать предметы. Ассортимент зависит от уровня главного здания базы (ратуша, форт или замок) и наличия других зданий."
    
    build_text_ubertip[FourCC('ogre')]="Базовое здание. Обучает батраков и хранит добытые ресурсы. Можно улучшить до крепости, а затем – до цитадели, чтобы получить доступ к новым зданиям и типам войск."
    build_text_ubertip[FourCC('otrb')]="Предоставляет припасы, увеличивая максимальную численность армии. Батраки могут укрыться в землянке и атаковать врагов. Можно улучшить с помощью укрепленных стен. |n|n|cffffcc00Атакует наземные и воздушные цели.|r"
    build_text_ubertip[FourCC('obar')]="Здание для подготовки базовых войск. Обучает рубак и охотников за головами, а также строит разрушители. |nДает доступ к «Грубой силе», «Берсерку», «Регенерации троллей» и «Горючей смеси»."
    build_text_ubertip[FourCC('ofor')]="Хранит добытую древесину. |nДает доступ к улучшениям для доспехов и оружия, а также позволяет строить укрепления."
    build_text_ubertip[FourCC('oalt')]="Призывает новых и воскрешает павших героев."
    build_text_ubertip[FourCC('obea')]="Обучает налетчиков, кодо, а также наездников на нетопырях и ветрокрылах. |nДает доступ к «Опутыванию», «Отравленным копьям», «Жидкому огню» и «Боевым барабанам»."
    build_text_ubertip[FourCC('osld')]="Здание для подготовки магов. Обучает шаманов и знахарей. |nДает доступ к улучшениям для шаманов и знахарей."
    build_text_ubertip[FourCC('otto')]="Обучает духостранников и тауренов. |nДает доступ к улучшениям для духостранников и тауренов."
    build_text_ubertip[FourCC('owtw')]="Оборонительное сооружение. Можно улучшить с помощью укрепленных стен. |n|n|cffffcc00Атакует наземные и воздушные цели.|r"
    build_text_ubertip[FourCC('ovln')]="Позволяет покупать предметы. Ассортимент зависит от уровня главного здания базы (дом вождей, крепость или цитадель) и наличия других зданий."
    
    build_text_hotkey = {}
    build_text_hotkey[FourCC('htow')]="H"
    build_text_hotkey[FourCC('hhou')]="F"
    build_text_hotkey[FourCC('hbar')]="B"
    build_text_hotkey[FourCC('hbla')]="S"
    build_text_hotkey[FourCC('hwtw')]="T"
    build_text_hotkey[FourCC('halt')]="A"
    build_text_hotkey[FourCC('harm')]="W"
    build_text_hotkey[FourCC('hars')]="R"
    build_text_hotkey[FourCC('hlum')]="L"
    build_text_hotkey[FourCC('hgra')]="G"
    build_text_hotkey[FourCC('hvlt')]="V"
    
    build_text_hotkey[FourCC('ogre')]="H"
    build_text_hotkey[FourCC('otrb')]="O"
    build_text_hotkey[FourCC('obar')]="B"
    build_text_hotkey[FourCC('ofor')]="M"
    build_text_hotkey[FourCC('oalt')]="A"
    build_text_hotkey[FourCC('obea')]="E"
    build_text_hotkey[FourCC('osld')]="S"
    build_text_hotkey[FourCC('otto')]="T"
    build_text_hotkey[FourCC('owtw')]="W"
    build_text_hotkey[FourCC('ovln')]="V"
    
    build_gold_cost,build_lumb_cost,build_mana_cost,build_food_cost = {},{},{},{}
    build_gold_cost[FourCC('htow')]=385
    build_gold_cost[FourCC('hhou')]=80
    build_gold_cost[FourCC('hbar')]=160
    build_gold_cost[FourCC('hbla')]=140
    build_gold_cost[FourCC('hwtw')]=30
    build_gold_cost[FourCC('halt')]=180
    build_gold_cost[FourCC('harm')]=140
    build_gold_cost[FourCC('hars')]=150
    build_gold_cost[FourCC('hlum')]=145
    build_gold_cost[FourCC('hgra')]=120
    build_gold_cost[FourCC('hvlt')]=130
    
    build_gold_cost[FourCC('ogre')]=385
    build_gold_cost[FourCC('otrb')]=160
    build_gold_cost[FourCC('obar')]=180
    build_gold_cost[FourCC('ofor')]=205
    build_gold_cost[FourCC('oalt')]=180
    build_gold_cost[FourCC('obea')]=145
    build_gold_cost[FourCC('osld')]=150
    build_gold_cost[FourCC('otto')]=90
    build_gold_cost[FourCC('owtw')]=110
    build_gold_cost[FourCC('ovln')]=130
    
    build_lumb_cost[FourCC('htow')]=205
    build_lumb_cost[FourCC('hhou')]=20
    build_lumb_cost[FourCC('hbar')]=60
    build_lumb_cost[FourCC('hbla')]=60
    build_lumb_cost[FourCC('hwtw')]=20
    build_lumb_cost[FourCC('halt')]=50
    build_lumb_cost[FourCC('harm')]=140
    build_lumb_cost[FourCC('hars')]=140
    build_lumb_cost[FourCC('hlum')]=0
    build_lumb_cost[FourCC('hgra')]=240
    build_lumb_cost[FourCC('hvlt')]=30
    
    build_lumb_cost[FourCC('ogre')]=185
    build_lumb_cost[FourCC('otrb')]=40
    build_lumb_cost[FourCC('obar')]=50
    build_lumb_cost[FourCC('ofor')]=0
    build_lumb_cost[FourCC('oalt')]=50
    build_lumb_cost[FourCC('obea')]=140
    build_lumb_cost[FourCC('osld')]=150
    build_lumb_cost[FourCC('otto')]=200
    build_lumb_cost[FourCC('owtw')]=80
    build_lumb_cost[FourCC('ovln')]=30
    
    buildings_required_for_construction ={}
    buildings_required_for_construction[FourCC('hbla')]={'htow'}
    buildings_required_for_construction[FourCC('harm')]={'hkee','hbla'}
    buildings_required_for_construction[FourCC('hars')]={'hkee'}
    buildings_required_for_construction[FourCC('hars')]={'hkee'}
    buildings_required_for_construction[FourCC('hgra')]={'hcas','hlum'}
    
    buildings_required_for_construction[FourCC('otto')]={'ofrt','ofor'}
    buildings_required_for_construction[FourCC('osld')]={'ostr'}
    buildings_required_for_construction[FourCC('obea')]={'ostr'}
    buildings_required_for_construction[FourCC('owtw')]={'ofor'}
    
    
    tech_required_for_construction ={}
основной код с фреймами, движение мыши итд
function LoadToc(s)
    if BlzLoadTOCFile(s) then
        print("Loaded: "..s)
    else
        print("Failed to Load: "..s)
    end
end

--находит узлы координатной оси
function Real_offset_64(r)
    local a,c,k
    if r == 0 then
        c = 0
    elseif r>0 then  
        a = math.modf(r/64)
        c = 64.00*a
    elseif r<0 then
        a = math.modf(r/64)-1
        c = 64.00*a  
    end
    return c
end
-- check type defense ==============
function GetUnitDefenseType(unit)
    return BlzGetUnitIntegerField(unit, UNIT_IF_DEFENSE_TYPE)
end 




do
    local real = MarkGameStarted
  function MarkGameStarted()
        real()

        local n = GetPlayerId(GetLocalPlayer())

        build_menu = {}

        build_menu[n]={}
        --флаги
        build_menu[n].display_interface = false --вкл/откл полностью меню строительства
        build_menu[n].display_menu_builder = false --отображается ли меню у игрока
        build_menu[n].player_chooses_place = false --игрок выбирает место
        build_menu[n].mask_cursor_mouse_in_frame=false --флаг, который показывает находится ли курсор внутри маски. помогает при перетаскивании прятать ии снимать курсор
        build_menu[n].button_cancel_cursor_mouse_in_frame=false --флаг, который показывает находится ли курсор внутри кнопки "отмена"
        build_menu[n].button_menu_builder_cursor_mouse_in_frame=false --флаг, который показывает находится ли курсор внутри кнопки "меню строительства"
        
        --параметры кнопок контейнера
        build_menu[n].button={} --кнопка
        build_menu[n].IconTexture={} --иконка
        build_menu[n].Trigger_click={} --триггер
        build_menu[n].Tooltip={} --главная подсказка
        build_menu[n].Tooltip_title={} --заглавие подсказки
        build_menu[n].Tooltip_Text={} --описание подсказки (текст)
        build_menu[n].Tooltip_HorizontalSeparator={} --горизонтальная линия между описанием и заглавием
        build_menu[n].Tooltip_Backdrop={} --фон подсказки
        build_menu[n].Building_Id={} --ид тип здания
        build_menu[n].trigger={} --нигде не используются
        build_menu[n].cursor_mouse_in_frame={} --нигде не используются
        
        --ресурс-полоса подсказки
        build_menu[n].resourse_bar={} --ресурс-полоса подсказки
        build_menu[n].icon_gold_cost={} --иконка золота
        build_menu[n].text_gold_cost={} --текст золота, отображающий стоимость
        build_menu[n].icon_lumber_cost={} --иконка дерева
        build_menu[n].text_lumber_cost={} --текст дерева, отображающий стоимость
        build_menu[n].icon_mana_cost={} --иконка маны (если она указана)
        build_menu[n].text_mana_cost={} --текст маны, отображающий стоимость
        build_menu[n].icon_food_cost={} --иконка пищи (если она указана)
        build_menu[n].text_food_cost={} --текст пищи, отображающий стоимость
        
        --требование подсказки
        build_menu[n].text_building_requirement={} --текст, описывающий требование построить здания
        build_menu[n].text_tech_requirement={} --текст, описывающий требование изучить технологию
        
        --данные кнопки (записываются из данных здания)
        build_menu[n].gold_required={} --кол-во требуемой золота
        build_menu[n].lumber_required={} --кол-во требуемой древесины
        build_menu[n].mana_required={} --кол-во требуемой маны (если она есть)
        build_menu[n].food_required={} --кол-во требуемой пищи (если она есть)
        build_menu[n].requirement_met={}--выполнено ли требования построить здания/изучить технологии	
        
        --требуемые характеристики при выборе места строительства игроком
        build_menu[n].id=0 --ид тип здания
        build_menu[n].model=nil --спецэффект (модель здания)
        build_menu[n].image={} --images (изображения)
        build_menu[n].image_x={}
        build_menu[n].image_y={}
        build_menu[n].flag={}
        build_menu[n].size=0 --размер паффинга здания
        build_menu[n].can_build=false --флаг, чекает местность на возможность строить
        build_menu[n].coord_x = 0 --координаты при выборе места для строительства
        build_menu[n].coord_y = 0
        

    
    
    
	
	
	
	BlzLoadTOCFile("war3mapImported\\MySimpleButton.toc")
	local gameUI = BlzGetOriginFrame(ORIGIN_FRAME_GAME_UI, 0)
    
	build_menu[n].interface = BlzCreateFrameByType("FRAME","interface",gameUI,"",0)
    BlzFrameSetVisible(build_menu[n].interface, false)
	
	--контейнер кнопок 1-12
    build_menu[n].conteiner = BlzCreateFrameByType("FRAME","conteiner",build_menu[n].interface,"",0)
    BlzFrameSetLevel(build_menu[n].conteiner, 5)
	
    --мертвая зона
    build_menu[n].DeadZoneMouse=BlzCreateFrameByType("SLIDER","DeadZoneMouse",build_menu[n].interface,"",0)
    build_menu[n].backdrop=BlzCreateFrameByType("BACKDROP","backdrop",build_menu[n].interface,"",0)
    BlzFrameSetLevel(build_menu[n].DeadZoneMouse, 1)
    
	--маска экрана (не дает выделять и выбирать объекты на карте во время выбора участка)  
    build_menu[n].Mask=BlzCreateFrameByType("SLIDER","DeadZoneMouse",BlzGetFrameByName("ConsoleUIBackdrop",0),"",0)
    BlzFrameSetLevel(build_menu[n].Mask, 1)
    BlzFrameSetSize(build_menu[n].Mask, 0.6*2, 0.6*2)
    BlzFrameSetEnable(build_menu[n].Mask, false)
    BlzFrameSetAbsPoint(build_menu[n].Mask, FRAMEPOINT_CENTER, 0.4, 0.3)
    
    local num = 0
    local size_button = 0.039
    
    for b=3, 1,-1 do
        for a=1, 4, 1 do
            num = num + 1
            --создаем кнопку
            build_menu[n].button[num] = BlzCreateFrameByType("SLIDER","button",build_menu[n].conteiner,"",num)
            build_menu[n].IconTexture[num] = BlzCreateFrameByType("BACKDROP","IconTexture",build_menu[n].button[num],"",num)
            
            --настройка кнопки и ее иконки
            BlzFrameSetAbsPoint(build_menu[n].button[num], FRAMEPOINT_CENTER, 0.4+(size_button*(a-1)), 0.3+(size_button*(b-1)))
            BlzFrameSetAllPoints(build_menu[n].IconTexture[num],build_menu[n].button[num])
            BlzFrameSetTexture(build_menu[n].IconTexture[num], path_icon, 0, true)
            BlzFrameSetSize(build_menu[n].button[num], size_button, size_button)
            
            --создаем главную подсказку (родителя всего tooltip)
            build_menu[n].Tooltip[num] = BlzCreateFrameByType("FRAME","tooltip",build_menu[n].button[num],"",num)
            BlzFrameSetVisible(build_menu[n].Tooltip[num], false)
            
            --создаем элементы подсказки
            build_menu[n].Tooltip_Backdrop[num] = BlzCreateFrameByType("BACKDROP","backdrop tooltip",build_menu[n].Tooltip[num],"BoxedTextBackgroundTemplate",num)   
            build_menu[n].Tooltip_title[num]=BlzCreateFrameByType("TEXT","title tooltip",build_menu[n].Tooltip[num],"BoxedTextTitle",num)
            build_menu[n].Tooltip_Text[num]=BlzCreateFrameByType("TEXT","description tooltip",build_menu[n].Tooltip[num],"BoxedTextValue",num)
            build_menu[n].Tooltip_HorizontalSeparator[num]=BlzCreateFrameByType("BACKDROP","Separator",build_menu[n].Tooltip[num],"",num)
            
            --настраиваем описание
            BlzFrameSetAbsPoint( build_menu[n].Tooltip_Text[num], FRAMEPOINT_BOTTOMLEFT, 0.55, 0.19)
            BlzFrameSetSize(build_menu[n].Tooltip_Text[num], 0.25, 0)
            BlzFrameSetEnable(build_menu[n].Tooltip_Text[num], false)
            BlzFrameSetText(build_menu[n].Tooltip_Text[num],'описание')

            --настраиваем горизонтальную линию (крепится к описанию)
            BlzFrameSetPoint(build_menu[n].Tooltip_HorizontalSeparator[num], FRAMEPOINT_BOTTOMLEFT, build_menu[n].Tooltip_Text[num], FRAMEPOINT_TOPLEFT, 0.0025, 0.0025)
            BlzFrameSetPoint(build_menu[n].Tooltip_HorizontalSeparator[num], FRAMEPOINT_BOTTOMRIGHT, build_menu[n].Tooltip_Text[num], FRAMEPOINT_TOPRIGHT, 0.0025, 0.0025)
            BlzFrameSetSize(build_menu[n].Tooltip_HorizontalSeparator[num], 0, 0.0015)
            BlzFrameSetTexture(build_menu[n].Tooltip_HorizontalSeparator[num], "UI\\Widgets\\ToolTips\\Human\\HorizontalSeparator",0, true) 

            --настраиваем заглавие (крепится к горизонтальной линии)
            BlzFrameSetPoint(build_menu[n].Tooltip_title[num], FRAMEPOINT_BOTTOMLEFT, build_menu[n].Tooltip_HorizontalSeparator[num], FRAMEPOINT_TOPLEFT, -0.005, 0.005)
            BlzFrameSetSize(build_menu[n].Tooltip_title[num], 0.25, 0)
            BlzFrameSetEnable(build_menu[n].Tooltip_title[num], false)
            BlzFrameSetText(build_menu[n].Tooltip_title[num],'заглавие')

            --настраиваем фон подсказки (настроек мало, тк часть лежит в fdf-file)
            BlzFrameSetPoint(build_menu[n].Tooltip_Backdrop[num], FRAMEPOINT_BOTTOMLEFT, build_menu[n].Tooltip_Text[num], FRAMEPOINT_BOTTOMLEFT, -0.005, -0.005)
            BlzFrameSetPoint(build_menu[n].Tooltip_Backdrop[num], FRAMEPOINT_TOPRIGHT, build_menu[n].Tooltip_title[num], FRAMEPOINT_TOPRIGHT, 0.005, 0.005)
            
            --далее идут требования к подсказке (их еще некуда крепить, тк неизвестны требования, поэтому просто создаем) 
            --Tooltip: resourse_bar
            build_menu[n].resourse_bar[num] = BlzCreateFrameByType("FRAME","resourse_bar",build_menu[n].Tooltip[num],"",num)
            BlzFrameSetVisible(build_menu[n].resourse_bar[num], false)
        
            --Tooltip: resourse_bar: mana cost
            build_menu[n].icon_mana_cost[num] = BlzCreateFrameByType("BACKDROP","icon_mana_cost",build_menu[n].resourse_bar[num],"",num)
            BlzFrameSetSize(build_menu[n].icon_mana_cost[num], 0.012, 0.012)
            BlzFrameSetTexture(build_menu[n].icon_mana_cost[num], ToolTipManaIcon, 0, true)
            BlzFrameSetVisible(build_menu[n].icon_mana_cost[num], false)
            
            build_menu[n].text_mana_cost[num] = BlzCreateFrameByType("TEXT","text mana cost",build_menu[n].icon_mana_cost[num] ,"BoxedTextValue",0)          
            BlzFrameSetEnable(build_menu[n].text_mana_cost[num], false)
            BlzFrameSetPoint(build_menu[n].text_mana_cost[num], FRAMEPOINT_LEFT, build_menu[n].icon_mana_cost[num], FRAMEPOINT_RIGHT, 0.0025, 0.0)
            BlzFrameSetSize(build_menu[n].text_mana_cost[num], 0, 0.012)
            --BlzFrameSetText(build_menu[n].text_mana_cost[num],'|cffffcc00'..requirements[FourCC('Hate')].mana_cost..'|r')
            
            --Tooltip: resourse_bar: gold cost
            build_menu[n].icon_gold_cost[num] = BlzCreateFrameByType("BACKDROP","icon gold cost",build_menu[n].resourse_bar[num],"",num)
            BlzFrameSetSize(build_menu[n].icon_gold_cost[num], 0.012, 0.012)
            BlzFrameSetTexture(build_menu[n].icon_gold_cost[num], ToolTipGoldIcon, 0, true)
            BlzFrameSetVisible(build_menu[n].icon_gold_cost[num], false)
            
            build_menu[n].text_gold_cost[num] = BlzCreateFrameByType("TEXT","text gold dcost",build_menu[n].icon_gold_cost[num] ,"BoxedTextValue",0)          
            BlzFrameSetEnable(build_menu[n].text_gold_cost[num], false)
            BlzFrameSetPoint(build_menu[n].text_gold_cost[num], FRAMEPOINT_LEFT, build_menu[n].icon_gold_cost[num], FRAMEPOINT_RIGHT, 0.0025, 0.0)
            BlzFrameSetSize(build_menu[n].text_gold_cost[num], 0, 0.012)
            --BlzFrameSetText(build_menu[n].text_gold_cost[num],'|cffffcc00'..requirements[FourCC('Hate')].gold_cost..'|r')
            
            --Tooltip: resourse_bar: lumber cost
            build_menu[n].icon_lumber_cost[num] = BlzCreateFrameByType("BACKDROP","icon lumber cost",build_menu[n].resourse_bar[num],"",num)
            BlzFrameSetSize(build_menu[n].icon_lumber_cost[num], 0.012, 0.012)
            BlzFrameSetTexture(build_menu[n].icon_lumber_cost[num], ToolTipLumberIcon, 0, true)
            BlzFrameSetVisible(build_menu[n].icon_lumber_cost[num], false)
            
            build_menu[n].text_lumber_cost[num] = BlzCreateFrameByType("TEXT","text lumber cost",build_menu[n].icon_lumber_cost[num] ,"BoxedTextValue",0)          
            BlzFrameSetEnable(build_menu[n].text_lumber_cost[num], false)
            BlzFrameSetPoint(build_menu[n].text_lumber_cost[num], FRAMEPOINT_LEFT, build_menu[n].icon_lumber_cost[num], FRAMEPOINT_RIGHT, 0.0025, 0.0)
            BlzFrameSetSize(build_menu[n].text_lumber_cost[num], 0, 0.012)
            --BlzFrameSetText(build_menu[n].text_lumber_cost[num],'|cffffcc00'..requirements[FourCC('Hate')].lumber_cost..'|r')

            
            --Tooltip: resourse_bar: food cost
            build_menu[n].icon_food_cost[num] = BlzCreateFrameByType("BACKDROP","icon food cost",build_menu[n].resourse_bar[num],"",num)
            BlzFrameSetSize(build_menu[n].icon_food_cost[num], 0.012, 0.012)
            BlzFrameSetTexture(build_menu[n].icon_food_cost[num], ToolTipSupplyIcon, 0, true)
            BlzFrameSetVisible(build_menu[n].icon_food_cost[num], false)
            
            build_menu[n].text_food_cost[num] = BlzCreateFrameByType("TEXT","text_food_cost",build_menu[n].icon_food_cost[num] ,"BoxedTextValue",0)          
            BlzFrameSetEnable(build_menu[n].text_food_cost[num], false)
            BlzFrameSetPoint(build_menu[n].text_food_cost[num], FRAMEPOINT_LEFT, build_menu[n].icon_food_cost[num], FRAMEPOINT_RIGHT, 0.0025, 0.0)
            BlzFrameSetSize(build_menu[n].text_food_cost[num], 0, 0.012)
            --BlzFrameSetText(build_menu[n].text_food_cost[num],'|cffffcc00'..requirements[FourCC('Hate')].lumber_cost..'|r')

            
            --Tooltip: text_building_requirement
            build_menu[n].text_building_requirement[num] = BlzCreateFrameByType("TEXT","text_building_requirement",build_menu[n].Tooltip[num],"BoxedTextValue",num)          
            BlzFrameSetEnable(build_menu[n].text_building_requirement[num], false)
            BlzFrameSetSize(build_menu[n].text_building_requirement[num], 0.25, 0)
            BlzFrameSetVisible(build_menu[n].text_building_requirement[num], false)
            
            --Tooltip: text_tech_requirement
            build_menu[n].text_tech_requirement[num] = BlzCreateFrameByType("TEXT","text_tech_requirement",build_menu[n].Tooltip[num],"BoxedTextValue",num)          
            BlzFrameSetEnable(build_menu[n].text_tech_requirement[num], false)
            BlzFrameSetSize(build_menu[n].text_tech_requirement[num], 0.25, 0)
            BlzFrameSetVisible(build_menu[n].text_tech_requirement[num], false)
            
            --прикрепляем к кнопке подсказку
            BlzFrameSetTooltip(build_menu[n].button[num], build_menu[n].Tooltip[num])
            
            build_menu[n].gold_required[num]=0
            build_menu[n].lumber_required[num]=0
            build_menu[n].mana_required[num]=0
            build_menu[n].food_required[num]=0
        end
    end	
	
    -- ========= кнопка отмены ===========================
        local button_cancel = BlzCreateFrameByType("SLIDER","button cancel",build_menu[n].interface,"",0)
        local icon_button_cancel = BlzCreateFrameByType("BACKDROP","IconTexture",button_cancel,"",0)
        BlzFrameSetAllPoints(button_cancel,build_menu[n].button[12])
        BlzFrameSetAllPoints(icon_button_cancel,button_cancel)
        BlzFrameSetTexture(icon_button_cancel, path_active_icon .. path_icon_cancel, 0, true)
        BlzFrameSetSize(button_cancel, size_button, size_button)
        BlzFrameSetVisible(button_cancel, false)
        BlzFrameSetLevel(button_cancel, 2)

        local tooltip_button_cancel = BlzCreateFrameByType("FRAME","tooltip",button_cancel,"",0)
        BlzFrameSetVisible(tooltip_button_cancel, false)
        
        local backdrop_tooltip_button_cancel = BlzCreateFrameByType("BACKDROP","backdrop tooltip",tooltip_button_cancel,"BoxedTextBackgroundTemplate",0)
        local description_tooltip_button_cancel = BlzCreateFrameByType("TEXT","description tooltip",tooltip_button_cancel,"BoxedTextValue",0)
        local title_tooltip_button_cancel = BlzCreateFrameByType("TEXT","title tooltip",tooltip_button_cancel,"BoxedTextTitle",0)
        local separator_tooltip_button_cancel = BlzCreateFrameByType("BACKDROP","Separator",tooltip_button_cancel,"",0)

        BlzFrameSetAbsPoint(description_tooltip_button_cancel, FRAMEPOINT_BOTTOMLEFT, 0.55, 0.19)
        BlzFrameSetSize(description_tooltip_button_cancel, 0.25, 0)
        BlzFrameSetEnable(description_tooltip_button_cancel, false)
        BlzFrameSetText(description_tooltip_button_cancel,cancel_text_ubertip)

        BlzFrameSetPoint(separator_tooltip_button_cancel, FRAMEPOINT_BOTTOMLEFT, description_tooltip_button_cancel, FRAMEPOINT_TOPLEFT, 0.0025, 0.0025)
        BlzFrameSetPoint(separator_tooltip_button_cancel, FRAMEPOINT_BOTTOMRIGHT, description_tooltip_button_cancel, FRAMEPOINT_TOPRIGHT, 0.0025, 0.0025)
        BlzFrameSetSize(separator_tooltip_button_cancel, 0, 0.0015)
        BlzFrameSetTexture(separator_tooltip_button_cancel, "UI\\Widgets\\ToolTips\\Human\\HorizontalSeparator",0, true) 

        BlzFrameSetPoint(title_tooltip_button_cancel, FRAMEPOINT_BOTTOMLEFT, separator_tooltip_button_cancel, FRAMEPOINT_TOPLEFT, -0.005, 0.005)
        BlzFrameSetSize(title_tooltip_button_cancel, 0.25, 0)
        BlzFrameSetEnable(title_tooltip_button_cancel, false)
        BlzFrameSetText(title_tooltip_button_cancel,cancel_text_tip)

        BlzFrameSetPoint(backdrop_tooltip_button_cancel, FRAMEPOINT_BOTTOMLEFT, description_tooltip_button_cancel, FRAMEPOINT_BOTTOMLEFT, -0.005, -0.005)
        BlzFrameSetPoint(backdrop_tooltip_button_cancel, FRAMEPOINT_TOPRIGHT, title_tooltip_button_cancel, FRAMEPOINT_TOPRIGHT, 0.005, 0.005)
        BlzFrameSetTooltip(button_cancel, tooltip_button_cancel)
    
    --============ кнопка строительства меню ===========
        local button_build_menu = BlzCreateFrameByType("TEXT","button build menu",build_menu[n].interface,"",0)
        local icon_button_build_menu = BlzCreateFrameByType("BACKDROP","IconTexture",button_build_menu,"",0)
        BlzFrameSetAllPoints(button_build_menu,build_menu[n].button[9])
        BlzFrameSetAllPoints(icon_button_build_menu,button_build_menu)
        BlzFrameSetTexture(icon_button_build_menu, path_icon_human_build, 0, true)
        BlzFrameSetSize(button_build_menu, size_button, size_button)
        BlzFrameSetVisible(button_build_menu, false)

        local tooltip_button_build_menu = BlzCreateFrameByType("FRAME","tooltip",button_build_menu,"",0)
        BlzFrameSetVisible(tooltip_button_build_menu, false)
        
        local backdrop_tooltip_button_build_menu = BlzCreateFrameByType("BACKDROP","backdrop tooltip",tooltip_button_build_menu,"BoxedTextBackgroundTemplate",0)
        local description_tooltip_button_build_menu = BlzCreateFrameByType("TEXT","description tooltip",tooltip_button_build_menu,"BoxedTextValue",0)
        local title_tooltip_button_build_menu = BlzCreateFrameByType("TEXT","title tooltip",tooltip_button_build_menu,"BoxedTextTitle",0)
        local separator_tooltip_button_build_menu = BlzCreateFrameByType("BACKDROP","Separator",tooltip_button_build_menu,"",0)

        BlzFrameSetAbsPoint(description_tooltip_button_build_menu, FRAMEPOINT_BOTTOMLEFT, 0.55, 0.19)
        BlzFrameSetSize(description_tooltip_button_build_menu, 0.25, 0)
        BlzFrameSetEnable(description_tooltip_button_build_menu, false)
        BlzFrameSetText(description_tooltip_button_build_menu,build_menu_text_ubertip)

        BlzFrameSetPoint(separator_tooltip_button_build_menu, FRAMEPOINT_BOTTOMLEFT, description_tooltip_button_build_menu, FRAMEPOINT_TOPLEFT, 0.0025, 0.0025)
        BlzFrameSetPoint(separator_tooltip_button_build_menu, FRAMEPOINT_BOTTOMRIGHT, description_tooltip_button_build_menu, FRAMEPOINT_TOPRIGHT, 0.0025, 0.0025)
        BlzFrameSetSize(separator_tooltip_button_build_menu, 0, 0.0015)
        BlzFrameSetTexture(separator_tooltip_button_build_menu, "UI\\Widgets\\ToolTips\\Human\\HorizontalSeparator",0, true) 

        BlzFrameSetPoint(title_tooltip_button_build_menu, FRAMEPOINT_BOTTOMLEFT, separator_tooltip_button_build_menu, FRAMEPOINT_TOPLEFT, -0.005, 0.005)
        BlzFrameSetSize(title_tooltip_button_build_menu, 0.25, 0)
        BlzFrameSetEnable(title_tooltip_button_build_menu, false)
        BlzFrameSetText(title_tooltip_button_build_menu,build_menu_text_tip)

        BlzFrameSetPoint(backdrop_tooltip_button_build_menu, FRAMEPOINT_BOTTOMLEFT, description_tooltip_button_build_menu, FRAMEPOINT_BOTTOMLEFT, -0.005, -0.005)
        BlzFrameSetPoint(backdrop_tooltip_button_build_menu, FRAMEPOINT_TOPRIGHT, title_tooltip_button_build_menu, FRAMEPOINT_TOPRIGHT, 0.005, 0.005)
        BlzFrameSetTooltip(button_build_menu, tooltip_button_build_menu)
        
    --=========== функции ==================
        --создаем список, определяющий порядок в горизонтальном рядом ресурсов
		build_menu[n].frame_List = {}
        
        function UpdateResourseBarTooltip(num,plaYer) --
            local n = GetPlayerId(plaYer)
            local Type_building = build_menu[n].Building_Id[num]
            
            build_menu[n].frame_List = {} --пересоздаем локалку
            
            BlzFrameClearAllPoints(build_menu[n].icon_mana_cost[num])
            BlzFrameClearAllPoints(build_menu[n].icon_gold_cost[num])
            BlzFrameClearAllPoints(build_menu[n].icon_lumber_cost[num])
            BlzFrameClearAllPoints(build_menu[n].icon_food_cost[num])

                build_menu[n].gold_required[num]=0
                build_menu[n].lumber_required[num]=0
                build_menu[n].mana_required[num]=0
                build_menu[n].food_required[num]=0
            
            if build_gold_cost[Type_building] then
                if build_gold_cost[Type_building]>0 then
                    build_menu[n].frame_List[#build_menu[n].frame_List+1]=build_menu[n].icon_gold_cost[num]
                    build_menu[n].frame_List[#build_menu[n].frame_List+1]=build_menu[n].text_gold_cost[num]
                    build_menu[n].gold_required[num]=build_gold_cost[Type_building]
                    BlzFrameSetVisible(build_menu[n].icon_gold_cost[num], true)
                    BlzFrameSetText(build_menu[n].text_gold_cost[num],'|cffffcc00'..build_menu[n].gold_required[num]..'|r')

                else
                    BlzFrameSetVisible(build_menu[n].icon_gold_cost[num], false)
                end
            else
                BlzFrameSetVisible(build_menu[n].icon_gold_cost[num], false)
            end
            if build_lumb_cost[Type_building] then
                if build_lumb_cost[Type_building]>0 then
                    build_menu[n].frame_List[#build_menu[n].frame_List+1]=build_menu[n].icon_lumber_cost[num]
                    build_menu[n].frame_List[#build_menu[n].frame_List+1]=build_menu[n].text_lumber_cost[num]
                    build_menu[n].lumber_required[num]=build_lumb_cost[Type_building]

                    BlzFrameSetVisible(build_menu[n].icon_lumber_cost[num], true)
                    BlzFrameSetText(build_menu[n].text_lumber_cost[num],'|cffffcc00'..build_menu[n].lumber_required[num]..'|r')
                else
                    BlzFrameSetVisible(build_menu[n].icon_lumber_cost[num], false)
                end
            else
                BlzFrameSetVisible(build_menu[n].icon_lumber_cost[num], false)
            end
            if build_mana_cost[Type_building] then
                if build_mana_cost[Type_building]>0 then
                    build_menu[n].frame_List[#build_menu[n].frame_List+1]=build_menu[n].icon_mana_cost[num]
                    build_menu[n].frame_List[#build_menu[n].frame_List+1]=build_menu[n].text_mana_cost[num]
                    build_menu[n].mana_required[num]=build_mana_cost[Type_building]
                    BlzFrameSetText(build_menu[n].text_mana_cost[num],'|cffffcc00'..build_menu[n].mana_required[num]..'|r')
                    
                    BlzFrameSetVisible(build_menu[n].icon_mana_cost[num], true)
                else
                    BlzFrameSetVisible(build_menu[n].icon_mana_cost[num], false)
                end 
            else
                BlzFrameSetVisible(build_menu[n].icon_mana_cost[num], false)
            end
            if build_food_cost[Type_building] then
                if build_food_cost[Type_building]>0 then
                    build_menu[n].frame_List[#build_menu[n].frame_List+1]=build_menu[n].icon_food_cost[num]
                    build_menu[n].frame_List[#build_menu[n].frame_List+1]=build_menu[n].text_food_cost[num]
                    build_menu[n].food_required[num]=build_food_cost[Type_building]
                    
                    BlzFrameSetVisible(build_menu[n].icon_food_cost[num], true)
                    BlzFrameSetText(build_menu[n].text_food_cost[num],build_menu[n].food_required[num])
                else
                    BlzFrameSetVisible(build_menu[n].icon_food_cost[num], false)
                end 
            else
                BlzFrameSetVisible(build_menu[n].icon_food_cost[num], false)
            end
            --порядок определен, теперь прикрепляем звенья горизонтального ряда друг с другом
            for a=#build_menu[n].frame_List-1, 1, -2 do 
                --у каждого ресурса 2 фрейма: иконка и текст.
                --фреймы между ресурсами крепим друг к другу, иконка одного реса креится к тексту другого реса
                if a>1 then 
                    BlzFrameSetPoint(build_menu[n].frame_List[a], FRAMEPOINT_LEFT, build_menu[n].frame_List[a-1], FRAMEPOINT_RIGHT, 0.005, 0.0)
                end
            end
            
        end

        function update_building_requirement(key_frame, playeR)
           --если что-то указано, значит, проверяем на требование?
            if buildings_required_for_construction[key_frame] then
                if #buildings_required_for_construction[key_frame]>0 then
                    local co,str =  0,"Требуется:"
                    for a=1, #buildings_required_for_construction[key_frame] do
                        local Type = FourCC(buildings_required_for_construction[key_frame][a])
                        local count = BlzCountLivingPlayerUnitsOfTypeId(Type, playeR)
                        --print('кол-во '..GetObjectName(Type)..' = '..count)
                        if count==0 then
                            co =co+1
                            str=str.."|n-"..GetObjectName(Type)
                        end
                    end 
                    return co,str
                else
                    return 0
                end
            else
                return 0
            end
        end
        function update_tech_requirement(key_frame, playeR)
            local count,str =  0,"Требуется изучить:"
            if tech_required_for_construction[key_frame] then
                local table = tech_required_for_construction[key_frame]

                for techId, value in pairs(table) do
                    local lv = GetPlayerTechCount(playeR,FourCC(techId),true) --текущий уровень технологии
                    
                    --если текущий уровень lv не достиг требуемого уровня value
                    --значит, не изучен еще, записываем список технологии
                    if value > lv then
                        count = count + 1
                        str=str.."|n-"..GetObjectName(FourCC(techId))
                    end                    
                end
                return count,str
            else
                return 0
            end
        end
        function update_Tooltip_for_menu_builder(num, playeR)
            local n = GetPlayerId(playeR)
            local Type_building = build_menu[n].Building_Id[num]
            
            --кол-во требуемых здании, и список
            local count_1,str_1 = update_building_requirement(Type_building, playeR) 
            --кол-во требуемых технологии, и список
            local count_2,str_2 = update_tech_requirement(Type_building, playeR)
            local list_frame = {}

            --требования построить здания не выполнено, значит, добавляем фрейм подсказку
            if count_1 > 0  then
                --оставляем только требование на постройку
                BlzFrameSetVisible(build_menu[n].text_building_requirement[num], true)
                BlzFrameSetText(build_menu[n].text_building_requirement[num],'|cffffcc00'..str_1..'|r')
                list_frame[#list_frame+1]=build_menu[n].text_building_requirement[num]
            else
                BlzFrameSetVisible(build_menu[n].text_building_requirement[num], false)
            end
            --требования изучить технологию не выполнено, значит, добавляем фрейм подсказку
            if count_2 > 0  then
                --оставляем только требование на изучение технологии
                BlzFrameSetVisible(build_menu[n].text_tech_requirement[num], true)
                BlzFrameSetText(build_menu[n].text_tech_requirement[num],'|cffffcc00'..str_2..'|r')
                list_frame[#list_frame+1]=build_menu[n].text_tech_requirement[num]
            else
                BlzFrameSetVisible(build_menu[n].text_tech_requirement[num], false)
            end

            BlzFrameClearAllPoints(build_menu[n].Tooltip_title[num])
            BlzFrameClearAllPoints(build_menu[n].text_tech_requirement[num])
            BlzFrameClearAllPoints(build_menu[n].text_building_requirement[num])

               
            if count_1>0 or count_2>0 then 
                --заменяем иконку на не активную
                local icon = build_icon[Type_building]
                BlzFrameSetTexture(build_menu[n].IconTexture[num], path_disabled_icon .. icon, 0, true)
                build_menu[n].requirement_met[num]=false
                --убираем /прячем лишние фреймы
                BlzFrameSetVisible(build_menu[n].resourse_bar[num], false)
                
                if #list_frame>1 then
                    BlzFrameSetPoint(build_menu[n].Tooltip_title[num], FRAMEPOINT_BOTTOMLEFT, build_menu[n].text_building_requirement[num], FRAMEPOINT_TOPLEFT, -0.005, 0.005)
                    BlzFrameSetPoint(build_menu[n].text_building_requirement[num], FRAMEPOINT_BOTTOMLEFT, build_menu[n].Tooltip_HorizontalSeparator[num], FRAMEPOINT_TOPLEFT, -0.005, 0.005)
                    BlzFrameSetPoint(build_menu[n].text_tech_requirement[num], FRAMEPOINT_BOTTOMLEFT, build_menu[n].text_building_requirement[num], FRAMEPOINT_TOPLEFT, -0.005, 0.005)
                    
                    
                elseif #list_frame==1 then
                    BlzFrameSetPoint(build_menu[n].Tooltip_title[num], FRAMEPOINT_BOTTOMLEFT, list_frame[1], FRAMEPOINT_TOPLEFT, -0.005, 0.005)
                    BlzFrameSetPoint(list_frame[1], FRAMEPOINT_BOTTOMLEFT, build_menu[n].Tooltip_HorizontalSeparator[num], FRAMEPOINT_TOPLEFT, -0.005, 0.005)
                end  
            elseif count_1+count_2==0 then
                --заменяем иконку на активную
                local icon = build_icon[Type_building]
                BlzFrameSetTexture(build_menu[n].IconTexture[num], path_active_icon .. icon, 0, true)
                build_menu[n].requirement_met[num]=true
                
                UpdateResourseBarTooltip(num,playeR)
                if #build_menu[n].frame_List>0 then
                    BlzFrameSetVisible(build_menu[n].resourse_bar[num], true)
                    
                    BlzFrameClearAllPoints(build_menu[n].frame_List[1])
                    BlzFrameClearAllPoints(build_menu[n].Tooltip_title[num])
                        
                    BlzFrameSetPoint(build_menu[n].frame_List[1], FRAMEPOINT_BOTTOMLEFT, build_menu[n].Tooltip_HorizontalSeparator[num], FRAMEPOINT_TOPLEFT, -0.0018, 0.0025)
                    BlzFrameSetPoint(build_menu[n].Tooltip_title[num], FRAMEPOINT_BOTTOMLEFT, build_menu[n].frame_List[1]~=nil and build_menu[n].frame_List[1] or build_menu[n].Tooltip_HorizontalSeparator[num], FRAMEPOINT_TOPLEFT, 0.00025, 0.0025)
                else
                    BlzFrameSetVisible(build_menu[n].resourse_bar[num], false)
                    
                    BlzFrameClearAllPoints(build_menu[n].Tooltip_title[num])
                    BlzFrameSetPoint(build_menu[n].Tooltip_title[num], FRAMEPOINT_BOTTOMLEFT, build_menu[n].Tooltip_HorizontalSeparator[num], FRAMEPOINT_TOPLEFT, -0.005, 0.005)
                end
            end      
        end
        function BuildMenu_Cancel(n)
            if build_menu[n].display_menu_builder then --отображается ли меню у игрока

                --скрываем кнопку отмены
                BlzFrameSetVisible(button_cancel, false)
                --показываем кнопку меню
                BlzFrameSetVisible(button_build_menu, true)
                --скрываем контейнер 
                BlzFrameSetVisible(build_menu[n].conteiner, false)
                --меню раба закрыто
                build_menu[n].display_menu_builder = false
                
                --обнуляем данные ячеек
                for a=1, 12 do
                    build_menu[n].Building_Id[a]=0
                    BlzFrameSetTexture(build_menu[n].IconTexture[a], path_icon, 0, true)
                    BlzFrameSetText(build_menu[n].Tooltip_Text[a],'описание')
                    BlzFrameSetText(build_menu[n].Tooltip_title[a],'заглавие')
                    build_menu[n].requirement_met[a]=false
                    
                end
            elseif build_menu[n].player_chooses_place then --если игрок выбирает место строительства
                --скрываем кнопку отмены
                BlzFrameSetVisible(button_cancel, false)
                --показываем кнопку меню
                BlzFrameSetVisible(button_build_menu, true)
                --скрываем контейнер 
                BlzFrameSetVisible(build_menu[n].conteiner, false)
                --меню раба закрыто
                build_menu[n].display_menu_builder = false
                
                --обнуляем данные ячеек
                for a=1, 12 do
                    build_menu[n].Building_Id[a]=0
                    BlzFrameSetTexture(build_menu[n].IconTexture[a], path_icon, 0, true)
                    BlzFrameSetText(build_menu[n].Tooltip_Text[a],'описание')
                    BlzFrameSetText(build_menu[n].Tooltip_title[a],'заглавие')
                    build_menu[n].requirement_met[a]=false
                    
                end
                
                --реим выбора закрыт
                build_menu[n].player_chooses_place = false
				BlzFrameSetEnable(build_menu[n].Mask, false)
                BlzEnableCursor(true)
                
                --двигаем в угол карты
                BlzSetSpecialEffectPosition( build_menu[n].model, GetRectMinX(GetWorldBounds()), GetRectMinY(GetWorldBounds()), 0 )
                --затем уничтожаем
                DestroyEffect(build_menu[n].model)
                local block = 32.
                local size = build_menu[n].size/2
                local minx,maxx,miny,maxy = -size,size,-size,size

                local x,y = minx,miny+(block/2)
                local num = 1
                for y=miny+(block/2),maxy,block do
                    for x=minx+(block/2),maxx,block do
                        DestroyImage(build_menu[n].image[num])
                        num = num+1
                    end
                end
            else
                --скрываем кнопку отмены
                BlzFrameSetVisible(button_cancel, false)
                --показываем кнопку меню
                BlzFrameSetVisible(button_build_menu, true)
                --скрываем контейнер 
                BlzFrameSetVisible(build_menu[n].conteiner, false)
            end
        end
        
        group_show_range = CreateGroup()
        function UpdatePathingPlayer(cx,cy,size,block,PlaYer)
            local n = GetPlayerId(PlaYer)
            local radius = 800*2
            local minx,maxx,miny,maxy = (cx-size),(cx+size),(cy-size),(cy+size)
            
            local x,y = minx,miny+(block/2)
            local num,count=1,0
            build_menu[n].flag = {}
            
            for y=miny+(block/2),maxy,block do
                for x=minx+(block/2),maxx,block do    
                    --print('move -'..num)
                    SetImagePosition(build_menu[n].image[num],x,y,0) 
                    
                    build_menu[n].image_x[num] = x
                    build_menu[n].image_y[num] = y
                    --проверяем ландшафт
                    if not IsTerrainPathable(x,y,PATHING_TYPE_BUILDABILITY) then
                        build_menu[n].flag[num] = true
                    else
                        build_menu[n].flag[num] = false
                    end
                    num=num+1
                end
            end
            print('count: '..num)

            local flag = true
            --проверяем декорации
            EnumDestructablesInRect(bj_mapInitialPlayableArea, nil, function()
                
                
                local d = GetEnumDestructable()
                local Type = GetDestructableTypeId(d)
                
                local dx,dy=GetDestructableX(d),GetDestructableY(d)
                --print('кооды:'..dx,dy)
                
                --поиск осуществуется в радиусе от точки cx,cy координат курсора
                --иначе будет лагать, уменьшаем кол-во
                local r = ((dx-cx)^2  + (dy-cy)^2)^0.5
                if r<radius then

                    local size = size_pathing_magenta[Type]/2
                    --print('размер декора:'..size)
                    
                    if IsDestructableAliveBJ(d) then
                        local minx,maxx,miny,maxy=(dx-size),(dx+size),(dy-size),(dy+size)
                    
                        for a=1, num do
                            if build_menu[n].flag[a] then
                                local x,y = build_menu[n].image_x[a],build_menu[n].image_y[a]
                                local bool = (x >= minx) and (x <= maxx) and (y >= miny) and (y <= maxy)
                                if bool then 
                                    build_menu[n].flag[a] = false
                                    --break 
                                end  
                            end
                        end
                    end
                end
            end)

        
            --проверяем юнитов
            GroupClear(group_show_range)
            --GroupEnumUnitsInRect(group_show_range, bj_mapInitialPlayableArea, nil)
            GroupEnumUnitsInRange(group_show_range, cx, cy, radius, nil)
               
            --print('units in group+: '..BlzGroupGetSize(group_show_range))
            ForGroup(group_show_range,function()
                local u = GetEnumUnit()
                if not IsUnitType(u,UNIT_TYPE_DEAD) then
                    local Type = GetUnitTypeId(u)
                    local ux,uy=GetUnitX(u),GetUnitY(u)
                    
                    local size_collision = BlzGetUnitCollisionSize(u)

                    --если юнит является зданием, то проверить на паффинг
                    if IsUnitType(u, UNIT_TYPE_STRUCTURE) then
                        
                           
                        --если юнит является древом, то проверяем
                        --является ли древо ходячим. у ходячих древ отсутствует pathing
                        --а еще уменьшен размер collision в 3 раза
                        if IsUnitType(u, UNIT_TYPE_ANCIENT) and IsUnitEnemy(u, PlaYer) then
                                    
                            --проверить, что древо ходячее можно по типу
                            if GetUnitDefenseType(u)==2 then
                                size_collision = size_collision/3
                                
                                for a=1, num do
                                    if build_menu[n].flag[a] then
                                        local x,y = build_menu[n].image_x[a],build_menu[n].image_y[a]
                                        local r = ((ux-x)^2 + (uy-y)^2)^0.5
                                        --если клетка лежит внутри коллижион
                                        if r > size_collision then
                                            build_menu[n].flag[a] = false
                                            --break 
                                        end  
                                    end
                                end
                            end
                        else
                            print('здание')
                            local size = build_size_ground_pathing[Type]/2
                            local minx,maxx,miny,maxy=(ux-size),(ux+size),(uy-size),(uy+size)
                            for a=1, num do
                                if build_menu[n].flag[a] then
                                    local x,y = build_menu[n].image_x[a],build_menu[n].image_y[a]
                                    local bool = (x >= minx) and (x <= maxx) and (y >= miny) and (y <= maxy)
                                    if bool then 
                                        build_menu[n].flag[a] = false
                                        --break 
                                    end  
                                end
                            end
                        end
                    else			
                        if IsUnitEnemy(u, PlaYer) then

                            local minx = Real_offset_64(GetUnitRealX(u)-size_collision)
                            local maxx = Real_offset_64(GetUnitRealX(u)+size_collision)
                            local miny = Real_offset_64(GetUnitRealY(u)-size_collision)
                            local maxy = Real_offset_64(GetUnitRealY(u)+size_collision)
                            for a=1, num do
                                if build_menu[n].flag[a] then
                                    local x,y = build_menu[n].image_x[a],build_menu[n].image_y[a]
                                    local bool = (x >= minx) and (x <= maxx) and (y >= miny) and (y <= maxy)
                                    if bool then 
                                        build_menu[n].flag[a] = false
                                        --break 
                                    end  
                                end
                            end


                        end
                    end
                end
            end)            
            
--[[ 
            --проверка предметов
            EnumItemsInRect( bj_mapInitialPlayableArea, nil, function()
                local it = GetEnumItem()
                if GetWidgetLife(it)>0 and (not IsItemHiddenBJ(it)) then
                    local ix,iy=GetItemX(it),GetItemY(it)
                    local size = 64.
                    local minx,maxx,miny,maxy=(x-size),(x+size),(y-size),(y+size)
                    for a=1, num do
                        if build_menu[n].flag[a] then
                            local x,y = build_menu[n].image_x[a],build_menu[n].image_y[a]
                            local bool = (ix >= minx) and (ix <= maxx) and (iy >= miny) and (iy <= maxy)
                            if bool then 
                                build_menu[n].flag[a] = false
                               --break 
                            end  
                        end
                    end
                end
            end)
        ]] 
            local count = 0 
            for a=1, num-1 do
                if build_menu[n].flag[a] then
                    SetImageColor(build_menu[n].image[a], 0, 255, 0, 80)
                else
                    SetImageColor(build_menu[n].image[a], 255, 0, 0, 80)
                    count = count + 1
                end
            end 
            
            
            if count>0  then
                build_menu[n].can_build=false
                --print('не может строить')
            else
                build_menu[n].can_build=true
                --print('может строить')
            end
        end
    
    
    --========== триггеры фреймов ====================
    
        --триггер фиксирует заход курсора мыши в фрейм-маску (помогает скрывать/отображать курсор)
            local trigger_mask_enter=CreateTrigger()
            BlzTriggerRegisterFrameEvent(trigger_mask_enter, build_menu[n].Mask, FRAMEEVENT_MOUSE_ENTER)
            TriggerAddAction(trigger_mask_enter,function()
                local n = GetPlayerId(GetTriggerPlayer())
                build_menu[n].mask_cursor_mouse_in_frame=TRUE
            end)
        --триггер фиксирует покидание курсора мыши из фрейм-маски (помогает скрывать/отображать курсор)
            local trigger_mask_leave=CreateTrigger()
            BlzTriggerRegisterFrameEvent(trigger_mask_leave, build_menu[n].Mask, FRAMEEVENT_MOUSE_LEAVE)
            TriggerAddAction(trigger_mask_leave,function()
                local n = GetPlayerId(GetTriggerPlayer())
                build_menu[n].mask_cursor_mouse_in_frame=false
            end)
        --для кнопок контейнера задаем события

            for num=1, #build_menu[n].button do 
        
                build_menu[n].Trigger_click[num]=CreateTrigger()
                BlzTriggerRegisterFrameEvent(build_menu[n].Trigger_click[num], build_menu[n].button[num], FRAMEEVENT_MOUSE_UP)
                TriggerAddAction(build_menu[n].Trigger_click[num],function()
                    local n = GetPlayerId(GetTriggerPlayer())
                    for a=1,#build_menu[n].button do
                        if BlzGetTriggerFrame()==build_menu[n].button[a] then --GetTriggeringTrigger
                            print('click button-'..tostring(a))
                            
                            if build_menu[n].requirement_met[a] then
                                print('требования выполнены')
                
                                local Type_Building = build_menu[n].Building_Id[a]
                                
                                local gold,lumber,food,mana =0,0,0,0
                                if Type_Building>0 then

                                    if build_gold_cost[Type_Building]then
                                        if build_gold_cost[Type_Building]> 0 then
                                            gold=build_gold_cost[Type_Building]
                                        end
                                    end
                                    if build_lumb_cost[Type_Building]then
                                        if build_lumb_cost[Type_Building]> 0 then
                                            lumber=build_lumb_cost[Type_Building]
                                        end
                                    end 
                                    if build_food_cost[Type_Building]then
                                        if build_food_cost[Type_Building]> 0 then
                                            food=build_food_cost[Type_Building]
                                        end
                                    end 
                                    if build_mana_cost[Type_Building]then
                                        if build_mana_cost[Type_Building]> 0 then
                                            mana=build_mana_cost[Type_Building]
                                        end
                                    end 
                                    local flag = true
                                    if (gold>GetPlayerState(GetTriggerPlayer(), PLAYER_STATE_RESOURCE_GOLD) and lumber>GetPlayerState(GetTriggerPlayer(), PLAYER_STATE_RESOURCE_LUMBER)) or gold>GetPlayerState(GetTriggerPlayer(), PLAYER_STATE_RESOURCE_GOLD)  then
                                        DisplayTimedTextToPlayer(GetTriggerPlayer(), 0.3, 0.21, 0.3, "|Cffffcc00Недостаточно золото|r")
                                        flag = false
                                    elseif lumber>GetPlayerState(GetTriggerPlayer(), PLAYER_STATE_RESOURCE_LUMBER) then
                                        DisplayTimedTextToPlayer(GetTriggerPlayer(), 0.3, 0.21, 0.3, "|Cffffcc00Недостаточно древесины|r")
                                        flag = false
                                    end
                                    if flag then
                                        --показываем кнопку отмены
                                        BlzFrameSetVisible(button_cancel, true)
                                        --скрываем кнопку меню
                                        BlzFrameSetVisible(button_build_menu, false)
                                        --скрываем контейнер 
                                        BlzFrameSetVisible(build_menu[n].conteiner, false)
                                        --меню раба закрыто
                                        build_menu[n].display_menu_builder = false
                                        --игрок выбирает участок
                                        build_menu[n].player_chooses_place = true
                                        BlzFrameSetEnable(build_menu[n].Mask, true)
                                        
                                        for b=1, 12 do
                                            build_menu[n].Building_Id[b]=0
                                            BlzFrameSetTexture(build_menu[n].IconTexture[b], path_icon, 0, true)
                                            BlzFrameSetText(build_menu[n].Tooltip_Text[b],'описание')
                                            BlzFrameSetText(build_menu[n].Tooltip_title[b],'заглавие')
                                        end
                                        
                                        local path_effect = GetTriggerPlayer()==GetLocalPlayer() and build_model[Type_Building] or nil
                                        
                                        build_menu[n].id=Type_Building
                                        build_menu[n].model=AddSpecialEffect(path_effect,0,0)
                                        BlzPlaySpecialEffect(build_menu[n].model,ANIM_TYPE_STAND)
                                        BlzSetSpecialEffectYaw(build_menu[n].model, math.rad(270))
                                        BlzSetSpecialEffectColorByPlayer( build_menu[n].model,GetOwningPlayer(LastSelestedUnit[n]))
                                        
                                        build_menu[n].size=build_size_ground_pathing[Type_Building]
                                        build_menu[n].can_build=false
                                            
                                        local block = 32.
                                        local size = build_menu[n].size/2
                                        local minx,maxx,miny,maxy = -size,size,-size,size

                                        local x,y = minx,miny+(block/2)
                                        local num = 1
                                        for y=miny+(block/2),maxy,block do
                                            for x=minx+(block/2),maxx,block do
                                                build_menu[n].image[num]=CreateSquareImageForPlayer(GetTriggerPlayer(),"war3mapImported\\block 32x32.TGA",block*2,x,y,2)
                                                num = num+1
                                            end
                                        end
                                        UpdatePathingPlayer(x,y,size,block,GetTriggerPlayer())
                                        
                                    end
                                
                                end
                            end
                        end
                    end
                   
                end)
            end

        --триггер фиксирует вход курсора мыши в кнопку "отмена" (помогает отслеживать клик в триггере trigger_button_cancel_click)
            local trigger_button_cancel_enter=CreateTrigger()
            BlzTriggerRegisterFrameEvent(trigger_button_cancel_enter, button_cancel, FRAMEEVENT_MOUSE_ENTER)
            TriggerAddAction(trigger_button_cancel_enter,function()
                local n = GetPlayerId(GetTriggerPlayer())
                build_menu[n].button_cancel_cursor_mouse_in_frame=TRUE
            end)
        --триггер фиксирует покидание курсора мыши из кнопки "отмена" (помогает отслеживать клик в триггере trigger_button_cancel_click)
            local trigger_button_cancel_leave=CreateTrigger()
            BlzTriggerRegisterFrameEvent(trigger_button_cancel_leave, button_cancel, FRAMEEVENT_MOUSE_LEAVE)
            TriggerAddAction(trigger_button_cancel_leave,function()
                local n = GetPlayerId(GetTriggerPlayer())
                build_menu[n].button_cancel_cursor_mouse_in_frame=false
            end)
        --триггер фиксирует отмену
            local trigger_button_cancel_click=CreateTrigger()
            BlzTriggerRegisterFrameEvent(trigger_button_cancel_click, button_cancel, FRAMEEVENT_MOUSE_UP)
            TriggerRegisterPlayerEvent(trigger_button_cancel_click, Player(0), EVENT_PLAYER_MOUSE_UP )
            TriggerRegisterPlayerEvent(trigger_button_cancel_click, Player(0), EVENT_PLAYER_END_CINEMATIC )

            TriggerAddAction(trigger_button_cancel_click,function()
                local n = GetPlayerId(GetTriggerPlayer())
                
                
                local b1 = GetTriggerEventId() == EVENT_PLAYER_END_CINEMATIC
                local b2 = GetTriggerEventId() == EVENT_PLAYER_MOUSE_UP and BlzGetTriggerPlayerMouseButton()==MOUSE_BUTTON_TYPE_LEFT and  build_menu[n].button_cancel_cursor_mouse_in_frame
                local b3 = GetTriggerEventId() == EVENT_PLAYER_MOUSE_UP and BlzGetTriggerPlayerMouseButton()==MOUSE_BUTTON_TYPE_RIGHT and  build_menu[n].player_chooses_place
                
                if b1 or b2 or b3 then
                    print('click button "cancel"')
                    BuildMenu_Cancel(n)
                end
            end)
        --триггер фиксирует вход курсора мыши в кнопку "меню строительства" (помогает отслеживать клик в триггере trigger_button_build_menu_click)
            local trigger_button_build_menu_enter=CreateTrigger()
            BlzTriggerRegisterFrameEvent(trigger_button_build_menu_enter, button_build_menu, FRAMEEVENT_MOUSE_ENTER)
            TriggerAddAction(trigger_button_build_menu_enter,function()
                local n = GetPlayerId(GetTriggerPlayer())
                build_menu[n].button_menu_builder_cursor_mouse_in_frame=TRUE
            end)
        --триггер фиксирует покидание курсора мыши из кнопки "меню строительства" (помогает отслеживать клик в триггере trigger_button_build_menu_click)
            local trigger_button_build_menu_leave=CreateTrigger()
            BlzTriggerRegisterFrameEvent(trigger_button_build_menu_leave, button_build_menu, FRAMEEVENT_MOUSE_LEAVE)
            TriggerAddAction(trigger_button_build_menu_leave,function()
                local n = GetPlayerId(GetTriggerPlayer())
                build_menu[n].button_menu_builder_cursor_mouse_in_frame=false
            end)
    
        --триггер фиксирует нажатие на кнопку "меню строительства"
            local trigger_button_build_menu_click=CreateTrigger()
            --BlzTriggerRegisterFrameEvent(trigger_button_build_menu_click, button_build_menu, FRAMEEVENT_MOUSE_UP)
            TriggerRegisterPlayerEvent(trigger_button_build_menu_click, Player(0), EVENT_PLAYER_MOUSE_UP )
            TriggerAddAction(trigger_button_build_menu_click,function()
                local n = GetPlayerId(GetTriggerPlayer())
                
                if build_menu[n].button_menu_builder_cursor_mouse_in_frame then
                    if BlzGetTriggerPlayerMouseButton()==MOUSE_BUTTON_TYPE_LEFT  then
                        print('click button "build menu"')
                        
                        --показываем кнопку отмены
                        BlzFrameSetVisible(button_cancel, true)
                        --скрываем кнопку меню
                        BlzFrameSetVisible(button_build_menu, false)
                        --показываем контейнер 
                        BlzFrameSetVisible(build_menu[n].conteiner, true)
                        --скрываем последнюю кнопку
                        BlzFrameSetVisible(build_menu[n].button[12], false)
                        
                        build_menu[n].display_menu_builder = true
                        
                        
                        --тип раба-строителя
                        local Type_builder = GetUnitTypeId(LastSelestedUnit[n])
                        if Type_builder==FourCC('hpea') or Type_builder==FourCC('opeo') then
                        
                            local num = 1
                            for a=1, #list_builder[Type_builder] do
                                --тип постройки
                                local Type_building = FourCC(list_builder[Type_builder][a])
                                --записываем тип здания в ячейку
                                build_menu[n].Building_Id[num]=Type_building
                                
                                BlzFrameSetText(build_menu[n].Tooltip_title[num],build_text_tip[Type_building]..' (|cffffcc00'..build_text_hotkey[Type_building]..'|r)')
                                BlzFrameSetText(build_menu[n].Tooltip_Text[num],build_text_ubertip[Type_building])

                                update_Tooltip_for_menu_builder(num, GetTriggerPlayer())
                                num = num + 1
                            end
                        end
                    end
                end

            end)
        --фиксирует изменение выбора игрока
            --инициируем глобалки (помогают отслеживать изменение выбора игрока)
            NewSelestedUnit = {} 
            LastSelestedUnit = {}
            --таймер чекает интерфейс и группу выделенных игроком юнитов
            TimerStart(CreateTimer(), 1/32, true, function()
                SelectedUnit()
            end)

    
            function SelectedUnit()
                local n = GetPlayerId(GetLocalPlayer())
                local index = GetSelectedUnitIndex()
                local u = GetMainSelectedUnit(index)
                
                NewSelestedUnit[n] = u

                --если юнит живой и существует
                if not ( GetUnitTypeId (u) == 0 or IsUnitType (u, UNIT_TYPE_DEAD)) then

                        
                    --если юнит новый, обновляем инфу
                    if LastSelestedUnit[n] ~= NewSelestedUnit[n] then 
                        
                        
                        if IsUnitType(u, UNIT_TYPE_HERO) then
                            if index then
                                print("|cffff00ffвыбран "..GetUnitName(u)..' '..GetHeroProperName(u)..', index group:|r '..tostring(index))
                            else
                                print("|cffff00ffвыделен "..GetUnitName(u)..' '..GetHeroProperName(u)..'|r')
                            end
                        else
                            if index then
                                print("|cffff00ffвыбран "..GetUnitName(u)..', index group:|r '..tostring(index))
                            else
                                print("|cffff00ffвыделен "..GetUnitName(u)..' '..GetHeroProperName(u)..'|r')
                            end
                        end

                        LastSelestedUnit[n] = NewSelestedUnit[n]  
                        
                        if GetUnitTypeId (u)==FourCC('hpea') then
                                
                            --закрываем меню
                            BuildMenu_Cancel(n)
                            --если выбран рабочий хуманов, показываем меню
                            BlzFrameSetVisible(build_menu[n].interface, true)
                            --сменить иконку на хуманскую
                            BlzFrameSetTexture(icon_button_build_menu, path_icon_human_build, 0, true)

                            
                        elseif GetUnitTypeId (u)==FourCC('opeo') then
                            
                            --закрываем меню
                            BuildMenu_Cancel(n)
                            --если выбран пеон орков, показываем меню
                            BlzFrameSetVisible(build_menu[n].interface, true)
                            --сменить иконку на орочью
                            BlzFrameSetTexture(icon_button_build_menu, path_icon_orc_build, 0, true)
                                
                        else
                            --если выбран не рабочий-строитель, а какой-то обычный юнит или герой
                        
                            --закрываем меню
                            BuildMenu_Cancel(n)
                            --иначе, если выбран новый юнит, которыйф не является рабочим
                            --если выбран не рабочий, меню скрываем
                            BlzFrameSetVisible(build_menu[n].interface, false)
                            --скрываем кнопку меню
                            BlzFrameSetVisible(button_build_menu, false)
                        end 
                    end

                else
                    --если юнит мертв или не существует (возможна выделена декорация или итем)
                    
                    --закрываем меню
                    BuildMenu_Cancel(n)
                    --иначе, если выбран новый юнит, которыйф не является рабочим
                    --если выбран не рабочий, меню скрываем
                    BlzFrameSetVisible(build_menu[n].interface, false)
                    --скрываем кнопку меню
                    BlzFrameSetVisible(button_build_menu, false)
                end
            end
        
        --триггер фиксирует изменения на поле боя
            --если здание удалилось/сменило владельца/заново построено
            --фиксирует исчезновение, появление юнита, и заносит изменение в подсказку фрейма
            --здания, которые не достроены, не учитываются
            local trigger_update = CreateTrigger()
            TriggerRegisterAnyUnitEventBJ( trigger_update, EVENT_PLAYER_UNIT_CONSTRUCT_FINISH )
            TriggerRegisterAnyUnitEventBJ( trigger_update, EVENT_PLAYER_UNIT_DEATH )
            TriggerRegisterAnyUnitEventBJ( trigger_update, EVENT_PLAYER_UNIT_CHANGE_OWNER )
            TriggerRegisterAnyUnitEventBJ( trigger_update, EVENT_PLAYER_UNIT_UPGRADE_FINISH )
            TriggerRegisterAnyUnitEventBJ( trigger_update, EVENT_PLAYER_UNIT_RESEARCH_FINISH )
            TriggerAddAction( trigger_update, function()
               
                local n = GetPlayerId(GetTriggerPlayer())
            
                --print('фиксируем изменения +')

                if build_menu[n].display_menu_builder then
                    TimerStart(CreateTimer(),0.03,false,function()
                
                        --тип раба-строителя
                        local Type_builder = GetUnitTypeId(LastSelestedUnit[n])
                        if Type_builder==FourCC('hpea') or Type_builder==FourCC('opeo') then
                    
                            local num = 1
                            for a=1, #list_builder[Type_builder] do
                                --тип постройки
                                local Type_building = FourCC(list_builder[Type_builder][a])

                                --записываем тип здания в ячейку
                                build_menu[n].Building_Id[num]=Type_building
                                
                                BlzFrameSetText(build_menu[n].Tooltip_title[num],build_text_tip[Type_building]..' (|cffffcc00'..build_text_hotkey[Type_building]..'|r)')
                                BlzFrameSetText(build_menu[n].Tooltip_Text[num],build_text_ubertip[Type_building])

                                update_Tooltip_for_menu_builder(num, Player(n))
                                num = num + 1
                            end
                        end
                        DestroyTimer(GetExpiredTimer())
                    end)
                end
            end)
    
  end
end

--почему-то только в InitGlobals норм таймер работает
do 
	local InitGlobalsOrigin = InitGlobals
	function InitGlobals()
		InitGlobalsOrigin()

        --группа здании, которые строятся. отсеивает достроенные здания от построенных
        local group_construct = CreateGroup()

        --триггер фиксирует начало строительства здания (отсеивает построенные здания от недостроенных)
        local start_construction = CreateTrigger()
        TriggerRegisterAnyUnitEventBJ( start_construction, EVENT_PLAYER_UNIT_CONSTRUCT_START )
        TriggerRegisterAnyUnitEventBJ( start_construction, EVENT_PLAYER_UNIT_UPGRADE_START )
        TriggerAddAction( start_construction, function()
            GroupAddUnit(group_construct, GetTriggerUnit())
        end)
        --триггер фиксирует завершение строительства здания (отсеивает построенные здания от недостроенных)
        local end_construction = CreateTrigger()
        TriggerRegisterAnyUnitEventBJ( end_construction, EVENT_PLAYER_UNIT_CONSTRUCT_FINISH )
        TriggerRegisterAnyUnitEventBJ( end_construction, EVENT_PLAYER_UNIT_CONSTRUCT_CANCEL )
        TriggerRegisterAnyUnitEventBJ( end_construction, EVENT_PLAYER_UNIT_UPGRADE_CANCEL )
        TriggerRegisterAnyUnitEventBJ( end_construction, EVENT_PLAYER_UNIT_UPGRADE_FINISH )
        TriggerRegisterAnyUnitEventBJ( end_construction, EVENT_PLAYER_UNIT_DEATH )
        TriggerAddAction( end_construction, function()
            GroupRemoveUnit(group_construct, GetTriggerUnit())
        end)

        function BlzCountLivingPlayerUnitsOfTypeId(unitId, whichPlayer)
            local g = CreateGroup()
            GroupEnumUnitsOfPlayer(g, whichPlayer, Condition(function()
            return GetUnitTypeId(GetFilterUnit())==unitId and (not IsUnitType( GetFilterUnit(), UNIT_TYPE_DEAD )) and (not IsUnitInGroup(GetFilterUnit(),group_construct))
            end))
            local Count = BlzGroupGetSize(g)
            DestroyGroup(g)

            return Count
        end
        
        

        
        TimerStart(CreateTimer(),0.00,false,function()
            print('init trigger_mouse_move')
            tr_mouse_move = CreateTrigger()
            TriggerRegisterPlayerEvent(tr_mouse_move, Player(0), EVENT_PLAYER_MOUSE_MOVE )
            TriggerAddAction(tr_mouse_move, function()
                
                
                local n = GetPlayerId(GetTriggerPlayer())
                --print(GetPlayerName(GetTriggerPlayer()))
                
                if build_menu[n].player_chooses_place then
                    --print(BlzGetTriggerPlayerMouseX(),BlzGetTriggerPlayerMouseY())
                
                    if build_menu[n].mask_cursor_mouse_in_frame then
                        BlzEnableCursor(false)
                    else
                        BlzEnableCursor(true)
                    end
                    
                    
                    local block = 32

                    local size = build_menu[n].size/2
                    local x = Real_offset_64(BlzGetTriggerPlayerMouseX()) 
                    local y = Real_offset_64(BlzGetTriggerPlayerMouseY()) 
                    --local Z = Real_offset_64(GetLocationZ(loc))
                    
                    if x<0 then
                        x=x+64.
                    end
                    if y<0 then
                        y=y+64.
                    end
                    build_menu[n].coord_x = x
                    build_menu[n].coord_y = y
                    BlzSetSpecialEffectPosition(build_menu[n].model, x, y,0)
                    UpdatePathingPlayer(x,y,size,block,GetTriggerPlayer())
                
                end
            end)

            tr_mouse_click = CreateTrigger()
            TriggerRegisterPlayerEvent(tr_mouse_click, Player(0), EVENT_PLAYER_MOUSE_DOWN )
            TriggerAddAction(tr_mouse_click, function()
                local n = GetPlayerId(GetTriggerPlayer())    
                  
                if MOUSE_BUTTON_TYPE_LEFT ==BlzGetTriggerPlayerMouseButton() then
                  
                    if build_menu[n].player_chooses_place then --если игрок выбирает место строительства
                        
						if build_menu[n].can_build then
                        
                        
                            local Type_Building = build_menu[n].id
                                
                            local gold,lumber,food,mana =0,0,0,0
                            if Type_Building>0 then

								if build_gold_cost[Type_Building]then
									if build_gold_cost[Type_Building]> 0 then
										gold=build_gold_cost[Type_Building]
									end
								end
								if build_lumb_cost[Type_Building]then
									if build_lumb_cost[Type_Building]> 0 then
										lumber=build_lumb_cost[Type_Building]
									end
								end 
								if build_food_cost[Type_Building]then
									if build_food_cost[Type_Building]> 0 then
										food=build_food_cost[Type_Building]
									end
								end 
								if build_mana_cost[Type_Building]then
									if build_mana_cost[Type_Building]> 0 then
										mana=build_mana_cost[Type_Building]
									end
								end 
								local flag = true
								if (gold>GetPlayerState(GetTriggerPlayer(), PLAYER_STATE_RESOURCE_GOLD) and lumber>GetPlayerState(GetTriggerPlayer(), PLAYER_STATE_RESOURCE_LUMBER)) or gold>GetPlayerState(GetTriggerPlayer(), PLAYER_STATE_RESOURCE_GOLD)  then
									DisplayTimedTextToPlayer(GetTriggerPlayer(), 0.3, 0.21, 0.3, "|Cffffcc00Недостаточно золото|r")
									flag = false
								elseif lumber>GetPlayerState(GetTriggerPlayer(), PLAYER_STATE_RESOURCE_LUMBER) then
									DisplayTimedTextToPlayer(GetTriggerPlayer(), 0.3, 0.21, 0.3, "|Cffffcc00Недостаточно древесины|r")
									flag = false
								end
                            
								if flag then
                                    --закрываем меню
									BuildMenu_Cancel(n)
									IssueBuildOrderById(LastSelestedUnit[n],Type_Building,build_menu[n].coord_x,build_menu[n].coord_y)

								end
							end
							
							
                        else
                            DisplayTimedTextToPlayer(GetTriggerPlayer(), 0.3, 0.21, 0.3, "|Cffffcc00Вы не можете здесь строить|r")
                        end
                     
                    end --+
                end
            end)
            DestroyTimer(GetExpiredTimer())

        end)
    end
end

Обновление до 0.02v

Произошло крупное обновление системы.
  • Был исправлен баг при сэйв/лоад. При загрузке вылетала игра из-за фреймов. Обычное дело, просто еще тогда не добавил. Еще надо потестить на десинхи
  • добавлены горячие клавиши (hotkey) в меню для здании. теперь можно выбирать не только по нажатию лкм фрейма.
  • проработаны кнопки нажатия только по лкм. иначе ранее активировать можно было не только лкм, но и пкм. Такое случается с типами фрейма: слайдер, текст
  • проработана отмена. Отменять можно не только кликом по кнопке отмена, но и кнопкой Esc, или пкм.
  • Добавлена и доработана карта путей для юнитов, итемов. Для остального декорации и здании нужно забивать бд размеров паффинга. Также старался учесть механику игры, когда подконтрольные игроку юниты освобождали место для строительства, если они конечно могут это сделать. Для неподвижных и застаненных итд (требуется доработка функции)
  • Добавлена возможность строить на воде. Можно для здании в требовании добавлять различные виды паффинга для строительства. а не только buildable. Есть разные типы, конечно, я еще не до конца проработал на флагами: сейчас в требовании доступно только buildable, walk. Остальное не прописано в коде, и придеться вручную картоделу вносить правку - моя недоработка
  • Добавлена возможность строить на порче. Аналогично с требованием строительства, есть еще пункт на запрет строительства в определенном месте. здесь учет идет на запрет строить в определенном месте - строить не на порче. ТАкже есть недоработка в не универсальности системы, картоделу придеться вносить правки лично. Учитывается запрет стройки unblight (не порча) на buildable.
  • добавлено требование на строительства около воды - радиус. пример, в варкрафте это верфи
  • Учтен радиус строительства между ратушей и золотой шахтой

требование построить здание

в меню иногда будет отключены некоторые здания. Требуется построить необходимые здания, и только тогда становятся доступными здания в списке

карта путей для юнитов, итемов

пришлось высчитывать карту путей. ранее я изучал коллижион, и относительного точки юнита пришлось центровку делать для коллижион. Здесь немного по-другому, мне пришлось мистическим способом сравнения подбирать размеры
код
не секрет, что самая минимальная клетка в игре 32x32, т.е. мин размер сетки 32. меньше бесполезно делать. наша выборочная площадка строительства состоит из таких квадратиков. Когда в точке нельзя строить, она отображается красным, иначе зеленым.
для юнитов пришлось много мучеении сделать:
  • коллижион 1-15 необходимо сместить x+16,y+16, клетка принимает размеры 32x32
  • коллижион 16-31 смещение x,y делать не нужно, клетка принимает размеры 64x64
  • коллижион 32-47 необходимо сместить x+16,y+16, клетка принимает размеры 96x96
  • коллижион 48-63 смещение x,y делать не нужно, клетка принимает размеры 96x96
  • коллижион больше 64 смещение x,y делать не нужно, клетка принимает размеры 128x128, больше чем 128 не видел. только у здании. но здания используют карты путей
для здании и декорации неиспользуется карта путей, необходимо забивать бд размеров всех здании и декорации, что будут у вас на карте. В том числе и блокираторы путей итд.
для итемов. С итемами было проще всего. У них нет коллижиона. Но занимают клетку 32x32. По факту в функцию bordersForCircle указываем радиус = 8 со смещением x+16,y+16. Замечано смещение
			function bordersForCircle(x,y,r,size)

				local minx,maxx,miny,maxy
				
				--радиус коллижиона = 1..15 нет смещения, добавляем 
				if r<16 then 
					x=x+16.
					y=y+16.
					r=8.
				--радиус коллижиона = 16..31 есть видимое смещение 
				elseif r<32 then
					r=16.
				--радиус коллижиона = 32..47 нет смещения, добавляем  
				elseif r<48 then 
					x=x+16.
					y=y+16.
					r=24.
				end
					

				local R = r%%size
				local count = math.modf(r/size)
				
				R = R*2 + count*size
					
				minx,maxx,miny,maxy = x-R,x+R,y-R,y+R

				minx=math.floor(minx/size)*size
				miny=math.floor(miny/size)*size
				maxx=math.floor(maxx/size)*size
				maxy=math.floor(maxy/size)*size

				return minx,maxx,miny,maxy
			end

Подконтрольные юниты освобождают место строительства

Юниты сами разбегаются. Исключение, только не подконтрольные юниты, и юниты, которые не могут двигаться.

Строительство на воде

Есть разные паффинги. Есть обычные, а есть и те, которые строятся на мелководье. Пример, наги могут строится на паффинге walk (там где можно ходить: мелководье, земля). Также есть верфи, к ним добавляется требование радиуса воды, нельяз строить дальше от воды

Строительство нежити строго на порче

Здания нежити возводятся строго на порче. В механике вара есть требование строить в определенном месте. А также есть второй пункт, где запрещено строить в определенном месте - запрещено строить "не на порче"

Строительство ратуш около золотывх шахт

У ратуш есть определенный радиус, где нельзя строиться. Сделано специально для хуманов и орков, чтобы носили золото не так близко.

Планы

Как будет желание, мб сделаю из ниже предложенных:
  • проработка и улучшения кода с флагами в требовании на строительство. Нужно сделать код более универсальным, чтобы картоделу не нужно было лезть под капот, внося правки в код. Достаточно было бд. ВЫПОЛНЕНО
  • необходимо доработать функцию проверки юнита на возможность двигаться. В нее вбил всякие условия на станы, скорость, дебаффы. Но по итогу, она перестала работать. Поэтому я ее исключил временно, тк времени нет с ней возиться было. Щас, система проверяет только скорость передвижения ВЫПОЛНЕНО
  • расположение кнопок по x,y. Кнопки расположены в порядке добавления здании в таблице, и поэтому могут лежать не в таком порядке. Если не указано в бд координаты иконки, то по дефолту принимает x=0, y=0. По идее в ячейку таблицы вносят кнопки. Если у некоторых одинаковые координаты, то ячейку займет кто-то один, а другому придется занять пустую ячейку (если она, конечно, будет доступной). ВЫПОЛНЕНО
  • проработать над золотыми шахтами. К сожалению, у нежити плохо работал проклятый рудник в v 0.02. По факту: проклятый рудник можно строить над рудником, т.е. координаты должны совпадать, иначе, нельзя строить. Короче, тут выделить можно 2 состояние: можно строить (закрашиваем зеленым) или нельзя (закрашиваем красным). Можно оптимизировать: 1 изображение (image) сделать в качестве исключения, вместо тысяч квадратных картинок. В данный момент, устранена ошибка, когда несколько рудников находятся рядом, и перезаписывает данные по последнему. Также исправлен приказ в точку, на приказ в цель. В данный момент, я еще не решился, стоит ли оптимизировать в 1 изображение ВЫПОЛНЕНО 50/50
  • Добавлен поворот здания колесиком. Исправлены все ошибки: когда пиксели при поворотах исчезали. Неверно удалялись пиксели, не все пиксели удалялись из игры. И при проверки при поворотах были неверные Осталось проблема с реализацией строительства ТРЕБУЕТСЯ ДОРАБОТКА
  • Сделать альтернативный список строительства
  • Возможность как-то листать список здании кнопками или скролл-барами итд
  • сделать одну общую динамичную подсказку. Сейчас для каждой кнопки создана своя подсказка с фоном, текстом и пр.
  • механика строительства как в старкрафте 2. Где рабочие строят вокруг около силового энергетического поля пилонов.
  • добавить очередь приказов из 1.33 патча. Там добавлены нативки на очередь приказов, теперь через shift возможно будет можно задать (но это не точно) После того как выйдет официальный патч, и как это будет работать
  • возможна нужна какая то оптимизация выбора. Число Images сократить, циклы. В последнюю очередь сделать, после реализации всех идеи
  • проверить на десинхи В последнюю очередь проверить
  • швы между images можно устранить, просто изменив размеры. Но пока это я оставлю, для тестов полезна видеть В последнюю очередь проверить
Внимание: после выхода патча 1.33 работа триггеров может быть поломана. События наведения сломаны, входа или входа курсора мыши работают уже не так. Ивент Leave вроде не работает. Ивент Enter периодически каждую сек отображает находится ли курсор внутри. Либо ждать, когда близзард переделают, или самим переделать

Содержание
`
ОЖИДАНИЕ РЕКЛАМЫ...
0
27
2 года назад
0
Последние новости!
Подстатья готова
0
33
2 года назад
Отредактирован PUVer
0
Ах вот зачем ты занимался изучением путей проходимости! Ай да мерзопакостный джентльмен! Джассовое строительство. А чего добился ты в 2022?

Тебе надо какой-нибудь проект крутой делать со всем этим потенциалом)
0
27
2 года назад
0
я ту карту путей так и не доделал. она оч сложная ... в моих задумках.. BonusMode лежит..

учтите, в будущем патче 1.33 добавлена очередь приказов. мб добавить это через отслеживание Shift
1
26
2 года назад
1
Я, кстати, тоже столкнулся с такой фигней как отклонение координат. Именно при перемещении здания. Приходилось увеличивать шаг перемещения, если текущая координата была меньше (0.0). Так и не понял почему такая ерунда возникает, но мне хватило 4 условий (при х<0, x>0, y<0 и y>0), чтобы решить эту проблему в моем случае.
1
27
2 года назад
1
Вышла новая версия!
Вышла версия 0.02
Чтобы оставить комментарий, пожалуйста, войдите на сайт.