XGM Forum
Сайт - Статьи - Проекты - Ресурсы - Блоги

Форуме в режиме ТОЛЬКО ЧТЕНИЕ. Вы можете задать вопросы в Q/A на сайте, либо создать свой проект или ресурс.
Вернуться   XGM Forum > Warcraft> Академия: форум для вопросов> Jass
Ник
Пароль
Войти через VK в один клик
Сайт использует только имя.

Закрытая тема
 
Kapa6acvlk

offline
Опыт: 151
Активность:
Цепной стан, Живой юнит равен null?
Функция GroupRandom время от времени возвращает null, хотя вокруг полно живых юнитов, уже всю голову сломал, не могу понять что за проблема.

» код
Код:
function DistanceBetweenUnits takes unit A, unit B returns real
    local real dx = GetUnitX(B) - GetUnitX(A)
    local real dy = GetUnitY(B) - GetUnitY(A)
    return SquareRoot(dx * dx + dy * dy)
endfunction

function GroupRandom takes group g returns unit
    local unit array u 
    local integer i = 0
    local unit r = null
    loop
        set u[i] = FirstOfGroup(g)
        exitwhen u[i] == null
        call GroupRemoveUnit(g, u[i])
        if(GetUnitState(u[i], UNIT_STATE_LIFE) > 0.00 and GetUnitTypeId(u[i]) != 'u000')then
            set i = i + 1
        endif
    endloop
    set r = u[GetRandomInt(0,i-1)]
    loop
        set u[i] = null
        exitwhen i == 0
        set i = i - 1
    endloop
    if(r==null)then
        call BJDebugMsg("r = null")
    endif
    return r 
endfunction

function ChainStun takes nothing returns nothing
    local timer t = GetExpiredTimer()
    local real x = GetUnitX(LoadUnitHandle(udg_Hash,GetHandleId(t),1))
    local real y = GetUnitY(LoadUnitHandle(udg_Hash,GetHandleId(t),1))
    local unit d = CreateUnit(GetOwningPlayer(LoadUnitHandle(udg_Hash,GetHandleId(t),0)),'u000',x,y  ,0.0)
    local group g = CreateGroup()
    local unit u = null
    local integer i = LoadInteger(udg_Hash,GetHandleId(t),2)+1
    call SaveInteger(udg_Hash,GetHandleId(t),2,i)
    call GroupEnumUnitsInRange(g,x,y,400.0,null)
    call UnitAddAbility(d,'A001')
    call SetUnitAbilityLevel(d,'A001',GetUnitAbilityLevel(LoadUnitHandle(udg_Hash,GetHand  leId(t),0) ,'A000'))
    call UnitApplyTimedLife(d, 'BTLF', 10.0)
    loop
        set u = GroupRandom(g)
        exitwhen (u == null)
        if (IsPlayerEnemy(GetOwningPlayer(LoadUnitHandle(udg_Hash,GetHandleId(t),0)), GetOwningPlayer(u)) and GetUnitState(u, UNIT_STATE_LIFE) > 0.00 and IsUnitType(u, UNIT_TYPE_STRUCTURE) == false) then
            call IssueTargetOrder( d, "thunderbolt", u )
            call SaveUnitHandle(udg_Hash,GetHandleId(t),1,u)
            call TimerStart(t,DistanceBetweenUnits(d,u)/500.00,false,function ChainStun)
            exitwhen true     
        endif
    endloop 
    if(i >= 6 or u == null)then
        call FlushChildHashtable(udg_Hash, GetHandleId(t))
        call DestroyTimer(t)
        set t = null
        call BJDebugMsg("Clear")
    endif
    call DestroyGroup(g) 
    set t = null
    set g = null      
    set d = null
    set u = null 
endfunction

function Trig_ChainStun_Conditions takes nothing returns boolean
    return GetSpellAbilityId() == 'A000'
endfunction

function Trig_ChainStun_Actions takes nothing returns nothing
    local unit c = GetSpellAbilityUnit()
    local unit u = GetSpellTargetUnit()
    local timer t = CreateTimer()
    call SaveUnitHandle(udg_Hash,GetHandleId(t),0,c)
    call SaveUnitHandle(udg_Hash,GetHandleId(t),1,u)
    call SaveInteger(udg_Hash,GetHandleId(t),2,0)
    call TimerStart(t,DistanceBetweenUnits(c,u)/500.00,false,function ChainStun)
endfunction

