Moveable Frame – система для перемещения фреймов мышью
Что это?  
Moveable Frame – это система, которая позволяет "хватать" и перемещать фреймы интерфейса вслед за курсором мыши.
Moveable Frame – это система, которая позволяет "хватать" и перемещать фреймы интерфейса вслед за курсором мыши.
В чём проблема?  
Игра не предоставляет прямого доступа к экранным координатам мыши – только к игровым (те, что на карте). Без точного позиционирования курсора на экране плавное перемещение фреймов невозможно.
Игра не предоставляет прямого доступа к экранным координатам мыши – только к игровым (те, что на карте). Без точного позиционирования курсора на экране плавное перемещение фреймов невозможно.
Решение:  
Используются невидимые "пустые" фреймы размером 0.01x0.01, покрывающие весь экран сеткой. Когда мышь движется, система определяет, над каким из этих микро-фреймов находится курсор, и обновляет позицию перетаскиваемого фрейма.  
Используются система мировых координат World2Screen, которая работает гораздо лучше сетки
Используются система мировых координат World2Screen, которая работает гораздо лучше сетки
World2Screen
library World2Screen
globals
real ScreenX = 0
real ScreenY = 0
endglobals
globals
real ScreenX = 0
real ScreenY = 0
endglobals
function World2Screen takes real x, real y, real z returns nothing
local real angleOfAttack = -GetCameraField(CAMERA_FIELD_ANGLE_OF_ATTACK)
local real fieldOfView = GetCameraField(CAMERA_FIELD_FIELD_OF_VIEW)
local real rotation = GetCameraField(CAMERA_FIELD_ROTATION) + bj_PI
local real angleOfAttack = -GetCameraField(CAMERA_FIELD_ANGLE_OF_ATTACK)
local real fieldOfView = GetCameraField(CAMERA_FIELD_FIELD_OF_VIEW)
local real rotation = GetCameraField(CAMERA_FIELD_ROTATION) + bj_PI
    local real cosAttack = Cos(angleOfAttack)
local real sinAttack = Sin(angleOfAttack)
local real cosRot = Cos(rotation)
local real sinRot = Sin(rotation)
local real sinAttack = Sin(angleOfAttack)
local real cosRot = Cos(rotation)
local real sinRot = Sin(rotation)
    local real M11 = cosAttack*cosRot
local real M12 = cosAttack*sinRot
local real M13 = sinAttack
local real M21 = -sinRot
local real M22 = cosRot
local real M23 = 0
local real M31 = -cosRot*sinAttack
local real M32 = -sinAttack*sinRot
local real M33 = cosAttack
local real M12 = cosAttack*sinRot
local real M13 = sinAttack
local real M21 = -sinRot
local real M22 = cosRot
local real M23 = 0
local real M31 = -cosRot*sinAttack
local real M32 = -sinAttack*sinRot
local real M33 = cosAttack
    local real dx = x - GetCameraEyePositionX()
local real dy = y - GetCameraEyePositionY()
local real dz = z - GetCameraEyePositionZ()
local real dy = y - GetCameraEyePositionY()
local real dz = z - GetCameraEyePositionZ()
    local real xPrime = M11*dx + M12*dy + M13*dz
local real yPrime = M21*dx + M22*dy + M23*dz
local real zPrime = M31*dx + M32*dy + M33*dz
local real yPrime = M21*dx + M22*dy + M23*dz
local real zPrime = M31*dx + M32*dy + M33*dz
    local real scaling = 1.04 / ( 2 * Tan(fieldOfView / 2) )
    set ScreenX = 0.4 - (scaling * yPrime) / xPrime
set ScreenY = 0.355 - (scaling * zPrime) / xPrime
endfunction
endlibrary
set ScreenY = 0.355 - (scaling * zPrime) / xPrime
endfunction
endlibrary
Из нового в переписанной версии с Lua на vJass:
- Расширенные границы – фреймы можно перемещать *за пределы стандартной зоны 0.0–0.8*.
 
Проблема с оптимизацией решена
- Теперь система создает всего 106 хэндлов
 
Невозможно сделать движение фрейма с мышкой 1к1, потому что событие Mouse Move срабатывает примерно не чаще чем  раз в 0.15 сек
✅ Два режима перемещения:
🔘 Удержание ПКМ – фрейм движется, пока зажата правая кнопка мыши.
🔘 Переключение по клику – первый клик ПКМ активирует движение, второй – сбрасывает.
✅ Плавное завершение анимации – фрейм теперь всегда доходит до конечной точки, а не останавливается раньше.
✅ Автоматический сброс масштаба – после завершения движения фрейм возвращается к стандартному размеру (scale = 1.0).
То же самое видео, на случай, если видео выше не грузится
Скачать карту:
FrameGrid (Больше не используется)
library FrameGrid  requires MoveAbleFrame
struct structFrame
    framehandle array   GridFrames[4800]
    framehandle array   GridFrames2[4800]
    integer             LastFrame = 0
    timer               Timer  
    real                FramesEachCol
    hashtable Coords 
    integer             index = 0
    
    method setFrameCoords takes framehandle frame, real x, real y returns nothing
        call SaveReal(Coords, GetHandleId(frame), 0, x)
        call SaveReal(Coords, GetHandleId(frame), 1, y)
    endmethod
    
    method GetFrameCoordsX takes framehandle frame returns real
        return LoadReal(Coords, GetHandleId(frame), 0)
    endmethod
    
    method GetFrameCoordsY takes framehandle frame returns real
        return LoadReal(Coords, GetHandleId(frame), 1)
    endmethod
endstruct
globals
    structFrame FrameGrid
    framehandle         Boss = null
endglobals
/*function updateSimple takes nothing returns nothing
local framehandle value
local integer index = 0
    if BlzFrameIsVisible(FrameGrid.Boss) then
    call BJDebugMsg("updateSimple BlzFrameIsVisible")
        loop
            exitwhen index == FrameGrid.LastFrame + 1
            set value = FrameGrid.GridFrames2[index]
            if BlzFrameIsVisible(value) then
                call moveFrame(FrameGrid.GetFrameCoordsX(FrameGrid.GridFrames2[index]),FrameGrid.GetFrameCoordsY(FrameGrid.GridFrames2[index]), true)
                return
            endif
            set index = index + 1
        endloop
    endif
endfunction*/
function update2 takes nothing returns nothing
    local integer yA = FrameGrid.LastFrame 
    local integer yB = FrameGrid.LastFrame
    
    if BlzFrameIsVisible(Boss) then
        loop
        exitwhen (yA < 0 and yB >= 4800)
            if yA >= 0 then
                if BlzFrameIsVisible(FrameGrid.GridFrames2[yA]) then
                    set FrameGrid.LastFrame = yA
                    call BJDebugMsg("update: trying to move " + BlzFrameGetName(FrameGrid.GridFrames2[yA]))
                    call moveFrame(FrameGrid.GetFrameCoordsX(FrameGrid.GridFrames2[yA]),FrameGrid.GetFrameCoordsY(FrameGrid.GridFrames2[yA]), true)
                    return
                endif
                set yA = yA - 1
            endif
            if BlzFrameIsVisible(FrameGrid.GridFrames2[yB]) then
                set FrameGrid.LastFrame = yB
                call BJDebugMsg("update: trying to move" + BlzFrameGetName(FrameGrid.GridFrames2[yB]))
                call moveFrame(FrameGrid.GetFrameCoordsX(FrameGrid.GridFrames2[yB]),FrameGrid.GetFrameCoordsY(FrameGrid.GridFrames2[yB]), true)
                return
            else
                set yB = yB + 1
            endif
        endloop
    endif
