(xgm.guru/p/100/216551) - предыдущая тема.
Ранее хотел создать скилл в GUI, но послушав советы, понял, что лучшее будет написать его на Jass (да и давно пора его изучить, так как смогу создавать скиллы более гибко).
Написал код в Редакторе Триггеров. Скилл - все тот же сюрикен, летящий в определенную точку и возвращающийся назад, по пути дамажащий вражин. Но пока этот сюрикен даже лететь отказывается. Почитав статьи на форуме, да посмотрев всяких видосиков по теме jass, я понял, что я что-то не понял. А именно - как работают таймеры. Точнее, принцип понял, но как их засунуть за место привычного ожидания (Wait) - пока не разобрался. Это же касается использования хэш-таблицы, так как для таймера, она вроде как, маст хэв. Поэтому прошу хелпы, добрые люди. Вот код скилла, в нем есть неработающий таймер (он там один), и он отвечает за полет сюрикена в конечную точку. Прошу указать мне, где косяк.
З.Ы. - на всякий случай, прикрепляю саму карту.
function Trig_Suriken_Conditions takes nothing returns boolean
    if ( not ( GetSpellAbilityId() == 'A01G' ) ) then
        return false
    endif
    return true
endfunction

function InitTrig_Hash takes nothing returns nothing
    set udg_Hash = InitHashtableBJ( )
endfunction

function Flyin takes nothing returns nothing
    local timer ping = GetExpiredTimer()
    local unit caster = LoadUnitHandle(udg_Hash,GetHandleId(ping),1)
    local unit suriken = LoadUnitHandle(udg_Hash,GetHandleId(ping),2)
    local location kursor = LoadLocationHandle(udg_Hash,GetHandleId(ping),3)
    local location endfly = LoadLocationHandle(udg_Hash,GetHandleId(ping),4)
    call SetUnitPositionLoc(suriken,PolarProjectionBJ(GetUnitLoc(suriken),10.00,AngleBetweenPoints(GetUnitLoc(suriken),endfly)))
    call DestroyTimer(ping)
    set ping = null
    set caster = null
    set suriken = null
    set kursor = null
    set endfly = null
endfunction

function Trig_Suriken_Actions takes nothing returns nothing
    local timer ping = CreateTimer()
    local integer countflyin = 1
    local unit caster = GetSpellAbilityUnit()
    local location kursor = GetSpellTargetLoc()
    local location endfly = PolarProjectionBJ(GetUnitLoc(caster),2000.00,AngleBetweenPoints(GetUnitLoc(caster),kursor))
    local real povorot = GetUnitFacing(caster)
    local unit suriken = CreateUnitAtLoc(GetOwningPlayer(caster),'u001',PolarProjectionBJ(GetUnitLoc(caster),200.00,AngleBetweenPoints(GetUnitLoc(caster),kursor)),povorot)
    loop
        exitwhen countflyin == 100
        if DistanceBetweenPoints(GetUnitLoc(suriken),endfly) >= 20 then
            call SaveUnitHandle(udg_Hash,GetHandleId(ping),1,caster)
            call SaveUnitHandle(udg_Hash,GetHandleId(ping),2,suriken)
            call SaveLocationHandle(udg_Hash,GetHandleId(ping),3,kursor)
            call SaveLocationHandle(udg_Hash,GetHandleId(ping),4,endfly)
            call TimerStart(ping,0.10,true,function Flyin)
        endif
        set countflyin = countflyin + 1
    endloop
    call FlushChildHashtable(udg_Hash, GetHandleId(ping))
    set ping = null
    set caster = null
    set suriken = null
    set kursor = null
    set endfly = 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 )
endfunction

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