//===========================================================================
function InitTrig_ChainStun takes nothing returns nothing
    set gg_trg_ChainStun = CreateTrigger(  )
    call TriggerRegisterAnyUnitEventBJ( gg_trg_ChainStun, EVENT_PLAYER_UNIT_SPELL_EFFECT )
    call TriggerAddCondition( gg_trg_ChainStun, Condition( function Trig_ChainStun_Conditions ) )
    call TriggerAddAction( gg_trg_ChainStun, function Trig_ChainStun_Actions )
endfunction
Прикрепленные файлы
Тип файла: w3x Chain_Stun.w3x (19.6 Кбайт, 6 просмотров )
Старый 14.03.2012, 02:57
Klop
Папа римский
offline
Опыт: 13,006
Активность:
попробуй так
» Code
function DistanceBetweenUnits takes unit A, unit B returns real
    local real dx = GetUnitX(B) - GetUnitX(A)
    local real dy = GetUnitY(B) - GetUnitY(A)
    return SquareRoot(dx * dx + dy * dy)
endfunction

function Check takes nothing returns boolean
    local timer t = GetExpiredTimer()
    local unit u = LoadUnitHandle(udg_Hash,GetHandleId(t),0)
    local boolean b = GetWidgetLife(GetFilterUnit())>0.405 and IsUnitEnemy(GetFilterUnit(),GetOwningPlayer(u))
    set u = null
    set t = null
    return b
endfunction

function GroupRandom takes group g returns unit
    local unit array u 
    local integer i = 0
    local unit r = null
    loop
        set u[i] = FirstOfGroup(g)
        exitwhen u[i] == null
        call GroupRemoveUnit(g, u[i])
        set i = i + 1
    endloop
    set r = u[GetRandomInt(0,i-1)]
    loop
        set u[i] = null
        exitwhen i == 0
        set i = i - 1
    endloop
    if(r==null)then
        call BJDebugMsg("r = null")
    endif
    return r 
endfunction

function ChainStun takes nothing returns nothing
    local timer t = GetExpiredTimer()
    local real x = GetUnitX(LoadUnitHandle(udg_Hash,GetHandleId(t),1))
    local real y = GetUnitY(LoadUnitHandle(udg_Hash,GetHandleId(t),1))
    local unit d = CreateUnit(GetOwningPlayer(LoadUnitHandle(udg_Hash,GetHandleId(t),0)),'u000',x,y,0.0)
    local group g = CreateGroup()
    local boolexpr b = Condition(function Check)
    local unit u = null
    local integer i = LoadInteger(udg_Hash,GetHandleId(t),2)+1
    call SaveInteger(udg_Hash,GetHandleId(t),2,i)
    call GroupEnumUnitsInRange(g,x,y,400.0,b)
    call UnitAddAbility(d,'A001')
    call SetUnitAbilityLevel(d,'A001',GetUnitAbilityLevel(LoadUnitHandle(udg_Hash,GetHandleId(t),0) ,'A000'))
    call UnitApplyTimedLife(d, 'BTLF', 10.0)
    loop
        set u = GroupRandom(g)
        exitwhen (u == null)
        if (IsPlayerEnemy(GetOwningPlayer(LoadUnitHandle(udg_Hash,GetHandleId(t),0)), GetOwningPlayer(u)) and GetUnitState(u, UNIT_STATE_LIFE) > 0.00 and IsUnitType(u, UNIT_TYPE_STRUCTURE) == false) then
            call IssueTargetOrder( d, "thunderbolt", u )
            call SaveUnitHandle(udg_Hash,GetHandleId(t),1,u)
            call TimerStart(t,DistanceBetweenUnits(d,u)/500.00,false,function ChainStun)
            exitwhen true     
        endif
    endloop 
    if(i >= 6 or u == null)then
        call FlushChildHashtable(udg_Hash, GetHandleId(t))
        call DestroyTimer(t)
        set t = null
        call BJDebugMsg("Clear")
    endif
    call DestroyBoolExpr(b)
    call DestroyGroup(g) 
    set b = null
    set t = null
    set g = null      
    set d = null
    set u = null 
endfunction

function Trig_ChainStun_Conditions takes nothing returns boolean
    return GetSpellAbilityId() == 'A000'
endfunction

function Trig_ChainStun_Actions takes nothing returns nothing
    local unit c = GetSpellAbilityUnit()
    local unit u = GetSpellTargetUnit()
    local timer t = CreateTimer()
    call SaveUnitHandle(udg_Hash,GetHandleId(t),0,c)
    call SaveUnitHandle(udg_Hash,GetHandleId(t),1,u)
    call SaveInteger(udg_Hash,GetHandleId(t),2,0)
    call TimerStart(t,DistanceBetweenUnits(c,u)/500.00,false,function ChainStun)