endfunction
function HideBossFrame takes nothing returns nothing
    call BlzFrameSetVisible(Boss, false)
endfunction
globals
    framehandle newButton
    framehandle tooltipButton
endglobals
function onGameStart2 takes nothing returns nothing
    local real xSize = 0.01
    local real ySize = 0.01
    local real yStart = ySize/2
    local real xStart = xSize/2
    local real x = -0.134
    local real y
    call PolledWait2(0.01)
    set FrameGrid = structFrame.create()
    set FrameGrid.Coords = InitHashtable()
    set FrameGrid.Timer = CreateTimer()
    call TimerStart(FrameGrid.Timer, 0.01, true, function update2)
    set Boss = BlzCreateFrameByType("BUTTON", "FrameGridBoss", BlzGetFrameByName("ConsoleUIBackdrop", 0),"",0)
    set FrameGrid.FramesEachCol = 0.6 / ySize
    loop
    exitwhen x>0.932
        set y = yStart
        loop
        exitwhen y>=0.6
            set newButton = BlzCreateFrameByType("FRAME", "FRAME" + I2S(FrameGrid.index), Boss,"",0)
            set tooltipButton = BlzCreateFrameByType("FRAME", "FRAME" + I2S(FrameGrid.index), Boss,"",0)
            call BlzFrameSetAbsPoint(newButton, FRAMEPOINT_CENTER, x, y)
            call BlzFrameSetSize(newButton, xSize, ySize)
            call BlzFrameSetTooltip(newButton, tooltipButton)
            call BlzFrameSetEnable(newButton, false)
            call BlzFrameSetEnable(tooltipButton, false)
            
            call FrameGrid.setFrameCoords(newButton,x,y)
            call FrameGrid.setFrameCoords(tooltipButton,x,y)
            set FrameGrid.GridFrames2[FrameGrid.index] = tooltipButton
            set FrameGrid.GridFrames[FrameGrid.index] = newButton
            
            set FrameGrid.index = FrameGrid.index + 1
        set y = y + ySize
        endloop
    set x = x + xSize
    endloop
    call BlzFrameSetVisible(Boss, false)
call onGameStart()
endfunction
endlibrary
CheckBox Setting
globals
    
    //      === Включаем перемещение предметов инвентаря только если зажата ПКМ ===
    boolean RIGHT_MOUSE_BUTTON_FRAME_DRAG_ENABLE = false
    
    //      === Таймер утечный(хотя раньше мне казалось это не вызывало утечек), но доводит фрейм до мышки, если было сильное дерганье или мышка переместилась быстро ===
//        === При true код будет вызывать десинхронизацию, а значит это для одиночной игры ===
    boolean DRAG_TIMER_ENABLE = false
    
    
    constant string DEFAULT_ICON = "ReplaceableTextures\\CommandButtons\\BTNSelectHeroOn"
    constant string BACKGROUND_UNITS = "war3mapImported\\InventoryTexture5Human.tga"
    constant string BACKGROUND_SLOTS = "war3mapImported\\InventoryTexture4.tga"   
    
    
    
endglobals
function CheckBoxDRAG_ENABLE takes nothing returns nothing
    if BlzGetTriggerFrameEvent() == FRAMEEVENT_CHECKBOX_CHECKED then
        set RIGHT_MOUSE_BUTTON_FRAME_DRAG_ENABLE = true
    else
        set RIGHT_MOUSE_BUTTON_FRAME_DRAG_ENABLE = false
    endif
endfunction
function CheckBoxDRAG_ENABLE_TIMER takes nothing returns nothing
    if BlzGetTriggerFrameEvent() == FRAMEEVENT_CHECKBOX_CHECKED then
        set DRAG_TIMER_ENABLE = true
    else
        set DRAG_TIMER_ENABLE = false
    endif
endfunction
function CheckBoxInit takes nothing returns nothing
    local framehandle parent = BlzGetFrameByName("ConsoleUIBackdrop", 0)//BlzGetOriginFrame(ORIGIN_FRAME_GAME_UI, 0)
    local framehandle checkBox = BlzCreateFrame("QuestCheckBox2", parent, 0, 0)
    local framehandle text = BlzCreateFrameByType("TEXT", "", checkBox, "StandardTextTemplate", 0)
    
    local framehandle checkBox2 = BlzCreateFrame("QuestCheckBox2", parent, 0, 0)
    local framehandle text2 = BlzCreateFrameByType("TEXT", "", checkBox2, "StandardTextTemplate", 0)
    
    local trigger t = CreateTrigger()
    local trigger t2 = CreateTrigger()
    
    // Основные настройки чекбокса
    call BlzFrameSetPoint(checkBox, FRAMEPOINT_LEFT, parent, FRAMEPOINT_LEFT, 0.01, 0.3 )
    call BlzFrameSetSize(checkBox, 0.03, 0.03)
    // Настройки текста
    call BlzFrameSetText(text, "Включить режим, |nдвижения только при зажатой правой кнопке")
    call BlzFrameSetPoint(text, FRAMEPOINT_LEFT, checkBox, FRAMEPOINT_RIGHT, 0.01, 0)
    call BlzFrameSetScale(text, 1.2)
    call BlzFrameSetTextAlignment(text, TEXT_JUSTIFY_LEFT, TEXT_JUSTIFY_LEFT) // Выравнивание
    
    
    // Регистрация событий
    call BlzTriggerRegisterFrameEvent(t, checkBox, FRAMEEVENT_CHECKBOX_CHECKED)
    call BlzTriggerRegisterFrameEvent(t, checkBox, FRAMEEVENT_CHECKBOX_UNCHECKED)
    call TriggerAddAction(t, function CheckBoxDRAG_ENABLE)
    call BlzFrameSetPoint(checkBox2, FRAMEPOINT_LEFT, parent, FRAMEPOINT_LEFT, 0.01, 0.3 - 0.05)
    call BlzFrameSetSize(checkBox2, 0.03, 0.03)
    
    call BlzFrameSetText(text2, "Включить таймер, |nдля продолжения движения после клика/отпускания ПКМ")
    call BlzFrameSetPoint(text2, FRAMEPOINT_LEFT, checkBox2, FRAMEPOINT_RIGHT, 0.01, 0)
    call BlzFrameSetScale(text2, 1.2)
    call BlzFrameSetTextAlignment(text2, TEXT_JUSTIFY_LEFT, TEXT_JUSTIFY_LEFT)
    
    call BlzFrameSetLevel(text, 0)
    call BlzFrameSetLevel(text2, 0)
    call BlzTriggerRegisterFrameEvent(t2, checkBox2, FRAMEEVENT_CHECKBOX_CHECKED)
    call BlzTriggerRegisterFrameEvent(t2, checkBox2, FRAMEEVENT_CHECKBOX_UNCHECKED)
    call TriggerAddAction(t2, function CheckBoxDRAG_ENABLE_TIMER)
endfunction
MoveAbleFrame (Основной)
library MoveAbleFrame initializer onTriggerInit requires World2Screen
globals
    real targetX = 0.0
    real targetY = 0.0
    real currentX = 0.0
    real currentY = 0.0
    real moveSpeed = 0.01 // от 0 до 1: выше — быстрее, ниже — плавнее
    real prevTargetX = 0.0
    real prevTargetY = 0.0
    real deltaX = 0.0
    real deltaY = 0.0
    boolean wasMoving // Флаг для того, чтоб сделать фрейм размером 1 после догонки
    boolean PolledMoving = false// Флаг для того, чтоб сделать фрейм размером 1 после догонки