Это достаточно неправильный код, везде BJ функции, location и т.д.
Сначала потренируйся просто переместить любого юнита в нужные тебе координаты.
Вместо location используй координаты "x" и "y"
К примеру:
Вычисление угла между координатами (в радианах)
a = Atan2(m.y - GetUnitY(u), m.x - GetUnitX(u))
//m.x и m.y это "конечная" точка, в которую юнит должен переместиться
Чтобы вычислить "x" смещение от места где стоит юнит с нужными тебе углом (угол "a" в радианах):
x = GetUnitX(u) + 2000. * Cos(a)
//Там где 2000. - это нужное тебе расстояние, можно записать как 2000.00 (без разницы)
Чтобы вычислить "y" смещение от места где стоит юнит с нужными тебе углом (угол "a" в радианах):
y = GetUnitY(u) + 2000. * Sin(a)
//Там где 2000. - это нужное тебе расстояние, можно записать как 2000.00 (без разницы)
Ну а потом
SetUnitX(u, x)
SetUnitY(u, y)
Далее уже можешь передвигать юнита каждые 0.03 секунды по 5 точек.
К примеру тот же код что выше - заранее вычисляешь им координаты где должен в итоге оказаться твой юнит
Или если у тебя уже есть готовые координаты, к примеру если юнит летит в точку кастования способности
И этим же кодом выше передвигаешь юнита по 5 точек каждые 0.03 секунды
А чтобы поймать окончание "передвижения" просто каждый раз сравнивай дистанцию, если она будет меньше 10, то уничтожай таймер и т.д
Там где 10 я имел ввиду кол-во точек на которое передвигается юнит + 5
Вычисление дистанции между координатами
local real dx = m.x - x
local real dy = m.y - y
local real d = SquareRoot(dx * dx + dy * dy)
//Там где m.x и m.y - это конечные координаты
//А "x" и "y" - это текущие координаты юнита
`
ОЖИДАНИЕ РЕКЛАМЫ...
1
18
6 лет назад
Отредактирован Hodor
1
Это достаточно неправильный код, везде BJ функции, location и т.д.
Сначала потренируйся просто переместить любого юнита в нужные тебе координаты.
Вместо location используй координаты "x" и "y"
К примеру:
Вычисление угла между координатами (в радианах)
a = Atan2(m.y - GetUnitY(u), m.x - GetUnitX(u))
//m.x и m.y это "конечная" точка, в которую юнит должен переместиться
Чтобы вычислить "x" смещение от места где стоит юнит с нужными тебе углом (угол "a" в радианах):
x = GetUnitX(u) + 2000. * Cos(a)
//Там где 2000. - это нужное тебе расстояние, можно записать как 2000.00 (без разницы)
Чтобы вычислить "y" смещение от места где стоит юнит с нужными тебе углом (угол "a" в радианах):
y = GetUnitY(u) + 2000. * Sin(a)
//Там где 2000. - это нужное тебе расстояние, можно записать как 2000.00 (без разницы)
Ну а потом
SetUnitX(u, x)
SetUnitY(u, y)
Далее уже можешь передвигать юнита каждые 0.03 секунды по 5 точек.
К примеру тот же код что выше - заранее вычисляешь им координаты где должен в итоге оказаться твой юнит
Или если у тебя уже есть готовые координаты, к примеру если юнит летит в точку кастования способности
И этим же кодом выше передвигаешь юнита по 5 точек каждые 0.03 секунды
А чтобы поймать окончание "передвижения" просто каждый раз сравнивай дистанцию, если она будет меньше 10, то уничтожай таймер и т.д
Там где 10 я имел ввиду кол-во точек на которое передвигается юнит + 5
Вычисление дистанции между координатами
local real dx = m.x - x
local real dy = m.y - y
local real d = SquareRoot(dx * dx + dy * dy)
//Там где m.x и m.y - это конечные координаты
//А "x" и "y" - это текущие координаты юнита
Принятый ответ
0
13
6 лет назад
0
Нужно еще почитать как делается движение по координатам...
Цыкл не нужен
В функции flyin после перемещения, пересохраняй позицию юнита suriken
Не видно действия запускающего функцию с инитиализацией хеша
для более плавного перемещения запускай таймер на 0.04сек
1
18
6 лет назад
1
Borodach:
Нужно еще почитать как делается движение по координатам...
там нету ничего сложного, наоборот - с координатами удобнее и проще + код более читаемый и оптимизированный, всё что нужно я написал выше)
0
5
6 лет назад
0
UrsaBoss:
Это достаточно неправильный код, везде BJ функции, location и т.д.
Сначала потренируйся просто переместить любого юнита в нужные тебе координаты.
Вместо location используй координаты "x" и "y"
К примеру:
Вычисление угла между координатами (в радианах)
a = Atan2(m.y - GetUnitY(u), m.x - GetUnitX(u))
//m.x и m.y это "конечная" точка, в которую юнит должен переместиться
Чтобы вычислить "x" смещение от места где стоит юнит с нужными тебе углом (угол "a" в радианах):
x = GetUnitX(u) + 2000. * Cos(a)
//Там где 2000. - это нужное тебе расстояние, можно записать как 2000.00 (без разницы)
Чтобы вычислить "y" смещение от места где стоит юнит с нужными тебе углом (угол "a" в радианах):
y = GetUnitY(u) + 2000. * Sin(a)
//Там где 2000. - это нужное тебе расстояние, можно записать как 2000.00 (без разницы)
Ну а потом
SetUnitX(u, x)
SetUnitY(u, y)
Далее уже можешь передвигать юнита каждые 0.03 секунды по 5 точек.
К примеру тот же код что выше - заранее вычисляешь им координаты где должен в итоге оказаться твой юнит
Или если у тебя уже есть готовые координаты, к примеру если юнит летит в точку кастования способности
И этим же кодом выше передвигаешь юнита по 5 точек каждые 0.03 секунды
А чтобы поймать окончание "передвижения" просто каждый раз сравнивай дистанцию, если она будет меньше 10, то уничтожай таймер и т.д
Там где 10 я имел ввиду кол-во точек на которое передвигается юнит + 5
Вычисление дистанции между координатами
local real dx = m.x - x
local real dy = m.y - y
local real d = SquareRoot(dx * dx + dy * dy)
//Там где m.x и m.y - это конечные координаты
//А "x" и "y" - это текущие координаты юнита
Это боллее сложный способ для меня, так как я напрочь забыл весь матан, который учил)) Но я попробую, так как, в действительности, если знать подобные формулы - это реально проще. А все таки, почему таймер не сработал? Мне бы понять, где там реально ошибка) Я его определенно вставил криво.
0
18
6 лет назад
0
Lillikon, это не требует знаний математики, просто нужно запомнить формулы
Насчет таймера - Borodach дал ответ
Чтобы оставить комментарий, пожалуйста, войдите на сайт.