endfunction

//===========================================================================
function InitTrig_ChainStun takes nothing returns nothing
    set gg_trg_ChainStun = CreateTrigger(  )
    call TriggerRegisterAnyUnitEventBJ( gg_trg_ChainStun, EVENT_PLAYER_UNIT_SPELL_EFFECT )
    call TriggerAddCondition( gg_trg_ChainStun, Condition( function Trig_ChainStun_Conditions ) )
    call TriggerAddAction( gg_trg_ChainStun, function Trig_ChainStun_Actions )
endfunction
с boolexpr всё нормально работает
Старый 14.03.2012, 04:40
prog

offline
Опыт: 32,865
Активность:
Могу ошибаться, но мне кажется что корень зла кроется в переборке через loop - null при определенных условиях может затесаться в группу. Можно попробовать удалять из группы null перед взятием FirstOfGroup. Если сказал глупость - поправьте, но когда-то давно именно эта глупость решила мою проблему.
Старый 14.03.2012, 08:28
Kapa6acvlk

offline
Опыт: 151
Активность:
boolexpr вроде вызывает утечку, нужно обнулять?
Код:
call DestroyBoolexpr(b)
b=null

В функции Check GetExpiredTimer() Вернет ли нужный мне таймер? Ибо их у меня в карте не один десяток.
Старый 14.03.2012, 12:10
Klop
Папа римский
offline
Опыт: 13,006
Активность:
Kapa6acvlk, всегда так делаю нормально работает
и у меня в коде после сообщения clear они обнуляются)
Старый 14.03.2012, 12:46
Kapa6acvlk

offline
Опыт: 151
Активность:
А, извини не заметил, спасибо попробую. Поясни пожалуйста еще одну вещь, не первый раз встречаю GetWidgetLife(u)>0.405 в чем отличие от GetUnitState(u, UNIT_STATE_LIFE) > 0.00 Только ли в количестве параметров которые берет функция? И почему 0.405, юнит умирает при здоровье ниже 0.5 почему именно такая цифра?
Старый 14.03.2012, 13:21
Klop
Папа римский
offline
Опыт: 13,006
Активность:
Kapa6acvlk, хз так все норм мужики используют говорят что у Вара причуды и смертные могут иметь хп больше 0 но меньше 0.405
Старый 14.03.2012, 13:25
ScorpioT1000
Работаем
online
Опыт: отключен
function IsUnitDead takes unit u returns boolean
    return IsUnitType(u, UNIT_TYPE_DEAD) or GetUnitTypeId(u) < 1
endfunction
возвращает правду, если он мертв, удален, неверно стерт, равен нулю, хендл равен мусору итп
Старый 14.03.2012, 13:59
Kapa6acvlk

offline
Опыт: 151
Активность:
Все равно возвращает по 2 null. Если бросить болт в рабочего, который стоит 1, то в u[0] попадает рабочий, в u[1] - null u[2] - null, и естественно получается 50/50 либо рабочий либо null
» раскрыть
Код:
function IsUnitDead takes unit u returns boolean
    return IsUnitType(u, UNIT_TYPE_DEAD) or GetUnitTypeId(u) < 1
endfunction

function DistanceBetweenUnits takes unit A, unit B returns real
    local real dx = GetUnitX(B) - GetUnitX(A)
    local real dy = GetUnitY(B) - GetUnitY(A)
    return SquareRoot(dx * dx + dy * dy)
endfunction

function Check takes nothing returns boolean
    local timer t = GetExpiredTimer()
    local unit u = LoadUnitHandle(udg_Hash,GetHandleId(t),0)
    local boolean b = not(IsUnitDead(GetFilterUnit())) and IsUnitEnemy(GetFilterUnit(),GetOwningPlayer(u))
    set u = null
    set t = null
    return b
endfunction

function GroupRandom takes group g returns unit
    local unit array u 
    local integer i = 0
    local unit r = null
    loop
        set u[i] = FirstOfGroup(g)
            call BJDebugMsg(GetUnitName(u[i]))
        exitwhen u[i] == null
        call GroupRemoveUnit(g, u[i])
        set i = i + 1
    endloop
    set r = u[GetRandomInt(0,i-1)]
    loop
        set u[i] = null
        exitwhen i == 0
        set i = i - 1
    endloop
    if(r==null)then
        call BJDebugMsg("r = null")
    endif
    return r 
endfunction