endglobals
struct structMoveAbleFrame
    boolean         Enabled = true
    
    framehandle     Frame = null
    framehandle     PlayerHoveredFrame
    framepointtype  FramePoint
    trigger         TriggerFrameEnter
    triggeraction   TriggerFrameEnterAction
    trigger         TriggerFrameLeave
    triggeraction   TriggerFrameLeaveAction
    trigger         MouseClickTrigger
    triggeraction   MouseClickTriggerAction
    trigger         MouseReleaseTrigger
    triggeraction   MouseReleaseTriggerAction
    trigger         MOUSE_MOVE_Trigger
    triggeraction   MOUSE_MOVE_TriggerAction
endstruct
globals
    structMoveAbleFrame MoveAbleFrame
endglobals
function enable takes player p, boolean flag returns boolean
    if GetLocalPlayer() == p then
        if flag == null then
            set MoveAbleFrame.Enabled = not MoveAbleFrame.Enabled
        else
            set MoveAbleFrame.Enabled = flag
        endif
    endif
    return MoveAbleFrame.Enabled
endfunction
function setup takes framehandle frame returns nothing
    call BlzTriggerRegisterFrameEvent(MoveAbleFrame.TriggerFrameEnter, frame, FRAMEEVENT_MOUSE_ENTER)
    call BlzTriggerRegisterFrameEvent(MoveAbleFrame.TriggerFrameLeave , frame, FRAMEEVENT_MOUSE_LEAVE)
endfunction
function startMoving takes framehandle frame, framepointtype framePoint returns nothing
    set MoveAbleFrame.Frame = frame
    if framePoint == null then
       set framePoint = FRAMEPOINT_CENTER
    endif
    set MoveAbleFrame.FramePoint = framePoint
endfunction
function moveFrame takes real x, real y returns nothing
    call BlzFrameClearAllPoints(MoveAbleFrame.Frame)
    call BlzFrameSetAbsPoint(MoveAbleFrame.Frame, MoveAbleFrame.FramePoint, x, y)
endfunction
function GetTriggerPlayerHoveredFrame takes nothing returns nothing
    local real x = BlzGetTriggerPlayerMouseX()
    local real y = BlzGetTriggerPlayerMouseY()
    if GetLocalPlayer() == GetTriggerPlayer() then
        set MoveAbleFrame.PlayerHoveredFrame = BlzGetTriggerFrame()
    endif
endfunction
function GetTriggerPlayerHoveredFrameNull takes nothing returns nothing
    if GetLocalPlayer() == GetTriggerPlayer() then
        set MoveAbleFrame.PlayerHoveredFrame = null
    endif
endfunction
globals
    location moveLoc = Location(0, 0)
    boolean flag = false
endglobals
function TempFrameSetting takes nothing returns nothing
    call BlzFrameSetEnable(MoveAbleFrame.PlayerHoveredFrame, false)
    call BlzFrameSetLevel(MoveAbleFrame.PlayerHoveredFrame, 9)
    call BlzFrameSetScale(MoveAbleFrame.PlayerHoveredFrame, 0.8)
endfunction
function NormalFrameSetting takes nothing returns nothing
    call BlzFrameSetScale(MoveAbleFrame.Frame, 1.0)
    call BlzFrameSetEnable(MoveAbleFrame.Frame, true)
    call BlzFrameSetLevel(MoveAbleFrame.Frame, 6)
    set MoveAbleFrame.Frame = null
endfunction
globals
    real mouseX = 0.0
    real mouseY = 0.0
    real mouseX_prev = 0.0
    real mouseY_prev = 0.0
    real mouseX_interp = 0.0
    real mouseY_interp = 0.0
    real interpProgress = 1.0
    real interpSpeed  = 0
endglobals
function UpdateTargetXYInstant takes nothing returns nothing
    local real x = BlzGetTriggerPlayerMouseX()
    local real y = BlzGetTriggerPlayerMouseY()
    local real z
    call MoveLocation(moveLoc, x, y)
    set z = GetLocationZ(moveLoc)
    call World2Screen(x, y, z)
    // не трогаем prev/interp — сразу задаём target
    set targetX = ScreenX
    set targetY = ScreenY
endfunction
function UpdateMouseScreenCoords takes nothing returns nothing
    local real x = BlzGetTriggerPlayerMouseX()
    local real y = BlzGetTriggerPlayerMouseY()
    local real z
    call MoveLocation(moveLoc, x, y)
    set z = GetLocationZ(moveLoc)
    call World2Screen(x, y, z)
    set mouseX_prev = mouseX
    set mouseY_prev = mouseY
    set mouseX = ScreenX
    set mouseY = ScreenY
    set mouseX_interp = mouseX
    set mouseY_interp = mouseY
    set interpProgress = 1.0
    set targetX = mouseX
    set targetY = mouseY
endfunction
function PolledWait2 takes real time returns nothing
local timer t
local real R
    if time>0. then
        set t = CreateTimer()
        call TimerStart(t,time,false,null)
        loop
            set R=TimerGetRemaining(t)
            exitwhen R<=0.
                call TriggerSleepAction(R)
        endloop
        call DestroyTimer(t)
        set t=null
    endif 
endfunction
function GetWorld2Screen takes nothing returns real
    local real x = BlzGetTriggerPlayerMouseX()
    local real y = BlzGetTriggerPlayerMouseY()
    local real z
    
    call MoveLocation(moveLoc, x, y)
    set z = GetLocationZ(moveLoc)
    call World2Screen(x, y, z)
    return SquareRoot((currentX - ScreenX)*(currentX - ScreenX) + (currentY - ScreenY)*(currentY - ScreenY))
endfunction
function MouseClick takes nothing returns nothing
    local player p = GetTriggerPlayer()
    local real dist
    local timer t
    if BlzGetTriggerPlayerMouseButton() == MOUSE_BUTTON_TYPE_RIGHT then
        if MoveAbleFrame.Enabled and GetLocalPlayer() == p then
            if RIGHT_MOUSE_BUTTON_FRAME_DRAG_ENABLE then
                // Стандартное поведение (перетаскивание)
                if MoveAbleFrame.PlayerHoveredFrame != null then
                    set flag = true
                    call startMoving(MoveAbleFrame.PlayerHoveredFrame, FRAMEPOINT_CENTER)
                    call TempFrameSetting()
                    call UpdateMouseScreenCoords() 
                    set currentX = targetX
                    set currentY = targetY
                    call moveFrame(currentX, currentY)
                else
                    set flag = false
                    set MoveAbleFrame.Frame = null
                endif
            else
                // Альтернативное поведение (вкл/выкл)
                if MoveAbleFrame.PlayerHoveredFrame != null then
                    set flag = not flag
                    set PolledMoving = not PolledMoving
                    if flag then
                        call startMoving(MoveAbleFrame.PlayerHoveredFrame, FRAMEPOINT_CENTER)
                        call UpdateMouseScreenCoords()
                        set currentX = targetX
                        set currentY = targetY
                        call moveFrame(currentX, currentY)
                        call TempFrameSetting()
                    else
                        // Добавлено: сброс масштаба при flag = false (клик по фрейму)
                        call NormalFrameSetting()
                    endif
                else
                    // Клик вне фрейма — сброс (если PolledMoving = true)
                    if DRAG_TIMER_ENABLE then
                        if PolledMoving then
                            set PolledMoving = not PolledMoving
                            if GetWorld2Screen() > 0.0029 then
                                set t = CreateTimer()
                                call TimerStart(t, 0.15, false, null)
                                loop
                                    set dist = GetWorld2Screen()
                                    exitwhen dist < 0.002 or TimerGetRemaining(t) <= 0.
                                    call TriggerSleepAction(0.01)
                                endloop
                                call DestroyTimer(t)
                                set t = null
                            endif
                        endif
                    endif
                    set flag = false
                    call NormalFrameSetting()
                endif 
            endif
        endif
    endif
