Приветствую, уже ломаю голову, казалось бы очевидно, но помогите с кодом, где-то, что то обрывается, не могу понять как одновременно наносить урон или как занести нормально в группу более одного юнита, карту пример прикладываю. Так же есть проблема с корректным движением молнии в сторону цели.
Мне кажется проблема вот в этом блоке, что-то делаю не так и код обрывается или не добавляет юнита, который стоит на линии самый первый
function GroupEnumSkillEnemies_f takes nothing returns boolean
    local unit u=GroupingTempUnit
    local unit u2=GetFilterUnit()
    local boolean b=GetWidgetLife(u2)>0. and IsPlayerEnemy(GetOwningPlayer(u),GetOwningPlayer(u2)) and not IsUnitType(u2,UNIT_TYPE_STRUCTURE) and GetUnitAbilityLevel(u2,'AEev')==0
    set u=null
    set u2=null
    return b
endfunction

function GroupAddUnitEnemiesDamageEnum takes group g,real x,real y,real radius,unit skiller returns group
local unit u
local unit u2
local group tg = CreateGroup()
local group sg = g
local boolexpr be=Condition(function GroupEnumSkillEnemies_f)
    set GroupingTempUnit=skiller
    set u2 = FirstOfGroup(g)
    //call BJDebugMsg(GetUnitName(u2)+"     PEXOTA???")
    if u2==null then
        call GroupEnumUnitsInRange(g,x,y,radius,be)
        return g
    endif
    call GroupEnumUnitsInRange(tg,x,y,radius,be)
    set u=FirstOfGroup(tg)
    if u==null then
        return g
    endif
    loop
        //call BJDebugMsg("2: "+GetUnitName(u))
        set sg = g
        ///////////
        loop 
            
            set u2 = FirstOfGroup(sg)
            //call BJDebugMsg("2: "+GetUnitName(u)+" = "+ GetUnitName(u2)) 
            if u==u2 then
                call GroupRemoveUnit(tg,u)
                //call GroupRemoveUnit(sg,u2)
                set sg = g
                //set u2 = FirstOfGroup(sg)
                set u=FirstOfGroup(tg)
            else
                call GroupRemoveUnit(sg,u2)
            endif
            
        exitwhen u2==null or u==null
        endloop
        ///////////
        exitwhen u==null
        call GroupAddUnit(g,u)
        call BJDebugMsg("1: "+GetUnitName(u))
        //call GroupRemoveUnit(g,u)
        //set u=FirstOfGroup(g)
        //call BJDebugMsg("100: "+GetUnitName(u))
        //call PolledWait(1.)
        call GroupRemoveUnit(tg,u)
        set u=FirstOfGroup(tg)
        exitwhen u==null
    endloop
    //call RemoveItem(delete)
    call DestroyBoolExpr(be)
    set be=null
    return g
endfunction
function MinusPlus takes real c returns real
if c<0 then
    return -c
else
    return c
endif
endfunction

function Vector takes real x2, real x, real y2, real y, integer f returns real
local real vectorX = MinusPlus(x2)-MinusPlus(x)
local real vectorY = MinusPlus(y2)-MinusPlus(y)
local real d = vectorX*vectorX+vectorY+vectorY
    if d>1500 then
        set d = 1500
    endif
    set vectorX = vectorX/d
    set vectorY = vectorY/d
    set vectorX = MinusPlus(vectorX)
    set vectorY = MinusPlus(vectorY)
    if f==1 then
        return vectorX
    else
        return vectorY
    endif
endfunction
Функция которая двигает молнию и там же проверяет есть ли на линии кто то, но если на линии второй и так далее юнит, то Урон будет наносится только последнему
function ll takes nothing returns nothing
//
local timer t=GetExpiredTimer()
local integer id=GetHandleId(t)

local unit u = LoadUnitHandle(H,id,1)
local unit u2 = LoadUnitHandle(H,id,2)

local lightning l = LoadLightningHandle(H,id,3)