function ChainStun takes nothing returns nothing
    local timer t = GetExpiredTimer()
    local real x = GetUnitX(LoadUnitHandle(udg_Hash,GetHandleId(t),1))
    local real y = GetUnitY(LoadUnitHandle(udg_Hash,GetHandleId(t),1))
    local unit d = CreateUnit(GetOwningPlayer(LoadUnitHandle(udg_Hash,GetHandleId(t),0)),'u000',x,y  ,0.0)
    local group g = CreateGroup()
    local boolexpr b = Condition(function Check)
    local unit u = null
    local integer i = LoadInteger(udg_Hash,GetHandleId(t),2)+1
    call SaveInteger(udg_Hash,GetHandleId(t),2,i)
    call GroupEnumUnitsInRange(g,x,y,400.0,b)
    call UnitAddAbility(d,'A001')
    call SetUnitAbilityLevel(d,'A001',GetUnitAbilityLevel(LoadUnitHandle(udg_Hash,GetHand  leId(t),0) ,'A000'))
    call UnitApplyTimedLife(d, 'BTLF', 10.0)
    loop
        set u = GroupRandom(g)
        exitwhen (u == null)
        if (IsPlayerEnemy(GetOwningPlayer(LoadUnitHandle(udg_Hash,GetHandleId(t),0)), GetOwningPlayer(u)) and not(IsUnitDead(u)) and IsUnitType(u, UNIT_TYPE_STRUCTURE) == false and u != LoadUnitHandle(udg_Hash,GetHandleId(t),1)) then
            call IssueTargetOrder( d, "thunderbolt", u )
            call SaveUnitHandle(udg_Hash,GetHandleId(t),1,u)
            call TimerStart(t,DistanceBetweenUnits(d,u)/500.00,false,function ChainStun)
            exitwhen true     
        endif
    endloop 
  //  if(i >= 6 or u == null)then
        call FlushChildHashtable(udg_Hash, GetHandleId(t))
        call DestroyTimer(t)
        set t = null
        call BJDebugMsg("Clear")
   // endif
    call DestroyBoolExpr(b)
    call DestroyGroup(g) 
    set b = null
    set t = null
    set g = null      
    set d = null
    set u = null 
endfunction

function Trig_ChainStun_Conditions takes nothing returns boolean
    return GetSpellAbilityId() == 'A000'
endfunction

function Trig_ChainStun_Actions takes nothing returns nothing
    local unit c = GetSpellAbilityUnit()
    local unit u = GetSpellTargetUnit()
    local timer t = CreateTimer()
    call SaveUnitHandle(udg_Hash,GetHandleId(t),0,c)
    call SaveUnitHandle(udg_Hash,GetHandleId(t),1,u)
    call SaveInteger(udg_Hash,GetHandleId(t),2,0)
    call TimerStart(t,DistanceBetweenUnits(c,u)/500.00,false,function ChainStun)
endfunction

//===========================================================================
function InitTrig_ChainStun takes nothing returns nothing
    set gg_trg_ChainStun = CreateTrigger(  )
    call TriggerRegisterAnyUnitEventBJ( gg_trg_ChainStun, EVENT_PLAYER_UNIT_SPELL_EFFECT )
    call TriggerAddCondition( gg_trg_ChainStun, Condition( function Trig_ChainStun_Conditions ) )
    call TriggerAddAction( gg_trg_ChainStun, function Trig_ChainStun_Actions )
endfunction
Старый 14.03.2012, 21:16
Klop
Папа римский
offline
Опыт: 13,006
Активность:
откуда цикл выполняется 3 раза если стоит один рабочий,я даже хз что сказать ещё)
Старый 14.03.2012, 22:28
Kapa6acvlk

offline
Опыт: 151
Активность:
Может ли быть так, дамми юнит добавляется в группу, но фильтр его удаляет и его значение равно null? Т.е. запись в группе о юните есть, но его самого там нет, бред какой-то получается.
Старый 14.03.2012, 23:34
Kapa6acvlk

offline
Опыт: 151
Активность:
Я разобрался, всем спасибо. Если кому интересно, вот рабочий код:
» КОД
Код:
function DistanceBetweenUnits takes unit A, unit B returns real
    local real dx = GetUnitX(B) - GetUnitX(A)
    local real dy = GetUnitY(B) - GetUnitY(A)
    return SquareRoot(dx * dx + dy * dy)
endfunction

function IsUnitDead takes unit u returns boolean
    return IsUnitType(u, UNIT_TYPE_DEAD) or GetUnitTypeId(u) < 1
endfunction

