(xgm.guru/p/100/216603) - Предыдущая тема.
Предыстория та же. Делаю скилл сюрикена на JASS (летит в точку и возвращается назад, по пути раздавая люлей врагам). Скилл доделал и он работает, но оставляет много утечек.
Наполовину переписал код по совету UrsaBoss, попутно убирая все BJ, но сейчас в очередной раз залип на пустом месте. Для движения сюрикена я использовал PolarProjectionBJ, но этот BJ надобно убрать, но как грамотно рассписать все расчеты по формуле - понять не могу.
Здесь требуется избавиться от BJ:
call SetUnitPositionLoc(suriken,PolarProjectionBJ(GetUnitLoc(suriken),20.00,AngleBetweenPoints(GetUnitLoc​(suriken),GetUnitLoc(caster))))
Код целиком:
function Trig_Suriken_Conditions takes nothing returns boolean
    return GetSpellAbilityId() == 'A01G'
endfunction

function Flyin takes nothing returns nothing
    local timer t = GetExpiredTimer()
    local integer h = GetHandleId(t)
    local unit caster = LoadUnitHandle(udg_Hash,GetHandleId(t),1)
    local unit suriken = LoadUnitHandle(udg_Hash,GetHandleId(t),2)
    local location endfly = LoadLocationHandle(udg_Hash,GetHandleId(t),3)
    local group pool = CreateGroup()
    local unit g
    local real dx = GetLocationX(endfly) - GetLocationX(GetUnitLoc(suriken))
    local real dy = GetLocationY(endfly) - GetLocationY(GetUnitLoc(suriken))
    if SquareRoot(dx * dx + dy * dy) >= 10 then
        call SetUnitPositionLoc(suriken,PolarProjectionBJ(GetUnitLoc(suriken),20.00,GetUnitFacing(suriken)))
        call GroupEnumUnitsInRange(pool,GetUnitX(suriken),GetUnitY(suriken),150.00,null)
        loop
            set g = FirstOfGroup(pool)
            exitwhen g == null
            if IsUnitEnemy(g, GetOwningPlayer(caster)) == true then
                call UnitDamageTarget(caster,g,40.00,false,false,null,null,null)
            endif
            call GroupRemoveUnit(pool,g)
        endloop
    else
        call DestroyTimer(t)
        call FlushChildHashtable(udg_Hash,h)
    endif
    call RemoveLocation(endfly)
    set t = null
    set h = 0
    set caster = null
    set suriken = null
    set endfly = null
    set pool = null
    set g = null
    set dx = 0
    set dy = 0
endfunction

function Flyout takes nothing returns nothing
    local timer t = GetExpiredTimer()
    local integer h = GetHandleId(t)
    local unit caster = LoadUnitHandle(udg_Hash,GetHandleId(t),1)
    local unit suriken = LoadUnitHandle(udg_Hash,GetHandleId(t),2)
    local real endfly_x = LoadReal(udg_Hash,GetHandleId(t),3)
    local real endfly_y = LoadReal(udg_Hash,GetHandleId(t),4)
    local group pool = CreateGroup()
    local unit g
    local real dx = GetLocationX(GetUnitLoc(caster)) - GetLocationX(GetUnitLoc(suriken))
    local real dy = GetLocationY(GetUnitLoc(caster)) - GetLocationY(GetUnitLoc(suriken))
    if SquareRoot(dx * dx + dy * dy) >= 50 then
        call SetUnitPositionLoc(suriken,PolarProjectionBJ(GetUnitLoc(suriken),20.00,AngleBetweenPoints(GetUnitLoc(suriken),GetUnitLoc(caster))))
        call GroupEnumUnitsInRange(pool,GetUnitX(suriken),GetUnitY(suriken),150.00,null)
        loop
            set g = FirstOfGroup(pool)
            exitwhen g == null
            if IsUnitEnemy(g, GetOwningPlayer(caster)) == true then
                call UnitDamageTarget(caster,g,40.00,false,false,null,null,null)
            endif
            call GroupRemoveUnit(pool,g)
        endloop
    else
        call KillUnit(suriken)
        call TriggerSleepAction(1.0)
        call RemoveUnit(suriken)
        call DestroyTimer(t)
    endif
    set t = null
    set h = 0
    set caster = null
    set suriken = null
    set endfly_x = 0
    set endfly_y = 0
    set pool = null
    set g = null
    set dx = 0
    set dy = 0
endfunction

function Trig_Suriken_Actions takes nothing returns nothing
    local timer t = CreateTimer()
    local unit caster = GetSpellAbilityUnit()
    local unit suriken = CreateUnit(GetOwningPlayer(caster),'u001',GetUnitX(caster),GetUnitY(caster),GetUnitFacing(caster))
    local real endfly_x = GetUnitX(caster) + 2000.00 * Cos(GetUnitFacing(caster) * bj_DEGTORAD)
    local real endfly_y = GetUnitY(caster) + 2000.00 * Sin(GetUnitFacing(caster) * bj_DEGTORAD)
    call SaveUnitHandle(udg_Hash,GetHandleId(t),1,caster)
    call SaveUnitHandle(udg_Hash,GetHandleId(t),2,suriken)
    call SaveReal(udg_Hash,GetHandleId(t),3,endfly_x)
    call SaveReal(udg_Hash,GetHandleId(t),4,endfly_x)
    call TimerStart(t,0.02,true,function Flyin)
    call TriggerSleepAction(1.7)
    call SaveUnitHandle(udg_Hash,GetHandleId(t),1,caster)
    call SaveUnitHandle(udg_Hash,GetHandleId(t),2,suriken)
    call SaveReal(udg_Hash,GetHandleId(t),3,endfly_x)
    call SaveReal(udg_Hash,GetHandleId(t),4,endfly_x)
    call TimerStart(t,0.02,true,function Flyout)
    call TriggerSleepAction(3.0)
    call DestroyTimer(t)
    set caster = null
    set suriken = null
    set endfly_x = 0
    set endfly_y = 0
    set t = null