local location locU = GetUnitLoc(u)
local real xu = GetLocationX(locU)
local real yu = GetLocationY(locU)
local real x = LoadReal(H,id,4)
local real y = LoadReal(H,id,5)

local location locU2

local real z1 = 50

local real x2
local real y2
local real z2


local real z = 50

local group g = CreateGroup()
local integer c
local integer s=150
local integer s1=20
local real vectorX
local real vectorY
local real d
local real vector


    //call BJDebugMsg("==================")
    call SetUnitAnimation(u,"spell")

        
    set locU2=  GetUnitLoc(u2)
    set x2 = GetLocationX(locU2)
    set y2 = GetLocationY(locU2)
    /////////////////////////////
    set vectorX = Vector(x2, xu, y2, yu, 1)
    set vectorY = Vector(x2, xu, y2, yu, 0)
    ///////////////////////////////
    //call BJDebugMsg(R2S(vectorX)+"=X VR Y="+R2S(vectorY))
    loop
    exitwhen vectorX>25 and vectorY>25
        set vectorX=vectorX*2
        set vectorY=vectorY*2
    endloop
    if vectorX>30 or vectorY>30 then
        set vectorX=vectorX/100
        set vectorY=vectorY/100
        if vectorX<20 or vectorY<20 then
            set vectorX=vectorX+20
            set vectorY=vectorY+20
        endif
    endif
    ////////////////////400<-100////////////
    //call BJDebugMsg(I2S(R2I(x2))+"<"+I2S(R2I(x)))
    if x2<x then
        set x = x-vectorX
    else
        set x = x+vectorX
    endif
    call SaveReal(H,id,4,x)
    if y2<y then
        set y = y-vectorY
        //call BJDebugMsg(R2S(y)+"=Y")
    else
        set y = y+vectorX
    endif
    call SaveReal(H,id,5,y)
    //call BJDebugMsg(R2S(vectorX)+"=X Y="+R2S(vectorY))
    call MoveLightningEx(l, true, xu, yu, z1, x, y, z)
    set x2=xu // -600
    set y2=yu // -600
        if x2<x then
                if y2<y then
                    set c = 1
                else
                    set c = 2
                endif
            else
                if y2<y then
                    set c = 3
                else
                    set c = 4
                endif
            endif
            //call BJDebugMsg("c="+I2S(c))
            //call PolledWait2(1)
        loop
            if c==1 then
                if x2<=x then
                    //call BJDebugMsg("x2="+R2S(x2))
                    set x2=x2+vectorX
                endif
                if y2<=y then
                    //call BJDebugMsg("y2="+R2S(y2))
                    set y2=y2+vectorY
                endif
                //call BJDebugMsg("x2="+R2S(x2)+"<"+R2S(x))
                //call BJDebugMsg("y2="+R2S(y2)+"<"+R2S(y))
                if x2>=x and y2>=y
                    //call BJDebugMsg("Выйти")
                endif
                exitwhen x2>=x and y2>=y
            elseif c==2 then
                if x2<x or x2==x then
                    set x2=x2+vectorX
                endif
                if y2>y or y2==y then
                    set y2=y2-vectorY
                endif
                exitwhen x2>x and y2<y 
            elseif c==3 then
                if x2>x or x2==x then
                    set x2=x2-vectorX
                endif
                if y2<y or y2==y then
                    set y2=y2+vectorY
                endif
                exitwhen x2<x and y2>y 
            else
                if x2>x or x2==x then
                    set x2=x2-vectorX
                endif
                if y2>y or y2==y then
                    set y2=y2-vectorY
                endif
                exitwhen x2<x and y2<y 
            endif
            set g = GroupAddUnitEnemiesDamageEnum(g,x2,y2,100,u) // Вызываем функцию на добавление в группу юнита
            //set u=FirstOfGroup(g)
            //if u!=null then
            //    call BJDebugMsg(GetUnitName(u))
           // endif
        endloop
        //call BJDebugMsg("ex!")
        loop
        set u2=FirstOfGroup(g)
        //
        exitwhen u2==null
        //call BJDebugMsg(GetUnitName(u2))
            //call BJDebugMsg("not null")
            
            call DestroyEffect(AddSpecialEffect("Objects\\Spawnmodels\\Other\\NeutralBuildingExplosion\\NeutralBuildingExplosion.mdl",GetUnitX(u2),GetUnitY(u2)))
            call UnitDamageTarget(u, u2, 1, true, false, ATTACK_TYPE_MAGIC, DAMAGE_TYPE_UNIVERSAL, WEAPON_TYPE_WHOKNOWS)
            call GroupRemoveUnit(g,u2)
        endloop