endfunction
function MouseRelease takes nothing returns nothing
    local real dist
    if MoveAbleFrame.Frame == null then
        return // нет фрейма — ничего не двигаем
    endif
    if RIGHT_MOUSE_BUTTON_FRAME_DRAG_ENABLE then
        set dist = GetWorld2Screen()
        if dist < 0.003 then
            // Мышь уже почти на фрейме — завершаем немедленно
            set flag = false
            set wasMoving = true
            set targetX = ScreenX
            set targetY = ScreenY
        else
            if DRAG_TIMER_ENABLE then
                 // Мышь далеко — ждём, пока дотянется
                call PolledWait2(0.15)
            endif
            set flag = false
            set wasMoving = true
            call UpdateTargetXYInstant()
        endif 
    endif
endfunction
function OnMouseMove takes nothing returns nothing
    local real newX = BlzGetTriggerPlayerMouseX()
    local real newY = BlzGetTriggerPlayerMouseY()
    //set GetFunctionName_DEBUG = "OnMouseMove"
    set mouseX_prev = mouseX
    set mouseY_prev = mouseY
    set mouseX = newX
    set mouseY = newY
    set interpProgress = 0.0
endfunction
function update2 takes nothing returns nothing
    local real dx
    local real dy
    local real distMouse
    local real dist
    local real dynamicSpeed
    local real speed = moveSpeed
    if MoveAbleFrame.Frame == null then
        return // нет фрейма — ничего не двигаем
    endif
    if flag or wasMoving then
        set dx = mouseX - mouseX_prev
        set dy = mouseY - mouseY_prev
        set distMouse = SquareRoot(dx * dx + dy * dy)
        set interpSpeed = 0.1 + distMouse * 0.6
        if interpSpeed > 0.3 then
            set interpSpeed = 0.3 // Ограничение скорости интерполяции
        endif
        set interpProgress = interpProgress + interpSpeed
        if interpProgress > 1.0 then
            set interpProgress = 1.0
        endif
        set mouseX_interp = mouseX_prev + (mouseX - mouseX_prev) * interpProgress
        set mouseY_interp = mouseY_prev + (mouseY - mouseY_prev) * interpProgress
        set targetX = mouseX_interp
        set targetY = mouseY_interp
        //set dist = SquareRoot((targetX - currentX)*(targetX - currentX) + (targetY - currentY)*(targetY - currentY))
        //set dynamicSpeed = moveSpeed + dist * 0.4
        //if dynamicSpeed > 0.08 then
            //set dynamicSpeed = 0.08
        //endif
        //set currentX = currentX + (targetX - currentX) * dynamicSpeed
        //set currentY = currentY + (targetY - currentY) * dynamicSpeed
        set dist = SquareRoot((targetX - currentX)*(targetX - currentX) + (targetY - currentY)*(targetY - currentY))
        if dist < 0.05 then
            set speed = moveSpeed + (0.05 - dist) * 2.0
            if speed > 0.025 then
                set speed = 0.025 // максимум, чтобы не прыгало
            endif
        endif
        set currentX = currentX * (1.0 - speed) + targetX * speed
        set currentY = currentY * (1.0 - speed) + targetY * speed
        call moveFrame(currentX, currentY)
        
        // завершение
        if not flag and dist < 0.001 then
            set wasMoving = false
            call BlzFrameSetScale(MoveAbleFrame.Frame, 1.0)
            call BlzFrameSetEnable(MoveAbleFrame.Frame, true)
            call BlzFrameSetLevel(MoveAbleFrame.Frame, 6)
        endif
    endif
endfunction
function CoordsMouse takes nothing returns nothing
    local real x = BlzGetTriggerPlayerMouseX()
    local real y = BlzGetTriggerPlayerMouseY()
    local real z
    if flag == true then
        call MoveLocation(moveLoc, x, y)
        set z = GetLocationZ(moveLoc)
        call World2Screen(x,y,z)
        set mouseX_prev = mouseX
        set mouseY_prev = mouseY
        set mouseX = ScreenX
        set mouseY = ScreenY
        set interpProgress = 0.0
    endif
endfunction
function onTriggerInit takes nothing returns nothing
local integer playerIndex = 0
local timer Timer = CreateTimer()
local timer Timer2 = CreateTimer()
    call PolledWait2(0.01)
    set MoveAbleFrame = structMoveAbleFrame.create()
    
    set MoveAbleFrame.TriggerFrameEnter = CreateTrigger()
    set MoveAbleFrame.TriggerFrameEnterAction = TriggerAddAction(MoveAbleFrame.TriggerFrameEnter,function GetTriggerPlayerHoveredFrame)
    
    set MoveAbleFrame.TriggerFrameLeave = CreateTrigger()
    set MoveAbleFrame.TriggerFrameLeaveAction = TriggerAddAction(MoveAbleFrame.TriggerFrameLeave, function GetTriggerPlayerHoveredFrameNull)
    set MoveAbleFrame.MouseClickTrigger = CreateTrigger()
    set MoveAbleFrame.MouseClickTriggerAction = TriggerAddAction(MoveAbleFrame.MouseClickTrigger, function MouseClick)
    
    set MoveAbleFrame.MouseReleaseTrigger = CreateTrigger()
    set MoveAbleFrame.MouseReleaseTriggerAction = TriggerAddAction(MoveAbleFrame.MouseReleaseTrigger, function MouseRelease)
    
    set MoveAbleFrame.MOUSE_MOVE_Trigger = CreateTrigger()
    set MoveAbleFrame.MOUSE_MOVE_TriggerAction = TriggerAddAction(MoveAbleFrame.MOUSE_MOVE_Trigger, function CoordsMouse)
    loop
    exitwhen playerIndex == GetBJMaxPlayers()
        call TriggerRegisterPlayerEvent(MoveAbleFrame.MouseClickTrigger, Player(playerIndex), EVENT_PLAYER_MOUSE_DOWN)
        call TriggerRegisterPlayerEvent(MoveAbleFrame.MouseReleaseTrigger, Player(playerIndex), EVENT_PLAYER_MOUSE_UP)
        call TriggerRegisterPlayerEvent(MoveAbleFrame.MOUSE_MOVE_Trigger, Player(playerIndex), EVENT_PLAYER_MOUSE_MOVE)
        set playerIndex = playerIndex + 1
    endloop
call ExecuteFunc("Init")
call TimerStart(Timer, 0.001, true, function update2)
call ExecuteFunc("CheckBoxInit")
endfunction
endlibrary
MoveAbleFrame 2 (Второй вариант)
library MoveAbleFrame initializer onTriggerInit requires World2Screen
globals
    real targetX = 0.0
    real targetY = 0.0
    real currentX = 0.0
    real currentY = 0.0
    real moveSpeed = 0.04 // от 0 до 1: выше — быстрее, ниже — плавнее
    real prevTargetX = 0.0
    real prevTargetY = 0.0
    real deltaX = 0.0
    real deltaY = 0.0
