Проблема с циклом

Добавлен
Есть код:
function OppositeFilter takes nothing returns boolean
    return IsPlayerInForce(GetOwningPlayer(GetFilterUnit()), udg_Opposite)
endfunction
    
function CalculatePercentOfAttackers takes unit Point returns integer
    local integer p
    local integer s
    
    local integer A
    local integer D
    
    local location loc = GetUnitLoc(Point)
    local group g = GetUnitsInRangeOfLocMatching( 1280.00, loc, Condition(function OppositeFilter) )
    local unit f
    
    if CountUnitsInGroup(g) > 0 then
        call Say("Loop starts")
        loop
            set f = FirstOfGroup(g)
            if f == null then
                call Say("Loop ends")
            endif
            exitwhen f == null
            if IsPlayerAlly( GetOwningPlayer(Point), GetOwningPlayer(f)) == true then
                set D = D + GetUnitLevel(f)
                call Say(GetUnitName(f)+I2S(GetHandleId(f))+" is defender.")
            elseif IsPlayerEnemy( GetOwningPlayer(Point), GetOwningPlayer(f)) == true then
                set A = A + GetUnitLevel(f)
                call Say(GetUnitName(f)+I2S(GetHandleId(f))+" is attacker.")
            else
                call Say(GetUnitName(f)+I2S(GetHandleId(f))+" is neutral.")
            endif            
            call GroupRemoveUnit( g, f )
        endloop
        call Say("Defenders level="+I2S(D)+"Attackers level="+I2S(A))
        set s = A + D
        if s == 0 then
            set s = 1
        endif    
        set p = A*100/s
    else    
        set p = 0    
    endif
    
    call RemoveLocation(loc)
    set loc = null
    call DestroyGroup(g)
    set g = null
    set f = null
    
    call Say( GetUnitName(Point)+I2S(GetHandleId(Point))+" calculations result = "+I2S(p) )
    return p
endfunction
Его предназначение — посчитать соотношение сил вокруг точки. Это нужно для системы захвата точек. Но сам цикл почему-то не работает. Кто может сказать мне, почему?