///////////// 
    //call BJDebugMsg("Удаляем?")
    call PauseUnit(u, false)
    //call DestroyLightning( l )
endfunction
function LigtingStart takes nothing returns nothing
    //local unit u=GetTriggerUnit()
    local timer t=CreateTimer()
    local integer id=GetHandleId(t)
    local unit u = gg_unit_hhes_0000//От Кого двигаем
    local unit u2 = gg_unit_hcth_0001//К Кому двигаем
    local location ul=GetUnitLoc(u)
    local lightning l = AddLightningEx("CLPB", false, GetLocationX(ul), GetLocationY(ul), GetLocationZ(ul), GetLocationX(ul), GetLocationY(ul), GetLocationZ(ul))
    local location loc = GetUnitLoc(u)
    call SetLightningColor(l, 1, 0, 0, 1)

    call SaveReal(H,id,4,GetLocationX(loc))
    call SaveReal(H,id,5,GetLocationY(loc))
    
    call SaveUnitHandle(H,id,1,u)
    call SaveUnitHandle(H,id,2,u2)

    call SaveLightningHandle(H,id,3,l)
    //call SaveInteger(udg_h,id,2,201)
    call TimerStart(t,0.15,true,function ll) //Двигаем молнию
    //set u=null
    set t=null
endfunction



//===========================================================================
function InitTrig_l takes nothing returns nothing
    set gg_trg_l = CreateTrigger(  )
    call TriggerRegisterTimerEventSingle( gg_trg_l, 3 )
    call TriggerAddAction( gg_trg_l, function LigtingStart )