endglobals
struct structMoveAbleFrame
    boolean         Enabled = true
    
    framehandle     Frame = null
    framehandle     PlayerHoveredFrame
    framepointtype  FramePoint
    trigger         TriggerFrameEnter
    triggeraction   TriggerFrameEnterAction
    trigger         TriggerFrameLeave
    triggeraction   TriggerFrameLeaveAction
    trigger         MouseClickTrigger
    triggeraction   MouseClickTriggerAction
    trigger         MouseReleaseTrigger
    triggeraction   MouseReleaseTriggerAction
    trigger         MOUSE_MOVE_Trigger
    triggeraction   MOUSE_MOVE_TriggerAction
endstruct
globals
    structMoveAbleFrame MoveAbleFrame
endglobals
function enable takes player p, boolean flag returns boolean
    if GetLocalPlayer() == p then
        if flag == null then
            set MoveAbleFrame.Enabled = not MoveAbleFrame.Enabled
        else
            set MoveAbleFrame.Enabled = flag
        endif
    endif
    return MoveAbleFrame.Enabled
endfunction
function setup takes framehandle frame returns nothing
    call BlzTriggerRegisterFrameEvent(MoveAbleFrame.TriggerFrameEnter, frame, FRAMEEVENT_MOUSE_ENTER)
    call BlzTriggerRegisterFrameEvent(MoveAbleFrame.TriggerFrameLeave , frame, FRAMEEVENT_MOUSE_LEAVE)
endfunction
function startMoving takes framehandle frame, framepointtype framePoint returns nothing
    set MoveAbleFrame.Frame = frame
    if framePoint == null then
       set framePoint = FRAMEPOINT_CENTER
    endif
    set MoveAbleFrame.FramePoint = framePoint
endfunction
function moveFrame takes real x, real y returns nothing
    call BJDebugMsg("moveFrame: called x=" + R2S(x) + " y=" + R2S(y))
    call BlzFrameClearAllPoints(MoveAbleFrame.Frame)
    call BlzFrameSetAbsPoint(MoveAbleFrame.Frame, MoveAbleFrame.FramePoint, x, y)
endfunction
function GetTriggerPlayerHoveredFrame takes nothing returns nothing
    if GetLocalPlayer() == GetTriggerPlayer() then
        set MoveAbleFrame.PlayerHoveredFrame = BlzGetTriggerFrame()
    endif
endfunction
function GetTriggerPlayerHoveredFrameNull takes nothing returns nothing
    if GetLocalPlayer() == GetTriggerPlayer() then
        set MoveAbleFrame.PlayerHoveredFrame = null
    endif
endfunction
globals
    location moveLoc = Location(0, 0)
    boolean flag = false
endglobals
function MouseClick takes nothing returns nothing
    local player p = GetTriggerPlayer()
    local real x = BlzGetTriggerPlayerMouseX()
    local real y = BlzGetTriggerPlayerMouseY()
    local real z
    call MoveLocation(moveLoc, x, y)
    set z = GetLocationZ(moveLoc)
    call BJDebugMsg("MouseClick")
    if BlzGetTriggerPlayerMouseButton() == MOUSE_BUTTON_TYPE_RIGHT then
        if MoveAbleFrame.PlayerHoveredFrame != null then
            call BJDebugMsg("MouseClick: frame is not null: " + BlzFrameGetName(MoveAbleFrame.PlayerHoveredFrame))
            if MoveAbleFrame.Enabled then
                if GetLocalPlayer() == p then
                    set flag = true // Перемещение только если действительно кликнули по фрейму
                    call startMoving(MoveAbleFrame.PlayerHoveredFrame, FRAMEPOINT_CENTER)
                    call BlzFrameSetEnable(MoveAbleFrame.PlayerHoveredFrame, false)
                    call World2Screen(x,y,z)
                endif
            endif
        else
            call BJDebugMsg("MouseClick: PlayerHoveredFrame is null")
        endif
    endif
endfunction
function MouseRelease takes nothing returns nothing
call BJDebugMsg("MouseRelease")
set flag = false
    if BlzGetTriggerPlayerMouseButton() == MOUSE_BUTTON_TYPE_RIGHT then
        if MoveAbleFrame.Frame != null then
            call BlzFrameSetEnable(MoveAbleFrame.Frame, true)
        endif
    endif
endfunction
function PolledWait2 takes real time returns nothing
local timer t
local real R
    if time>0. then
        set t = CreateTimer()
        call TimerStart(t,time,false,null)
        loop
            set R=TimerGetRemaining(t)
            exitwhen R<=0.
                call TriggerSleepAction(R)
        endloop
        call DestroyTimer(t)
        set t=null
    endif 
endfunction
function update2 takes nothing returns nothing
    local real dist
    local real dynamicSpeed
    if flag == true then
        set dist = SquareRoot((targetX - currentX)*(targetX - currentX) + (targetY - currentY)*(targetY - currentY))
        set dynamicSpeed = moveSpeed + dist * 0.4
        if dynamicSpeed > 0.08 then
            set dynamicSpeed = 0.08
        endif
        // Плавное приближение к целевой позиции
        set currentX = currentX + (targetX - currentX) * moveSpeed
        set currentY = currentY + (targetY - currentY) * moveSpeed
        call moveFrame(currentX, currentY)
    endif
endfunction
function CoordsMouse takes nothing returns nothing
    local real x = BlzGetTriggerPlayerMouseX()
    local real y = BlzGetTriggerPlayerMouseY()
    local real speedLimit = 0.25
    local real deltaLength = SquareRoot(deltaX * deltaX + deltaY * deltaY)
    local real z
    if flag == true then
        call MoveLocation(moveLoc, x, y)
        set z = GetLocationZ(moveLoc)
        call World2Screen(x,y,z)
        set deltaX = ScreenX - prevTargetX
        set deltaY = ScreenY - prevTargetY
        if deltaLength > speedLimit then
            set deltaX = deltaX * speedLimit / deltaLength
            set deltaY = deltaY * speedLimit / deltaLength
        endif
        set targetX = ScreenX + deltaX * 1.4
        set targetY = ScreenY + deltaY * 1.4
        set prevTargetX = ScreenX
        set prevTargetY = ScreenY
    endif
endfunction
function onTriggerInit takes nothing returns nothing
local integer playerIndex = 0
local timer Timer = CreateTimer()
local timer Timer2 = CreateTimer()
    call PolledWait2(0.01)
    set MoveAbleFrame = structMoveAbleFrame.create()
    
    set MoveAbleFrame.TriggerFrameEnter = CreateTrigger()
    set MoveAbleFrame.TriggerFrameEnterAction = TriggerAddAction(MoveAbleFrame.TriggerFrameEnter,function GetTriggerPlayerHoveredFrame)
    
    set MoveAbleFrame.TriggerFrameLeave = CreateTrigger()
    set MoveAbleFrame.TriggerFrameLeaveAction = TriggerAddAction(MoveAbleFrame.TriggerFrameLeave, function GetTriggerPlayerHoveredFrameNull)
    set MoveAbleFrame.MouseClickTrigger = CreateTrigger()
    set MoveAbleFrame.MouseClickTriggerAction = TriggerAddAction(MoveAbleFrame.MouseClickTrigger, function MouseClick)
    
    set MoveAbleFrame.MouseReleaseTrigger = CreateTrigger()
    set MoveAbleFrame.MouseReleaseTriggerAction = TriggerAddAction(MoveAbleFrame.MouseReleaseTrigger, function MouseRelease)
    
    set MoveAbleFrame.MOUSE_MOVE_Trigger = CreateTrigger()
    set MoveAbleFrame.MOUSE_MOVE_TriggerAction = TriggerAddAction(MoveAbleFrame.MOUSE_MOVE_Trigger, function CoordsMouse)
    loop
    exitwhen playerIndex == GetBJMaxPlayers()
        call TriggerRegisterPlayerEvent(MoveAbleFrame.MouseClickTrigger, Player(playerIndex), EVENT_PLAYER_MOUSE_DOWN)
        call TriggerRegisterPlayerEvent(MoveAbleFrame.MouseReleaseTrigger, Player(playerIndex), EVENT_PLAYER_MOUSE_UP)
        call TriggerRegisterPlayerEvent(MoveAbleFrame.MOUSE_MOVE_Trigger, Player(playerIndex), EVENT_PLAYER_MOUSE_MOVE)
        set playerIndex = playerIndex + 1
    endloop