endfunction

//===========================================================================
    function InitTrig_Suriken takes nothing returns nothing
        set gg_trg_Suriken = CreateTrigger( )
        call TriggerRegisterAnyUnitEventBJ( gg_trg_Suriken, EVENT_PLAYER_UNIT_SPELL_EFFECT )
        call TriggerAddCondition( gg_trg_Suriken, Condition( function Trig_Suriken_Conditions ) )
        call TriggerAddAction( gg_trg_Suriken, function Trig_Suriken_Actions )
        
        set udg_Hash = InitHashtableBJ( )
    endfunction
Карта:
З.Ы. Если кто может помочь с вопросами на чистом энтузиазме - могу скинуть DS.
З.Ы.Ы. Дабы не дергать форум много раз, а то уже 4 темы создал))

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

range * Cos(a * bj_DEGTORAD)
должно получится так:
a = Atan2(endfly_y - GetUnitY(suriken), endfly_x - GetUnitX(suriken))
SetUnitX(suriken, GetUnitX(suriken) + 20.00 * Cos(a))
SetUnitY(suriken, GetUnitY(suriken) + 20.00 * Sin(a))
`
ОЖИДАНИЕ РЕКЛАМЫ...

Показан только небольшой набор комментариев вокруг указанного. Перейти к актуальным.
0
26
6 лет назад
Отредактирован Hate
0
call TriggerSleepAction() 
убрать

бж функции для исследования замечательно раскрываются с зажатием ctrl и кликом по ним

обнулять реалки довольно мощно

сравнивать логические с логическими так же не нужно

вместо точек используйте координаты

это на первое время

и да, закрывайте созданные вопросы если на них дали ответ
0
5
6 лет назад
0
Hate:
call TriggerSleepAction() 
убрать

бж функции для исследования замечательно раскрываются с зажатием ctrl и кликом по ним

обнулять реалки довольно мощно

сравнивать логические с логическими так же не нужно

вместо точек используйте координаты

это на первое время

и да, закрывайте созданные вопросы если на них дали ответ
Если убрать call TriggerSleepAction(), то следом после таймера Flyin, который отвечает за полет сюрикена в точку endfly_x,endfly_y, запуститься таймер Flyout, который отвечает за полет сюрикена обратно к caster. В итоге сюрикен никуда не полетит и сразу исчезнет(проверено).
бж функции для исследования замечательно раскрываются с зажатием ctrl и кликом по ним
Это я и так знал, но я запутался в формулах, а не в принципе.
вместо точек используйте координаты
Это и пытаюсь сделать, избавившись от них сначала в функции Flyout (функцию Flyin пока не переписывал)
2
26
6 лет назад
Отредактирован Hate
2
я не имел ввиду буквально убрать слип не заменив ничем. все что вы делаете двумя функциями через слип должно делаться одной без него
Это я и так знал, но я запутался в формулах, а не в принципе.
a = угол направления
x + range * Cos(a * bj_DEGTORAD)
y + range * Sin(a * bj_DEGTORAD)
0
5
6 лет назад
0
Hate:
я не имел ввиду буквально убрать слип не заменив ничем. все что вы делаете двумя функциями через слип должно делаться одной без него
Это я и так знал, но я запутался в формулах, а не в принципе.
a = угол направления
x + range * Cos(a * bj_DEGTORAD)
y + range * Sin(a * bj_DEGTORAD)
Как вставить в эту формулу то, что suriken сдвигается на 20 едениц?
0
26
6 лет назад
0
Как вставить в эту формулу то, что suriken сдвигается на 20 едениц?
range = дистанция / (время полета / период срабатывания)
нахождение времени дистанции и скорости это 4 класс математики
2
18
6 лет назад
Отредактирован Hodor
2
Там где ты уничтожаешь таймер в Flyin - можно заного запустить таймер и уже юзать Flyout
И ещё ты во Flyin используешь "location endfly" которая там просто висит, наверное ты забыл поменять на endfly_x/y
Вместо многократного использования GetHandleId(t) - занеси всё в одну integer и используй её
Обнулять нужно только указатели на игровой объект, обнулять real/integer/boolean/string не нужно.
Есть исключения, если игровой объект в игре будет всю игру (к примеру игрок) - то указатель на него не обязательно обнулять
0
28
6 лет назад
0
Не все BJ функции зло. Злом являются те, кто использует локации, группы, кланы, делают вызов 1-й функции без доп. аргументов.
0
18
6 лет назад
Отредактирован Hodor
0
Lillikon
На 20 единиц опасно сдвигать, т.к может не сработать условие на то что дистанция < 10 и сюрикен улетит за пределы карты.
Надо поставить условие чтобы дистанция была < 25, и вместо узнавания угла сюрикена - использовать угол между координатами (так он хотябы не улетит, если ошибешься с расчетами)
Вычисление угла в радианах
a = Atan2(m.y - GetUnitY(u), m.x - GetUnitX(u))
m.x и m.y это "конечная" точка, в которую юнит должен переместиться
И не надо переводить радианы в градусы, просто косинус и синус вычисляешь чтобы переместить юнита на 20
x = GetUnitX(u) + 20. * Cos(a)
y = GetUnitY(u) + 20. * Sin(a)
Показан только небольшой набор комментариев вокруг указанного. Перейти к актуальным.
Чтобы оставить комментарий, пожалуйста, войдите на сайт.