endfunction
`
LOADING AD...
The comment is deleted
Replies (2)
8
nazarpunk, Подправь меня по вращению, не до конца смог разобраться с твоей документацией, не понимаю где ошибся, а то получается фигура вращения кривая. На фото указал красным как должно быть, а черным, как происходит
function Condution2 takes real px, real py, location lu, location lu2 returns boolean
if (GetLocationX(lu2)>GetLocationX(lu)and GetLocationY(lu2)>GetLocationY(lu)and px>GetLocationX(lu2)and py>GetLocationX(lu2)) or (GetLocationX(lu2)>GetLocationX(lu) and GetLocationY(lu2)<GetLocationY(lu) and px>GetLocationX(lu2) and py<GetLocationX(lu2))or (GetLocationX(lu2)<GetLocationX(lu) and GetLocationY(lu2)<GetLocationY(lu) and px<GetLocationX(lu2) and py<GetLocationY(lu2)) then
    return true
endif
    return false
endfunction

function Condution takes real px, real py, location lu, location lu2 returns boolean
if Condution2(px,py,lu,lu2)==true or (GetLocationX(lu2)<GetLocationX(lu) and GetLocationY(lu2)>GetLocationY(lu) and px<GetLocationX(lu2)and py>GetLocationX(lu2)) then
    return true
endif
    return false
endfunction
function AngleBetweenXY takes real xa, real ya, real xb, real yb returns real
    return Atan2(yb - ya, xb - xa)
endfunction

function Trig_Line_Actions takes nothing returns nothing
local location lu = GetUnitLoc(gg_unit_hfoo_0000)
local location lu2//= GetUnitLoc(gg_unit_hfoo_0001)
local real dx// = RAbsBJ(GetLocationX(lu2)) - RAbsBJ(GetLocationX(lu))
local real dy// = RAbsBJ(GetLocationY(lu2)) - RAbsBJ(GetLocationY(lu))
local real d// = SquareRoot(dx * dx + dy * dy)
local real dist = 0
local real dist2 = 0
local real px = 0
local real py = 0
local real px2 = 0
local real py2 = 0
local real angle
local location p
local boolean flag=true
local group g = CreateGroup()
local lightning l = AddLightningEx("CLPB", false, GetLocationX(lu), GetLocationY(lu), GetLocationZ(lu), GetLocationX(lu), GetLocationY(lu), GetLocationZ(lu))
    set udg_i = 1
    loop
        call PolledWait2(0.15)
        set lu = GetUnitLoc(gg_unit_hfoo_0000)
        set lu2= GetUnitLoc(gg_unit_hfoo_0001)
        set dx = GetLocationX(lu2)- GetLocationX(lu)
        set dy = GetLocationY(lu2) - GetLocationY(lu)
        set d = SquareRoot(dx * dx + dy * dy)
        set angle = AngleBetweenXY(GetLocationX(lu),GetLocationY(lu),GetLocationX(lu2),GetLocationY(lu2)) //AngleBetweenPoints(lu , lu2)
        //if (px>GetLocationX(lu2) and py>GetLocationX(lu2)) or (px>GetLocationX(lu2) and py<GetLocationX(lu2)) then
        if Condution(px, py, lu, lu2)==true then
            set dist = dist-d/25
        else
            set dist = dist+d/25
        endif
        set px=Cos(angle) * dist + GetLocationX(lu)//GetLocationX(lu) + dist * Cos(angle * bj_DEGTORAD)
        set py=Sin(angle) * dist + GetLocationY(lu)//GetLocationY(lu) + dist * Sin(angle * bj_DEGTORAD)
        call LinePointPerpendicular(GetLocationX(lu),GetLocationY(lu),GetLocationX(lu2),GetLocationY(lu2),px,py)
        call MoveLightningEx(l, true, GetLocationX(lu), GetLocationY(lu), 50, LinePointPerpendicularX, LinePointPerpendicularY, 50)
        set udg_i=udg_i+1
exitwhen udg_i==1000
endloop

endfunction
Uploaded files
29
Smeto, LinePointPerpendicular возвращает расстояние от прямой, проходящей через две точки, до третьей точки. Удобная вещь, чтоб сразу отфильтровать всех юнитов, которые находятся на прямой. Ты зачем-то туда молнию двигаешь.

Тегни меня в канале WE телеги или дискорда, расскажу как твой говнокод пофиксить.
21
Ну и геморрой конечно)
Имхо, как по мне, самый примитивный но более-менее рабочий способ
Распотрошить bj функции где вычисляются полярные координаты точек, и угол с расстоянием и переделать их под х у
Создать 2 группы - "темповую" и основную
Занести юнитов в "темповую" группу по радиусу в пункте А
Затем перенести их в основную группу через bj функцию GroupAddGroup
Повторить действия в пункте Б, В, Г итд по линии.
Таким образом в группе окажутся юниты "по линии"
Собственно урон или потом всем сразу наносить или поочередно, тут уже по вкусу)
Если поочерёдно с отсрочкой по времени, ещё придётся позаботиться о том, чтобы подобное работало, даже когда несколько подобных алгоритмов запущено до истечения предыдущих.
когда енамишь юнитов в одну и ту же группу несколько раз подряд, группа опустошается перед каждым енамом. Проверялось через FirstOfGroup
Replies (2)
21
nazarpunk, Вот тебе тест карта. Развлекайся ) Заенамились они заново, в чем сам можешь убедиться. Оригинальный варик, оригинальный джасс, без всяких этих ваших наворотов. Для полной чистоты теста.
Если б ты был прав, то цифры показали бы 5, 12, 18. Но ты неправ
29
EugeAl, сорян, по запаре написал тесты через жопу. Переписал и прогнал заново. Группы и правда очищаются перед вызовом GrouEnum*. Исправил доку.
To leave a comment please sign in to the site.