call ExecuteFunc("onGameStart")
call TimerStart(Timer, 0.003, true, function update2)
endfunction
endlibrary
Код для тестирования системы
library Testb
private function click takes nothing returns nothing
    call BJDebugMsg("click " + BlzFrameGetName(BlzGetTriggerFrame()))
endfunction
private function enter takes nothing returns nothing
   // call BJDebugMsg("enter " + BlzFrameGetName(BlzGetTriggerFrame()))
endfunction
function onGameStart takes nothing returns nothing
    local framehandle gameUI = BlzGetFrameByName("ConsoleUIBackdrop", 0)
    local trigger t = CreateTrigger()
    local trigger t2 = CreateTrigger()
    local framehandle b
    call TriggerAddAction(t, function click)
    
    call TriggerAddAction(t2, function enter)
    
    set b =  BlzCreateFrameByType("GLUETEXTBUTTON", "b 1", gameUI, "ScriptDialogButton", 0)
    call BlzFrameSetAbsPoint(b, FRAMEPOINT_CENTER, 0.55, 0.4)
    call BlzFrameSetText(b, "b 1")
    call setup(b)
    call BlzTriggerRegisterFrameEvent(t, b, FRAMEEVENT_CONTROL_CLICK)
    call BlzTriggerRegisterFrameEvent(t2, b, FRAMEEVENT_MOUSE_ENTER)
    set b =  BlzCreateFrameByType("GLUETEXTBUTTON", "b 2", gameUI, "ScriptDialogButton", 0)
    call BlzFrameSetAbsPoint(b, FRAMEPOINT_CENTER, 0.55, 0.35)
    call BlzFrameSetText(b, "b 2")
    call setup(b)
    call BlzTriggerRegisterFrameEvent(t, b, FRAMEEVENT_CONTROL_CLICK)
    call BlzTriggerRegisterFrameEvent(t2, b, FRAMEEVENT_MOUSE_ENTER)
    set b =  BlzCreateFrameByType("GLUETEXTBUTTON", "b 3", gameUI, "ScriptDialogButton", 0)
    call BlzFrameSetAbsPoint(b, FRAMEPOINT_CENTER, 0.55, 0.45)
    call BlzFrameSetText(b, "b 3")
    call setup(b)
    call BlzTriggerRegisterFrameEvent(t, b, FRAMEEVENT_CONTROL_CLICK)
    call BlzTriggerRegisterFrameEvent(t2, b, FRAMEEVENT_MOUSE_ENTER)
    //call enable(GetLocalPlayer(),true)
    call BJDebugMsg(GetPlayerName(GetLocalPlayer()))
    call BJDebugMsg("onGameStart END")
endfunction
endlibrary
Спасибо больше  ScorpioT1000, за помощь в  плавном движении и замечательную вещь экстраполяцию

                                WC3
                            



                            
                            
                            
                            
