Создаю порчу квадратом 300 на 300 но проблема в том что квадрат начинает отсчёт не от позиции юнита

Принятый ответ

об этом написано в статье, размер должен быть кратен 128
плюс у триггерных нативок еще смещение от заданной оси, поэтому я всегда юзал dummy-cast предмета нежити, которая наводит порчи. она более точная.

да, отсчет действительно начинает не от позиции юнита или каста. юнит или цель каста не будет находится в центре порчи, тк там координаты ищут ближайшие значения, если координата будет 43, то ближайшими координатами будут 0 и 64. там же крайние точки клетки берутся каждые 128 (или 256, точно не могу сказать, говорю на угад).
тестовый код (мб ошибки)
//точечно add/remove blight (заполняется клетка 128х128, а если быть точнее 256x256)
function DummyCastPointBlight takes player whichPlayer, real cx, real cy, real cx0, real cy0, boolean addBlight returns nothing
local unit dummy = CreateUnit( whichPlayer, 'h000', cx, cy, 0 )

//теперь нужно создать итем. Используем стандарт. способность предмета "наведение порчи". 
//Дело в том, что эта способность используется только в предмете
if addBlight then //если нужно добавить порчу, создаем итем наводящий порчу
    call UnitAddItemByIdSwapped( 'spsh', dummy )
else
    call UnitAddItemByIdSwapped( 'pmna', dummy )
endif
call UnitUseItemPoint( dummy, bj_lastCreatedItem, cx0, cy0 )
//Для устранения утечки (остается не удаленным юнит и предмет) можно использовать таймеры
//для удаления использовал триггер DeathDummy
endfunction

//круги с маленьким радиусом мало будут похожи на круг
function SetBlightCircle takes player whichPlayer, real cx, real cy, real radius, boolean addBlight returns nothing
local real Rad = RealRadius128(radius)
local real minx = cx-Rad
local real maxx = cx+Rad
local real miny = cy-Rad
local real maxy = cy+Rad
//начинаем с правого верхнего края
local real x0 = minx
local real y0 = maxy
//центр крайнего правого-верхнего квадратика
local real cx0 = minx+64.0
local real cy0 = maxy-64.0

loop
    exitwhen cx0>maxx
    
    set cy0 = maxy-64.0
    
    loop
        exitwhen cy0<miny
        call MoveRectTo(udg_Rect_32x32[4],cx0,cy0)
        if RectContainsCircle(udg_Rect_32x32[4], cx,cy, radius)then //если крайние точки и центр квадрата попадают в круг, начит 
            //call BJDebugMsg("Проверка прошла")
            //call SetBlightPoint(whichPlayer, cx0, cy0, addBlight)
            call DummyCastPointBlight(whichPlayer, cx, cy, cx0, cy0, addBlight) 
        else
            //call BJDebugMsg("Проверка не прошла")
        endif
        
        set cy0 = cy0-128.0
    endloop
    
    set cx0 = cx0 + 128.0
endloop

//call BJDebugMsg("Проверка")
endfunction


//для того, чтобы цель находилась в центре rect. вам нужен другой алгоритм. у меня код начинает с краю от цели
function SetBlightRectangle takes player whichPlayer, rect R, boolean addBlight returns nothing
//local real centx = GetRectCenterX(R)
//local real centy = GetRectCenterY(R)
local real maxx = RealCoord128(GetRectMaxX(R))
local real minx = RealCoord128(GetRectMinX(R))
local real maxy = RealCoord128(GetRectMaxY(R))
local real miny = RealCoord128(GetRectMinY(R))

//начинаем с правого верхнего края
local real x0 = minx
local real y0 = maxy
//центр крайнего правого-верхнего квадратика
local real cx0 = minx+64.0
local real cy0 = maxy-64.0

loop
    exitwhen cx0>maxx
    
    set cy0 = maxy-64.0
    
    loop
        exitwhen cy0<miny
        //call SetBlightPoint(whichPlayer, cx0, cy0, addBlight)
        call DummyCastPointBlight(whichPlayer, cx0, cy0, cx0, cy0, addBlight)         
        set cy0 = cy0-128.0
    endloop
    
    set cx0 = cx0 + 128.0