function Check takes nothing returns boolean
    local timer t = GetExpiredTimer()
    local unit u = LoadUnitHandle(udg_Hash,GetHandleId(t),0)
    local boolean b = not(IsUnitDead(GetFilterUnit())) and IsUnitEnemy(GetFilterUnit(),GetOwningPlayer(u)) and IsUnitType(u, UNIT_TYPE_STRUCTURE) == false
    set u = null
    set t = null
    return b
endfunction

function GroupRandom takes group g returns unit
    local unit array u 
    local integer i = 0
    local unit r = null
    local group p = CreateGroup()
    call GroupAddGroup(g,p)
    loop
        set u[i] = FirstOfGroup(p)
        exitwhen u[i] == null
        call GroupRemoveUnit(p, u[i])
        set i = i + 1
    endloop
    set r = u[GetRandomInt(0,i-1)]
    loop
        set u[i] = null
        exitwhen i <= 0
        set i = i - 1
    endloop
    if(r==null)then
        call BJDebugMsg("r = null")
    endif
    call DestroyGroup(p)
    set p = null
    return r 
endfunction

function ChainStun takes nothing returns nothing
    local timer t = GetExpiredTimer()
    local real x = GetUnitX(LoadUnitHandle(udg_Hash,GetHandleId(t),1))
    local real y = GetUnitY(LoadUnitHandle(udg_Hash,GetHandleId(t),1))
    local unit d = CreateUnit(GetOwningPlayer(LoadUnitHandle(udg_Hash,GetHandleId(t),0)),'u000',x,y  ,0.0)
    local group g = CreateGroup()
    local unit u = null
    local integer i = LoadInteger(udg_Hash,GetHandleId(t),2)+1
    local boolexpr b = Condition(function Check)
    call SaveInteger(udg_Hash,GetHandleId(t),2,i)
    call GroupEnumUnitsInRange(g,x,y,400.0,b)
    call UnitAddAbility(d,'A001')
    call SetUnitAbilityLevel(d,'A001',GetUnitAbilityLevel(LoadUnitHandle(udg_Hash,GetHand  leId(t),0) ,'A000'))
    call UnitApplyTimedLife(d, 'BTLF', 10.0)
    set u = GroupRandom(g)
    if(u == LoadUnitHandle(udg_Hash,GetHandleId(t),1))then
        call GroupRemoveUnit(g, u)
        set u = GroupRandom(g)    
    endif
        call IssueTargetOrder( d, "thunderbolt", u )
        call SaveUnitHandle(udg_Hash,GetHandleId(t),1,u)
        call TimerStart(t,DistanceBetweenUnits(d,u)/500.00,false,function ChainStun)   
    if(i >= 6 or u == null)then
        call FlushChildHashtable(udg_Hash, GetHandleId(t))
        call DestroyTimer(t)
        set t = null
    endif
    call DestroyBoolExpr(b)
    call DestroyGroup(g) 
    set t = null
    set g = null      
    set d = null
    set u = null
    set b = null 
endfunction

function Trig_ChainStun_Conditions takes nothing returns boolean
    return GetSpellAbilityId() == 'A000'
endfunction

function Trig_ChainStun_Actions takes nothing returns nothing
    local unit c = GetSpellAbilityUnit()
    local unit u = GetSpellTargetUnit()
    local timer t = CreateTimer()
    call SaveUnitHandle(udg_Hash,GetHandleId(t),0,c)
    call SaveUnitHandle(udg_Hash,GetHandleId(t),1,u)
    call SaveInteger(udg_Hash,GetHandleId(t),2,0)
    call TimerStart(t,DistanceBetweenUnits(c,u)/500.00,false,function ChainStun)
    set c = null
    set u = null
    set t = null
endfunction

//===========================================================================
function InitTrig_ChainStun takes nothing returns nothing
    set gg_trg_ChainStun = CreateTrigger(  )
    call TriggerRegisterAnyUnitEventBJ( gg_trg_ChainStun, EVENT_PLAYER_UNIT_SPELL_EFFECT )
    call TriggerAddCondition( gg_trg_ChainStun, Condition( function Trig_ChainStun_Conditions ) )
    call TriggerAddAction( gg_trg_ChainStun, function Trig_ChainStun_Actions )
endfunction
Старый 15.03.2012, 18:45
Закрытая тема

Опции темы Поиск в этой теме
Поиск в этой теме:

Расширенный поиск

Ваши права в разделе
Вы не можете создавать темы
Вы не можете отвечать на сообщения
Вы не можете прикреплять файлы
Вы можете скачивать файлы

BB-коды Вкл.
[IMG] код Вкл.
HTML код Выкл.
Быстрый переход



Часовой пояс GMT +3, время: 23:25.