Ред. Koladik
Ред. darkowlom
Ред. darkowlom
Ред. darkowlom
Ред. darkowlom
Прокрутить к ресурсу
real targetX = 0.0
real targetY = 0.0
real currentX = 0.0
real currentY = 0.0
real moveSpeed = 0.04 от 0 до 1: выше — быстрее, ниже — плавнее
real prevTargetX = 0.0
real prevTargetY = 0.0
real deltaX = 0.0
real deltaY = 0.0
endglobals
boolean Enabled = true
framehandle Frame = null
framehandle PlayerHoveredFrame
framepointtype FramePoint
trigger TriggerFrameEnter
triggeraction TriggerFrameEnterAction
trigger TriggerFrameLeave
triggeraction TriggerFrameLeaveAction
trigger MouseClickTrigger
triggeraction MouseClickTriggerAction
trigger MouseReleaseTrigger
triggeraction MouseReleaseTriggerAction
trigger MOUSE_MOVE_Trigger
triggeraction MOUSE_MOVE_TriggerAction
endstruct
structMoveAbleFrame MoveAbleFrame
endglobals
if GetLocalPlayer() == p then
if flag == null then
set MoveAbleFrame.Enabled = not MoveAbleFrame.Enabled
else
set MoveAbleFrame.Enabled = flag
endif
endif
return MoveAbleFrame.Enabled
endfunction
call BlzTriggerRegisterFrameEvent(MoveAbleFrame.TriggerFrameEnter, frame, FRAMEEVENT_MOUSE_ENTER)
call BlzTriggerRegisterFrameEvent(MoveAbleFrame.TriggerFrameLeave , frame, FRAMEEVENT_MOUSE_LEAVE)
endfunction
set MoveAbleFrame.Frame = frame
if framePoint == null then
set framePoint = FRAMEPOINT_CENTER
endif
set MoveAbleFrame.FramePoint = framePoint
endfunction
call BJDebugMsg("moveFrame: called x=" + R2S(x) + " y=" + R2S(y))
call BlzFrameClearAllPoints(MoveAbleFrame.Frame)
call BlzFrameSetAbsPoint(MoveAbleFrame.Frame, MoveAbleFrame.FramePoint, x, y)
endfunction
local real x = BlzGetTriggerPlayerMouseX()
local real y = BlzGetTriggerPlayerMouseY()
set GetTriggerName_DEBUG = "TriggerFrameEnter"
if GetLocalPlayer() == GetTriggerPlayer() then
set MoveAbleFrame.PlayerHoveredFrame = BlzGetTriggerFrame()
endif
endfunction
set GetTriggerName_DEBUG = "TriggerFrameLeave"
if GetLocalPlayer() == GetTriggerPlayer() then
set MoveAbleFrame.PlayerHoveredFrame = null
endif
endfunction
location moveLoc = Location(0, 0)
boolean flag = false
endglobals
local player p = GetTriggerPlayer()
local real x = BlzGetTriggerPlayerMouseX()
local real y = BlzGetTriggerPlayerMouseY()
local real z
call updateDebugFrame()
set GetFunctionName_DEBUG = "MouseClick"
set GetTriggerName_DEBUG = "MouseClickTrigger"
call MoveLocation(moveLoc, x, y)
set z = GetLocationZ(moveLoc)
if MoveAbleFrame.PlayerHoveredFrame != null then
call BJDebugMsg("MouseClick: frame is not null: " + BlzFrameGetName(MoveAbleFrame.PlayerHoveredFrame))
if MoveAbleFrame.Enabled then
if GetLocalPlayer() == p then
set flag = true
call startMoving(MoveAbleFrame.PlayerHoveredFrame, FRAMEPOINT_CENTER)
call BlzFrameSetEnable(MoveAbleFrame.PlayerHoveredFrame, false)
call World2Screen(x,y,z)
set mouseX = ScreenX
set mouseY = ScreenY
set mouseX_prev = ScreenX
set mouseY_prev = ScreenY
set currentX = ScreenX
set currentY = ScreenY
set interpProgress = 1.0
endif
endif
else
call BJDebugMsg("MouseClick: PlayerHoveredFrame is null")
endif
endif
endfunction
set flag = false
set GetFunctionName_DEBUG = "MouseRelease"
set GetTriggerName_DEBUG = "MouseReleaseTrigger"
if BlzGetTriggerPlayerMouseButton() == MOUSE_BUTTON_TYPE_RIGHT then
if MoveAbleFrame.Frame != null then
call BlzFrameSetEnable(MoveAbleFrame.Frame, true)
endif
endif
endfunction
local timer t
local real R
if time>0. then
set t = CreateTimer()
call TimerStart(t,time,false,null)
loop
set R=TimerGetRemaining(t)
exitwhen R<=0.
call TriggerSleepAction(R)
endloop
call DestroyTimer(t)
set t=null
endif
endfunction
real mouseX = 0.0
real mouseY = 0.0
real mouseX_prev = 0.0
real mouseY_prev = 0.0
real mouseX_interp = 0.0
real mouseY_interp = 0.0
real interpProgress = 1.0
real interpSpeed = 0
endglobals
local real newX = BlzGetTriggerPlayerMouseX()
local real newY = BlzGetTriggerPlayerMouseY()
set GetFunctionName_DEBUG = "OnMouseMove"
set mouseX_prev = mouseX
set mouseY_prev = mouseY
set mouseY = newY
set interpProgress = 0.0
endfunction
local real dist
local real dynamicSpeed
local real dx
local real dy
local real distMouse
call updateDebugFrame()
set GetFunctionName_DEBUG = "update2"
set dx = mouseX - mouseX_prev
set dy = mouseY - mouseY_prev
set distMouse = SquareRoot(dx * dx + dy * dy)
if interpProgress > 1.0 then
set interpProgress = 1.0
endif
set mouseY_interp = mouseY_prev + (mouseY - mouseY_prev) * interpProgress
set targetY = mouseY_interp
set dynamicSpeed = moveSpeed + dist * 0.2
if dynamicSpeed > 0.08 then
set dynamicSpeed = 0.08
endif
set currentY = currentY + (targetY - currentY) * dynamicSpeed
endif
endfunction
local real x = BlzGetTriggerPlayerMouseX()
local real y = BlzGetTriggerPlayerMouseY()
local real z
set GetFunctionName_DEBUG = "CoordsMouse"
set GetTriggerName_DEBUG = "MOUSE_MOVE_Trigger"
if flag == true then
call MoveLocation(moveLoc, x, y)
set z = GetLocationZ(moveLoc)
call World2Screen(x,y,z)
set mouseY_prev = mouseY
set mouseX = ScreenX
set mouseY = ScreenY
set interpProgress = 0.0
endif
endfunction
local integer playerIndex = 0
local timer Timer = CreateTimer()
local timer Timer2 = CreateTimer()
call PolledWait2(0.01)
set MoveAbleFrame = structMoveAbleFrame.create()
set MoveAbleFrame.TriggerFrameEnter = CreateTrigger()
set MoveAbleFrame.TriggerFrameEnterAction = TriggerAddAction(MoveAbleFrame.TriggerFrameEnter,function GetTriggerPlayerHoveredFrame)
set MoveAbleFrame.TriggerFrameLeave = CreateTrigger()
set MoveAbleFrame.TriggerFrameLeaveAction = TriggerAddAction(MoveAbleFrame.TriggerFrameLeave, function GetTriggerPlayerHoveredFrameNull)
set MoveAbleFrame.MouseClickTriggerAction = TriggerAddAction(MoveAbleFrame.MouseClickTrigger, function MouseClick)
set MoveAbleFrame.MouseReleaseTrigger = CreateTrigger()
set MoveAbleFrame.MouseReleaseTriggerAction = TriggerAddAction(MoveAbleFrame.MouseReleaseTrigger, function MouseRelease)
set MoveAbleFrame.MOUSE_MOVE_Trigger = CreateTrigger()
set MoveAbleFrame.MOUSE_MOVE_TriggerAction = TriggerAddAction(MoveAbleFrame.MOUSE_MOVE_Trigger, function CoordsMouse)
exitwhen playerIndex == GetBJMaxPlayers()
call TriggerRegisterPlayerEvent(MoveAbleFrame.MouseClickTrigger, Player(playerIndex), EVENT_PLAYER_MOUSE_DOWN)
call TriggerRegisterPlayerEvent(MoveAbleFrame.MouseReleaseTrigger, Player(playerIndex), EVENT_PLAYER_MOUSE_UP)
call TriggerRegisterPlayerEvent(MoveAbleFrame.MOUSE_MOVE_Trigger, Player(playerIndex), EVENT_PLAYER_MOUSE_MOVE)
set playerIndex = playerIndex + 1
endloop
call ExecuteFunc("onGameStart")
call TimerStart(Timer, 0.003, true, function update2)
endfunction
real targetX = 0.0
real targetY = 0.0
real currentX = 0.0
real currentY = 0.0
real moveSpeed = 0.02 от 0 до 1: выше — быстрее, ниже — плавнее
real prevTargetX = 0.0
real prevTargetY = 0.0
real deltaX = 0.0
real deltaY = 0.0
endglobals
boolean Enabled = true
framehandle Frame = null
framehandle PlayerHoveredFrame
framepointtype FramePoint
trigger TriggerFrameEnter
triggeraction TriggerFrameEnterAction
trigger TriggerFrameLeave
triggeraction TriggerFrameLeaveAction
trigger MouseClickTrigger
triggeraction MouseClickTriggerAction
trigger MouseReleaseTrigger
triggeraction MouseReleaseTriggerAction
trigger MOUSE_MOVE_Trigger
triggeraction MOUSE_MOVE_TriggerAction
endstruct
structMoveAbleFrame MoveAbleFrame
endglobals
if GetLocalPlayer() == p then
if flag == null then
set MoveAbleFrame.Enabled = not MoveAbleFrame.Enabled
else
set MoveAbleFrame.Enabled = flag
endif
endif
return MoveAbleFrame.Enabled
endfunction
call BlzTriggerRegisterFrameEvent(MoveAbleFrame.TriggerFrameEnter, frame, FRAMEEVENT_MOUSE_ENTER)
call BlzTriggerRegisterFrameEvent(MoveAbleFrame.TriggerFrameLeave , frame, FRAMEEVENT_MOUSE_LEAVE)
endfunction
set MoveAbleFrame.Frame = frame
if framePoint == null then
set framePoint = FRAMEPOINT_CENTER
endif
set MoveAbleFrame.FramePoint = framePoint
endfunction
call BJDebugMsg("moveFrame: called x=" + R2S(x) + " y=" + R2S(y))
call BlzFrameClearAllPoints(MoveAbleFrame.Frame)
call BlzFrameSetAbsPoint(MoveAbleFrame.Frame, MoveAbleFrame.FramePoint, x, y)
endfunction
local real x = BlzGetTriggerPlayerMouseX()
local real y = BlzGetTriggerPlayerMouseY()
set GetTriggerName_DEBUG = "TriggerFrameEnter"
if GetLocalPlayer() == GetTriggerPlayer() then
set MoveAbleFrame.PlayerHoveredFrame = BlzGetTriggerFrame()
endif
endfunction
set GetTriggerName_DEBUG = "TriggerFrameLeave"
if GetLocalPlayer() == GetTriggerPlayer() then
set MoveAbleFrame.PlayerHoveredFrame = null
endif
endfunction
location moveLoc = Location(0, 0)
boolean flag = false
endglobals
local player p = GetTriggerPlayer()
local real x = BlzGetTriggerPlayerMouseX()
local real y = BlzGetTriggerPlayerMouseY()
local real z
call updateDebugFrame()
set GetFunctionName_DEBUG = "MouseClick"
set GetTriggerName_DEBUG = "MouseClickTrigger"
call MoveLocation(moveLoc, x, y)
set z = GetLocationZ(moveLoc)
if MoveAbleFrame.PlayerHoveredFrame != null then
call BJDebugMsg("MouseClick: frame is not null: " + BlzFrameGetName(MoveAbleFrame.PlayerHoveredFrame))
if MoveAbleFrame.Enabled then
if GetLocalPlayer() == p then
set flag = true
call startMoving(MoveAbleFrame.PlayerHoveredFrame, FRAMEPOINT_CENTER)
call BlzFrameSetEnable(MoveAbleFrame.PlayerHoveredFrame, false)
call World2Screen(x,y,z)
set mouseX = ScreenX
set mouseY = ScreenY
set mouseX_prev = ScreenX
set mouseY_prev = ScreenY
set currentX = ScreenX
set currentY = ScreenY
set interpProgress = 1.0
endif
endif
else
call BJDebugMsg("MouseClick: PlayerHoveredFrame is null")
endif
endif
endfunction
set flag = false
set GetFunctionName_DEBUG = "MouseRelease"
set GetTriggerName_DEBUG = "MouseReleaseTrigger"
if BlzGetTriggerPlayerMouseButton() == MOUSE_BUTTON_TYPE_RIGHT then
if MoveAbleFrame.Frame != null then
call BlzFrameSetEnable(MoveAbleFrame.Frame, true)
endif
endif
endfunction
local timer t
local real R
if time>0. then
set t = CreateTimer()
call TimerStart(t,time,false,null)
loop
set R=TimerGetRemaining(t)
exitwhen R<=0.
call TriggerSleepAction(R)
endloop
call DestroyTimer(t)
set t=null
endif
endfunction
real mouseX = 0.0
real mouseY = 0.0
real mouseX_prev = 0.0
real mouseY_prev = 0.0
real mouseX_interp = 0.0
real mouseY_interp = 0.0
real interpProgress = 1.0
real interpSpeed = 0
endglobals
local real newX = BlzGetTriggerPlayerMouseX()
local real newY = BlzGetTriggerPlayerMouseY()
set GetFunctionName_DEBUG = "OnMouseMove"
set mouseX_prev = mouseX
set mouseY_prev = mouseY
set mouseY = newY
set interpProgress = 0.0
endfunction
local real dist
local real dynamicSpeed
local real dx
local real dy
local real distMouse
call updateDebugFrame()
set GetTriggerName_DEBUG = "onTriggerInit"
set GetFunctionName_DEBUG = "update2"
set dx = mouseX - mouseX_prev
set dy = mouseY - mouseY_prev
set distMouse = SquareRoot(dx * dx + dy * dy)
if interpProgress > 1.0 then
set interpProgress = 1.0
endif
set mouseY_interp = mouseY_prev + (mouseY - mouseY_prev) * interpProgress
set targetY = mouseY_interp
set dynamicSpeed = moveSpeed + dist * 0.1
if dynamicSpeed > 0.05 then
set dynamicSpeed = 0.05
endif
set currentY = currentY + (targetY - currentY) * dynamicSpeed
endif
endfunction
local real x = BlzGetTriggerPlayerMouseX()
local real y = BlzGetTriggerPlayerMouseY()
local real z
set GetFunctionName_DEBUG = "CoordsMouse"
set GetTriggerName_DEBUG = "MOUSE_MOVE_Trigger"
if flag == true then
call MoveLocation(moveLoc, x, y)
set z = GetLocationZ(moveLoc)
call World2Screen(x,y,z)
set mouseY_prev = mouseY
set mouseX = ScreenX
set mouseY = ScreenY
set interpProgress = 0.0
endif
endfunction
local integer playerIndex = 0
local timer Timer = CreateTimer()
local timer Timer2 = CreateTimer()
call PolledWait2(0.01)
set MoveAbleFrame = structMoveAbleFrame.create()
set MoveAbleFrame.TriggerFrameEnter = CreateTrigger()
set MoveAbleFrame.TriggerFrameEnterAction = TriggerAddAction(MoveAbleFrame.TriggerFrameEnter,function GetTriggerPlayerHoveredFrame)
set MoveAbleFrame.TriggerFrameLeave = CreateTrigger()
set MoveAbleFrame.TriggerFrameLeaveAction = TriggerAddAction(MoveAbleFrame.TriggerFrameLeave, function GetTriggerPlayerHoveredFrameNull)
set MoveAbleFrame.MouseClickTriggerAction = TriggerAddAction(MoveAbleFrame.MouseClickTrigger, function MouseClick)
set MoveAbleFrame.MouseReleaseTrigger = CreateTrigger()
set MoveAbleFrame.MouseReleaseTriggerAction = TriggerAddAction(MoveAbleFrame.MouseReleaseTrigger, function MouseRelease)
set MoveAbleFrame.MOUSE_MOVE_Trigger = CreateTrigger()
set MoveAbleFrame.MOUSE_MOVE_TriggerAction = TriggerAddAction(MoveAbleFrame.MOUSE_MOVE_Trigger, function CoordsMouse)
exitwhen playerIndex == GetBJMaxPlayers()
call TriggerRegisterPlayerEvent(MoveAbleFrame.MouseClickTrigger, Player(playerIndex), EVENT_PLAYER_MOUSE_DOWN)
call TriggerRegisterPlayerEvent(MoveAbleFrame.MouseReleaseTrigger, Player(playerIndex), EVENT_PLAYER_MOUSE_UP)
call TriggerRegisterPlayerEvent(MoveAbleFrame.MOUSE_MOVE_Trigger, Player(playerIndex), EVENT_PLAYER_MOUSE_MOVE)
set playerIndex = playerIndex + 1
endloop
call ExecuteFunc("onGameStart")
call TimerStart(Timer, 0.001, true, function update2)
endfunction
- 
                                    
                                        
                                        Warcraft_III_Reforged_2025.07.25_-_23.23.00.04_copy1.mp4
                                    
                                
 
                            
                        
                            
                                - 
                                    
                                        
                                        Warcraft_III_Reforged_2025.07.25_-_23.21.36.03_copy1.mp4
                                    
                                
 
                            
                        
                            
                                - 
                                    
                                        
                                        Moveable_Frame_2.0.w3x
                                    
                                
 
                            
                        
                    
Полный списокP.S продолжаю эксперименты в попытках обойти задержку события, может что-то накопаю
Надо будет понять есть ли ещё варианты, ну и применить как-то для более идеальной плавности :)
Ред. darkowlom
Ред. Smeto
Прокрутить к ресурсу
Скачать версию карты для Warcraft 3 Reforget 2.0.0
Прокрутить к ресурсу
🔹 Новые возможности:
✅ Два режима перемещения:
🛠 Фрейм не возвращался к исходному размеру после клика по нему (теперь работает корректно).
Улучшена плавность движения.