function CalculatePercentOfAttackers takes unit Point returns integer
    local integer p = 0
    local integer s = 0
    
    local integer A = 0
    local integer D = 0
   
    local group g = CreateGroup()
    local unit f
    
    GroupEnumUnitsInRange(g, GetWidgetX(Point), GetWidgetY(Point), 1280., null)
    if CountUnitsInGroup(g) > 0 then
        call Say("Loop starts")
        loop
            set f = FirstOfGroup(g)
            if f == null then
                call Say("Loop ends")
            endif
            exitwhen f == null
            if (IsUnitInForce(f, udg_Opposite) then
                if IsUnitAlly(Point, GetOwningPlayer(f)) then
                    set D = D + GetUnitLevel(f)
                    call Say(GetUnitName(f)+I2S(GetHandleId(f))+" is defender.")
                elseif IsUnitEnemy(Point, GetOwningPlayer(f)) then
                    set A = A + GetUnitLevel(f)
                    call Say(GetUnitName(f)+I2S(GetHandleId(f))+" is attacker.")
                else
                    call Say(GetUnitName(f)+I2S(GetHandleId(f))+" is neutral.")
                endif
            endif
            call GroupRemoveUnit(g, f)
        endloop
        call Say("Defenders level="+I2S(D)+"Attackers level="+I2S(A))
        set s = A + D
        if s == 0 then
            set s = 1
        endif    
        set p = A*100/s
    else    
        set p = 0    
    endif
    call Say(GetUnitName(Point)+I2S(GetHandleId(Point))+" calculations result = "+I2S(p))

    call DestroyGroup(g)
    set g = null
    set f = null
    
    return p
endfunction
Числовые и реальные переменные инициализируйте, иначе в качестве их значения выступит всякий числовой мусор. Поправил Вам код, по логике должен работать, проверить не могу :)
`
ОЖИДАНИЕ РЕКЛАМЫ...
20
Помимо того, что код грустьпичаль,
function OppositeFilter takes nothing returns boolean
return IsPlayerInForce(GetOwningPlayer(GetFilterUnit()), udg_Opposite)
endfunction
магический код.
Какие сообщения выдаются в игре и какие игроки входят в udg_Opposite?
Короче ситуацию в целом опишите
set s = A + D
никогда не будет равно нулю, согласно коду
Вц3 давно не трогал, но, вроде, после кода
local integer A
A!=0
Возможно дизинфа.
22
Какие сообщения выдаются в игре
Только те, которые не входят в цикл. Всё что внутри цикла и сообщение сразу после него (Say("Defenders level="...)) не отображается.
и какие игроки входят в udg_Opposite?
Те, которые могут претендовать на владение точкой, а именно игроки номер: 0, 1, 11.
никогда не будет равно нулю, согласно коду
Да, я всё время забываю убрать это условие.
A!=0
Почему?
Короче ситуацию в целом опишите
Задумано так:
Периодический таймер запускает функцию CalculatePercentOfAttackers. Эта функция считает количество противников владельца точки и количество союзников владельца точки в радиусе от этой самой точки. Затем, нехитрая формула находит количество врагов в процентах из общей массы:
Соотношение произведения количества врагов на сто к сумме врагов и союзников.
Затем, функция возвращает результат. Если он больше 66, то запускается функция, которая меняет владельца точки. Всё просто, вплоть до глупости.
Проблема в самом цикле. Такое впечатление, будто он бесконечный по какой-то причине. Юниты в группу заносятся нормально.
20
Если уж не терпится юзать через юнита это дело(в радиусе юнита пикать) вместо локаций юзай координаты, это менее затратно, не смотря на бОльшее кол-во кода. Не юзай проверку через цикл, ForGroup, если не ошибаюсь, лучше(поиск в помощь, причин не помню) Офк пофикси логическую часть, + тот самый юнит Point может засчитываться какой-то команде(не знаю всего кода, лишь теория).
Отображается ли Loop starts? Если нет- проблема в фильтре.
22
Офк пофикси логическую часть
Всмысле?
тот самый юнит Point может засчитываться какой-то команде(не знаю всего кода, лишь теория)
Нет, он не засчитывается
Отображается ли Loop starts?
Да
Если нет- проблема в фильтре.
Но ведь юниты нормально добавляються в группу.
Не юзай проверку через цикл, ForGroup, если не ошибаюсь, лучше(поиск в помощь, причин не помню)
И как тогда я посчитаю уровни юнитов, если всё будет в отдельной функции?
9
function CalculatePercentOfAttackers takes unit Point returns integer
    local integer p = 0
    local integer s = 0
    
    local integer A = 0
    local integer D = 0
   
    local group g = CreateGroup()
    local unit f
    
    GroupEnumUnitsInRange(g, GetWidgetX(Point), GetWidgetY(Point), 1280., null)
    if CountUnitsInGroup(g) > 0 then
        call Say("Loop starts")
        loop
            set f = FirstOfGroup(g)
            if f == null then
                call Say("Loop ends")
            endif
            exitwhen f == null
            if (IsUnitInForce(f, udg_Opposite) then
                if IsUnitAlly(Point, GetOwningPlayer(f)) then
                    set D = D + GetUnitLevel(f)
                    call Say(GetUnitName(f)+I2S(GetHandleId(f))+" is defender.")
                elseif IsUnitEnemy(Point, GetOwningPlayer(f)) then
                    set A = A + GetUnitLevel(f)
                    call Say(GetUnitName(f)+I2S(GetHandleId(f))+" is attacker.")
                else
                    call Say(GetUnitName(f)+I2S(GetHandleId(f))+" is neutral.")
                endif
            endif
            call GroupRemoveUnit(g, f)
        endloop
        call Say("Defenders level="+I2S(D)+"Attackers level="+I2S(A))
        set s = A + D
        if s == 0 then
            set s = 1
        endif    
        set p = A*100/s
    else    
        set p = 0    
    endif
    call Say(GetUnitName(Point)+I2S(GetHandleId(Point))+" calculations result = "+I2S(p))

    call DestroyGroup(g)
    set g = null
    set f = null
    
    return p
endfunction
Числовые и реальные переменные инициализируйте, иначе в качестве их значения выступит всякий числовой мусор. Поправил Вам код, по логике должен работать, проверить не могу :)
Принятый ответ
22
Числовые и реальные переменные инициализируйте, иначе в качестве их значения выступит всякий числовой мусор.
Как всегда я прокалываюсь на мелочах — мне ведь Hellfim уже это объяснял! Спасибо.
Поправил Вам код, по логике должен работать, проверить не могу :)
Благодарю, я чуток поправил под свои нужды и всё заработало.
Чтобы оставить комментарий, пожалуйста, войдите на сайт.