endloop
endfunction
кастует точечно, тк если брать размеры абилы больше 128, то начинает просто кастовать круг
скрин
Загруженные файлы
`
ОЖИДАНИЕ РЕКЛАМЫ...
3
19
5 лет назад
3
Похожие вопросы:

ответ
~16GB:
function move takes integer i returns nothing
    local unit u = udg_unit[i] // дамми снаряда
    local location p = GetUnitLoc(u)
    local location p2 = udg_point[i] // таргет спелла
    local real a
if DistanceBetweenPoints(p, p2) > 100 then
   set a = AngleBetweenPoints(p, p2)
   call MoveLocation(p, GetLocationX(p) + 10 * CosBJ(a), GetLocationY(p) + 10 * SinBJ(a))
   call SetUnitPositionLoc( u, p )
else
    call KillUnit( u )
    call RemoveLocation(p2)
    set udg_unit[i] = udg_unit[udg_number]
    set udg_point[i] = udg_point[udg_number]
    set udg_i = udg_i-1
    set udg_number = udg_number -1
    call PolledWait(0.5)
    call RemoveUnit(u)
endif
    set u = null
    call RemoveLocation(p)
    set p = null
    set p2 = null
    set a = 0
endfunction
Ты удалял точку сразу
ответ
Исключи курьера из условий проверки уровней..

Добавь условие: Проверка Типа Юнита (Юнит Триггера) != (не равно) Курьер
ответ
да вот только thistype возвращает структуру из которой он вызван, а не структуру инстанса идентификатора, т.е. getTrack будет всегда возвращать тип Tracker. Вопрос в том, как по идентификатору определить конкретный тип структуры и к нему привести.
Этот код тестировал? Он должен работать.

Структуры в vJass - массивы. Объект структуры - integer.
У каждой структуры есть массив, куда записывается тип каждого объекта структуры. Пусть у Trackle айди 1, а у Button 2. При создании объекта структуры будет сделано следующее: set массив_куда_записывается_тип[объект_структуры] = айди_структуры. При создании объекта Button и в массив типа структуры Button, и в массив структуры Trackle будет записано 2.

Перезаписываемые методы - массив триггеров, у которых в качестве условия записано тело метода.
Вызов такого метода - call TriggerEvaluate(массив_триггеров[массив_куда_записывается_тип[объект_структуры]]).
В нашем случае это будет выглядеть call TriggerEvaluate(массив_триггеров_OnTrack[массив_куда_записывается_тип[getTrack(h)]]).

Потому должно работать.
ответ
~8gabriel8:
Недавно сделал человеку универсальный триггер для таких случаев, который работает и в алтаре, и в таверне.
Событие: Юнит входит в область (Вся игровая карта)
Условие: (Триггеринг юнит) равно Герой равно Да
Действие: Игрок - Установить лимит юнита (тип юнита (Триггеринг юнит)) для игрока (Owner of unit (Триггеринг юнит)) в 1
ответ
~8gabriel8:
Это жесть, что ты сделал) Этот русификатор триггеров уж такую муть содержит, что ты просто какую-то белиберду сотворил. Исправил до рабочего вида, но чтобы совсем красиво было, это не ко мне, а к джассерам. Просто времени мало на всё, а исправление этих триггеров затратило его довольно много.

6
27
5 лет назад
Отредактирован MpW
6
об этом написано в статье, размер должен быть кратен 128
плюс у триггерных нативок еще смещение от заданной оси, поэтому я всегда юзал dummy-cast предмета нежити, которая наводит порчи. она более точная.

да, отсчет действительно начинает не от позиции юнита или каста. юнит или цель каста не будет находится в центре порчи, тк там координаты ищут ближайшие значения, если координата будет 43, то ближайшими координатами будут 0 и 64. там же крайние точки клетки берутся каждые 128 (или 256, точно не могу сказать, говорю на угад).
тестовый код (мб ошибки)
//точечно add/remove blight (заполняется клетка 128х128, а если быть точнее 256x256)
function DummyCastPointBlight takes player whichPlayer, real cx, real cy, real cx0, real cy0, boolean addBlight returns nothing
local unit dummy = CreateUnit( whichPlayer, 'h000', cx, cy, 0 )

//теперь нужно создать итем. Используем стандарт. способность предмета "наведение порчи". 
//Дело в том, что эта способность используется только в предмете
if addBlight then //если нужно добавить порчу, создаем итем наводящий порчу
    call UnitAddItemByIdSwapped( 'spsh', dummy )
else
    call UnitAddItemByIdSwapped( 'pmna', dummy )
endif
call UnitUseItemPoint( dummy, bj_lastCreatedItem, cx0, cy0 )
//Для устранения утечки (остается не удаленным юнит и предмет) можно использовать таймеры
//для удаления использовал триггер DeathDummy
endfunction

//круги с маленьким радиусом мало будут похожи на круг
function SetBlightCircle takes player whichPlayer, real cx, real cy, real radius, boolean addBlight returns nothing
local real Rad = RealRadius128(radius)
local real minx = cx-Rad
local real maxx = cx+Rad
local real miny = cy-Rad
local real maxy = cy+Rad
//начинаем с правого верхнего края
local real x0 = minx
local real y0 = maxy
//центр крайнего правого-верхнего квадратика
local real cx0 = minx+64.0
local real cy0 = maxy-64.0

loop
    exitwhen cx0>maxx
    
    set cy0 = maxy-64.0
    
    loop
        exitwhen cy0<miny
        call MoveRectTo(udg_Rect_32x32[4],cx0,cy0)
        if RectContainsCircle(udg_Rect_32x32[4], cx,cy, radius)then //если крайние точки и центр квадрата попадают в круг, начит 
            //call BJDebugMsg("Проверка прошла")
            //call SetBlightPoint(whichPlayer, cx0, cy0, addBlight)
            call DummyCastPointBlight(whichPlayer, cx, cy, cx0, cy0, addBlight) 
        else
            //call BJDebugMsg("Проверка не прошла")
        endif
        
        set cy0 = cy0-128.0
    endloop
    
    set cx0 = cx0 + 128.0
endloop

//call BJDebugMsg("Проверка")
endfunction


//для того, чтобы цель находилась в центре rect. вам нужен другой алгоритм. у меня код начинает с краю от цели
function SetBlightRectangle takes player whichPlayer, rect R, boolean addBlight returns nothing
//local real centx = GetRectCenterX(R)
//local real centy = GetRectCenterY(R)
local real maxx = RealCoord128(GetRectMaxX(R))
local real minx = RealCoord128(GetRectMinX(R))
local real maxy = RealCoord128(GetRectMaxY(R))
local real miny = RealCoord128(GetRectMinY(R))

//начинаем с правого верхнего края
local real x0 = minx
local real y0 = maxy
//центр крайнего правого-верхнего квадратика
local real cx0 = minx+64.0
local real cy0 = maxy-64.0

loop
    exitwhen cx0>maxx
    
    set cy0 = maxy-64.0
    
    loop
        exitwhen cy0<miny
        //call SetBlightPoint(whichPlayer, cx0, cy0, addBlight)
        call DummyCastPointBlight(whichPlayer, cx0, cy0, cx0, cy0, addBlight)         
        set cy0 = cy0-128.0
    endloop
    
    set cx0 = cx0 + 128.0
endloop
endfunction
кастует точечно, тк если брать размеры абилы больше 128, то начинает просто кастовать круг
скрин
Загруженные файлы
Принятый ответ
3
27
5 лет назад
Отредактирован MpW
3
вот сделал карту, в которой рект теперь ставится посередине. Однако, есть некоторые моменты. Dummy-cast в точку отбирает клетку 256х256 (жалко, слишком огромные размеры. меньше задать никак. это в способности по умолчанию задано). Хотя бы работает точно.

вот небольшие изменения. короче круг не очень похож на круг. только с большими размерами похож на круг. с маленькими размерами едва ли круг можно сделать, тк квадратами порчу наводит. а у нас dummy-cast квадратит с большими размерами, с 256х256
циклами шагами каждую точку проверяем, как и с ректами, тут проверяем так:
расстояние между point и центром круга > R круга, значит вышел за круг.
напоминает пиксельную графику

почитал снова статью. в статье обнаружил, что только у нативок (см ниже) смещается картинка порчи
native SetBlightPoint takes player whichPlayer, real x, real y, boolean addBlight returns nothing
native SetBlightRect takes player whichPlayer, rect r, boolean addBlight returns nothing
а вот у нативки SetBlight такой проблемы нет. Поэтому можно отказаться от вызова функции Dummy-cast, тк может вызывать подвисания при больших размерах. В функции dummy-cast создает каждый раз даймика и итема, и кастует. тк может одновременно дохера создать даймиков
native SetBlight takes player whichPlayer, real x, real y, real radius, boolean addBlight returns nothing
можно задать самый минимальный радиус radius, это будет почти тоже самое что и dummy-cast.

еще переделать круги. теперь нечто похожее на круг делает
код
//проверяет 5 точек квадрата points (это центр и 4 крайние), попали ли в круг
//расстояние между указанной точкой (cx,cy) и point > R круга, значит вышел за круг. иначе находится внутри круга
//логика такова: если все точки квадрата внутри, значит квадрат покрываем порчей
function RectContainsCircle takes rect R, real cx, real cy, real radius returns boolean
local real centx = GetRectCenterX(R)
local real centy = GetRectCenterY(R)
local real maxx = GetRectMaxX(R)
local real minx = GetRectMinX(R)
local real maxy = GetRectMaxY(R)
local real miny = GetRectMinY(R)

if (DistanceBetween2Points(minx,maxy,cx,cy) < radius) and DistanceBetween2Points(maxx,maxy,cx,cy) < radius and DistanceBetween2Points(centx,centy,cx,cy) < radius and DistanceBetween2Points(minx,miny,cx,cy) < radius and DistanceBetween2Points(maxx,miny,cx,cy) < radius then
    return true
endif

return false

endfunction

некоторые операции могут привести к лимиту операции. то же распространение порчи (с большим радиусом не хватает операции чтобы доделать круг, будет такой полукруг). Поэтому воспользовался ExecuteFunc, теперь всю карту покрывает норм.
Загруженные файлы
Чтобы оставить комментарий, пожалуйста, войдите на сайт.