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

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

Ответ
 
Nerevar
I'll be back!
offline
Опыт: 18,352
Активность:
Помощь с прерываемым спелом
Решил я освоить ещё и написание прерываемых спелов,но столкнулся с проблемой - вместо 5 ожидаемых снарядов вылетает всего 1(в конце каста) и летит в рандомную сторону до упора карты.Писал спел 2.5 часа - уже не знаю что с ним сделать
function Parabola takes real h, real d, real x returns real
    return (4 * h / d) * (d - x) * (x / d)
endfunction

function Trig_fiverockets_Conditions takes nothing returns boolean
    return GetSpellAbilityId() == 'A02X'
endfunction

function fiverockets_m takes nothing returns nothing
local timer t=GetExpiredTimer()
local integer id=GetHandleId(t)
local real rdistance=LoadReal(udg_ah,id,S2I("RDistance"))+20
local real distance=LoadReal(udg_ah,id,S2I("Distance"))-20
local real angle=LoadReal(udg_ah,id,S2I("Angle"))
local unit rocket=LoadUnitHandle(udg_ah,id,S2I("Rocket"))
local integer level=LoadInteger(udg_ah,id,S2I("Level"))
local real x=GetUnitX(rocket)
local real y=GetUnitY(rocket)
local unit dammi
if distance<=10 or IsTerrainPathable(x+20*CosBJ(angle),y+20*SinBJ(angle),PATHING_TYPE_FLYABILITY) == true then
    call SetUnitZ( rocket, 0)
    call KillUnit(rocket)//удаление ракеты-снаряда
    set dammi=CreateUnit(GetOwningPlayer(rocket),'u00A',x,y,0)//создание дамика,применяющего топ
    call UnitAddAbility(dammi,'A02Y')//добавление ему топа
    call SetUnitAbilityLevel(dammi,'A02Y',level)
    call IssueImmediateOrder( dammi, "thunderclap" )
    call UnitApplyTimedLife(dammi,'BTLF',3)
    call FlushChildHashtable(udg_ah,id)
    call PauseTimer(t)
    call DestroyTimer(t)
else 
    call SetUnitZ( rocket,Parabola(distance+rdistance,rdistance,(distance+rdistance)/2))
    call SetUnitX(rocket,x+20*CosBJ(angle))
    call SetUnitY(rocket,y+20*SinBJ(angle))
endif
set dammi=null
set t=null
set rocket=null
endfunction

function fiverockets_timer takes nothing returns nothing
local timer t=GetExpiredTimer()
local integer id=GetHandleId(t)
local integer trgid=LoadInteger(udg_ah,id,S2I("TrgId"))
local real duration=LoadReal(udg_ah,id,trgid)
local unit caster=LoadUnitHandle(udg_ah,id,S2I("Caster"))
local real angle=GetUnitFacing(caster)
local real x=GetUnitX(caster)
local real y=GetUnitY(caster)
local integer level=LoadInteger(udg_ah,id,S2I("level"))
local real tx=x+duration*200*CosBJ(angle)
local real ty=x+duration*200*SinBJ(angle)
local real distance=SquareRoot((tx - x) * (tx - x) + (ty - y) * (ty - y))
local integer remove=LoadInteger(udg_ah,trgid,S2I("remove"))
local timer tt=CreateTimer()
local integer idtt=GetHandleId(tt)
local unit rocket
if duration==2.5 or remove==1 then
    call FlushChildHashtable(udg_ah,id)
    call PauseTimer(t)
    call DestroyTimer(t)
else
    set duration=duration+0.5
    set rocket=CreateUnit(GetOwningPlayer(caster),'u00J',x,y,angle)
    call SaveUnitHandle(udg_ah,idtt,S2I("Rocket"),rocket)
    call SaveInteger(udg_ah,idtt,S2I("Level"),level)
    call SaveReal(udg_ah,idtt,S2I("Angle"),angle)
    call SaveReal(udg_ah,idtt,S2I("Distance"),distance)
    call TimerStart(tt,0.025,true,function fiverockets_m)
endif
    call SaveReal(udg_ah,id,trgid,duration)
set t=null
set tt=null
set caster=null
set rocket=null
endfunction

function fiverockets_conditions takes nothing returns boolean
local trigger trg=GetTriggeringTrigger()
local integer trgid=GetHandleId(trg)
local timer t=LoadTimerHandle(udg_ah,trgid,S2I("timer"))
local integer remove=LoadInteger(udg_ah,trgid,S2I("remove"))+1
    call PauseTimer(t)
    call DestroyTimer(t)
    call FlushChildHashtable(udg_ah,GetHandleId(t))
    call DestroyTrigger(trg)
set trg=null
    return true
endfunction

function Trig_fiverockets_Actions takes nothing returns nothing
local trigger trg=CreateTrigger()
local unit caster=GetTriggerUnit()
local integer trgid=GetHandleId(trg)
local real duration=0
local integer level=GetUnitAbilityLevel(GetTriggerUnit(),'A02X')
local timer t=CreateTimer()
local integer id=GetHandleId(t)
    call SaveUnitHandle(udg_ah,id,S2I("Caster"),caster)
    call SaveInteger(udg_ah,id,S2I("TrgId"),trgid)
    call SaveInteger(udg_ah,id,S2I("level"),level)
    call SaveReal(udg_ah,id,trgid,duration)
    call TimerStart(t,0.5,true,function fiverockets_timer)
    call SaveTimerHandle(udg_ah,trgid,S2I("timer"),t)
    call TriggerRegisterUnitEvent( trg, caster, EVENT_UNIT_SPELL_FINISH )
    call TriggerRegisterUnitEvent( trg, caster, EVENT_UNIT_SPELL_ENDCAST )
    call TriggerAddCondition(trg,Condition(function fiverockets_conditions))
set caster=null
set trg=null
endfunction

//===========================================================================
function InitTrig_fiverockets takes nothing returns nothing
    set gg_trg_fiverockets = CreateTrigger(  )
    call TriggerRegisterAnyUnitEventBJ( gg_trg_fiverockets, EVENT_PLAYER_UNIT_SPELL_CAST )
    call TriggerAddCondition( gg_trg_fiverockets, Condition( function Trig_fiverockets_Conditions ) )
    call TriggerAddAction( gg_trg_fiverockets, function Trig_fiverockets_Actions )
endfunction
Принцип действия таков - при начале использования магии создаю локальный тригер,добавляю в него 2 события на окончание каста,добавляю кондишн,в котором делаю действия(а именно установление переменной,отвечающей за конец каста и дестрой созданного тригера),также я запускаю таймер с периодом в 0.5 секунд,который устанавливает свои переменный(суть спела в том,что за каждые 0.5 секунды каста создаётся 1 ракета и летит в точку поворота каста,растоянием в 200*0.5(с каждым тактом таймера значение 0.5 увеличивается на 0.5)),затем в колбеке созданного таймера я проверяю не отработал ли он 5 раз,либо не прерван ли каст,если ещё не конец - то создание ракета-снаряда(а также создание для неё набора переменных,таких как угол,дистанция,создание таймера для ракеты,через который все эти значения передадутся,затем при движении ракеты - если растояние пройдено - то убить ракету-снаряд,создать на её месте дамика,кастующего топ))
Ещё если не сложно объясните более легкий способо осуществления такой задачи(если он есть) и укажите возможные утечки.
Старый 24.07.2011, 21:20
16GB
GhostOne User
offline
Опыт: 60,317
Активность:
лучше проверить периодиком текущий приказ же, если он кастит этот приказ будет
Старый 24.07.2011, 21:52
Nerevar
I'll be back!
offline
Опыт: 18,352
Активность:
function Parabola takes real h, real d, real x returns real
    return (4 * h / d) * (d - x) * (x / d)
endfunction

function Trig_fiverockets_Conditions takes nothing returns boolean
    return GetSpellAbilityId() == 'A02X'
endfunction

function fiverockets_m takes nothing returns nothing
local timer t=GetExpiredTimer()
local integer id=GetHandleId(t)
local real rdistance=LoadReal(udg_ah,id,S2I("RDistance"))+20
local real distance=LoadReal(udg_ah,id,S2I("Distance"))-20
local real angle=LoadReal(udg_ah,id,S2I("Angle"))
local unit rocket=LoadUnitHandle(udg_ah,id,S2I("Rocket"))
local integer level=LoadInteger(udg_ah,id,S2I("Level"))
local real x=GetUnitX(rocket)
local real y=GetUnitY(rocket)
local unit dammi
if distance<=10 or IsTerrainPathable(x+20*CosBJ(angle),y+20*SinBJ(angle),PATHING_TYPE_FLYABILITY) == true then
    call SetUnitZ( rocket, 0)
    call KillUnit(rocket)
    set dammi=CreateUnit(GetOwningPlayer(rocket),'u00A',x,y,0)
    call UnitAddAbility(dammi,'A02Y')
    call SetUnitAbilityLevel(dammi,'A02Y',level)
    call IssueImmediateOrder( dammi, "thunderclap" )
    call UnitApplyTimedLife(dammi,'BTLF',3)
    call FlushChildHashtable(udg_ah,id)
    call PauseTimer(t)
    call DestroyTimer(t)
else 
    call SetUnitZ( rocket,Parabola(distance+rdistance,rdistance,(distance+rdistance)/2))
    call SetUnitX(rocket,x+20*CosBJ(angle))
    call SetUnitY(rocket,y+20*SinBJ(angle))
endif
set dammi=null
set t=null
set rocket=null
endfunction

function fiverockets_timer takes nothing returns nothing
local timer t=GetExpiredTimer()
local integer id=GetHandleId(t)
local real duration=LoadReal(udg_ah,id,S2I("Duration"))
local unit caster=LoadUnitHandle(udg_ah,id,S2I("Caster"))
local real angle=GetUnitFacing(caster)
local real x=GetUnitX(caster)
local real y=GetUnitY(caster)
local integer level=LoadInteger(udg_ah,id,S2I("level"))
local real tx=x+duration*200*CosBJ(angle)
local real ty=x+duration*200*SinBJ(angle)
local real distance=SquareRoot((tx - x) * (tx - x) + (ty - y) * (ty - y))
local timer tt=CreateTimer()
local integer idtt=GetHandleId(tt)
local unit rocket
if duration==2.5 or LoadInteger(udg_ah,GetHandleId(caster),S2I("Order"))!=S2I("slow") then
    call FlushChildHashtable(udg_ah,id)
    call PauseTimer(t)
    call DestroyTimer(t)
else
    set duration=duration+0.5
    set rocket=CreateUnit(GetOwningPlayer(caster),'u00J',x,y,angle)
    call SaveUnitHandle(udg_ah,idtt,S2I("Rocket"),rocket)
    call SaveInteger(udg_ah,idtt,S2I("Level"),level)
    call SaveReal(udg_ah,idtt,S2I("Angle"),angle)
    call SaveReal(udg_ah,idtt,S2I("Distance"),distance)
    call TimerStart(tt,0.025,true,function fiverockets_m)
endif
    call SaveReal(udg_ah,id,S2I("Duration"),duration)
set t=null
set tt=null
set caster=null
set rocket=null
endfunction

function Trig_fiverockets_Actions takes nothing returns nothing
local unit caster=GetTriggerUnit()
local real duration=0
local integer level=GetUnitAbilityLevel(GetTriggerUnit(),'A02X')
local timer t=CreateTimer()
local integer id=GetHandleId(t)
    call SaveUnitHandle(udg_ah,id,S2I("Caster"),caster)
    call SaveInteger(udg_ah,id,S2I("level"),level)
    call SaveReal(udg_ah,id,S2I("Duration"),duration)
    call TimerStart(t,0.5,true,function fiverockets_timer)
set caster=null
endfunction
Вот заменил условие на то,при котором проверяется не переменная,отвечающая за конец\прерывание каста,а за текущий приказ юнита - стало вылетать 5 рокет(как и задумывалось),и летят они с интервалом в 0.5 секунды,правда после того как юнит закончил кастовать абилу и в разные стороны до упора карты,да и летят они не по параболе...
Старый 25.07.2011, 13:40
agentex

offline
Опыт: 34,834
Активность:
для параболы и вобще 3д движения лучше использовать векторы. (возможностей куда больше, можно любую траекторию задать)
Старый 25.07.2011, 14:42
Nerevar
I'll be back!
offline
Опыт: 18,352
Активность:
function Trig_fiverockets_Conditions takes nothing returns boolean
    return GetSpellAbilityId() == 'A02X'
endfunction

function fiverockets_m takes nothing returns nothing
local timer t=GetExpiredTimer()
local integer id=GetHandleId(t)
local unit rocket=LoadUnitHandle(udg_ah,id,0)
local integer level=LoadInteger(udg_ah,id,1)
local real angle=LoadReal(udg_ah,id,2)
local real distance=LoadReal(udg_ah,id,3)-20
local real x=GetUnitX(rocket)
local real y=GetUnitY(rocket)
local unit dammi
if distance<=10 or IsTerrainPathable(x+20*Cos(angle),y+20*Sin(angle),PATHING_TYPE_FLYABILITY) == true then
    call SetUnitZ( rocket, 0)
    call KillUnit(rocket)
    set dammi=CreateUnit(GetOwningPlayer(rocket),'u00A',x,y,0)
    call UnitApplyTimedLife(dammi,'BTLF',3)
    call UnitAddAbility(dammi,'A02Y')
    call SetUnitAbilityLevel(dammi,'A02Y',level)
    call IssueImmediateOrder( dammi, "thunderclap" )
    call FlushChildHashtable(udg_ah,id)
    call PauseTimer(t)
    call DestroyTimer(t)
else 
    call SetUnitZ( rocket,GetRandomReal(90.,120.))
    call SetUnitX(rocket,x+20*Cos(angle))
    call SetUnitY(rocket,y+20*Sin(angle))
    call SetUnitFacing(rocket,angle*bj_RADTODEG)
endif
call SaveReal(udg_ah,id,3,distance)
set dammi=null
set t=null
set rocket=null
endfunction

function fiverockets_timer takes nothing returns nothing
local timer t=GetExpiredTimer()
local integer id=GetHandleId(t)
local real angle=LoadReal(udg_ah,id,0)
local unit caster=LoadUnitHandle(udg_ah,id,1)
local integer level=LoadInteger(udg_ah,id,2)
local real duration=LoadReal(udg_ah,id,3)
local real x=GetUnitX(caster)
local real y=GetUnitY(caster)
local real tx=x+duration*200*Cos(angle)
local real ty=x+duration*200*Sin(angle)
local real distance=SquareRoot((tx - x) * (tx - x) + (ty - y) * (ty - y))
local timer tt=CreateTimer()
local integer idtt=GetHandleId(tt)
local unit rocket
call DisplayTextToForce( GetPlayersAll(), "Duration is "+R2S(duration) )
call DisplayTextToForce( GetPlayersAll(), "Angle is "+R2S(angle) )
call DisplayTextToForce( GetPlayersAll(), "Distance is "+R2S(distance) )
call DisplayTextToForce( GetPlayersAll(), "CasterX is "+R2S(x) )
call DisplayTextToForce( GetPlayersAll(), "CasterY is "+R2S(y) )
if duration>5 or LoadStr(udg_ah,GetHandleId(caster),S2I("Order"))!=("slow") then
    call FlushChildHashtable(udg_ah,id)
    call PauseTimer(t)
    call DestroyTimer(t)
else
    set duration=duration+1
    call SaveReal(udg_ah,id,3,duration)
    set rocket=CreateUnit(GetOwningPlayer(caster),'u00J',x,y,0.)
    call SaveUnitHandle(udg_ah,idtt,0,rocket)
    call SaveInteger(udg_ah,idtt,1,level)
    call SaveReal(udg_ah,idtt,2,angle)
    call SaveReal(udg_ah,idtt,3,distance)
    call TimerStart(tt,0.04,true,function fiverockets_m)
endif    
set t=null
set tt=null
set caster=null
set rocket=null
endfunction

function Trig_fiverockets_Actions takes nothing returns nothing
local unit caster=GetTriggerUnit()
local real duration=1
local integer level=GetUnitAbilityLevel(GetTriggerUnit(),'A02X')
local timer t=CreateTimer()
local integer id=GetHandleId(t)
local real angle=GetUnitFacing(caster)*bj_DEGTORAD
    call SaveReal(udg_ah,id,0,angle)
    call SaveUnitHandle(udg_ah,id,1,caster)
    call SaveInteger(udg_ah,id,2,level)
    call SaveReal(udg_ah,id,3,duration)
    call TimerStart(t,0.5,true,function fiverockets_timer)
set caster=null
set t=null
endfunction

//===========================================================================
function InitTrig_fiverockets takes nothing returns nothing
    set gg_trg_fiverockets = CreateTrigger(  )
    call TriggerRegisterAnyUnitEventBJ( gg_trg_fiverockets, EVENT_PLAYER_UNIT_SPELL_CHANNEL )
    call TriggerAddCondition( gg_trg_fiverockets, Condition( function Trig_fiverockets_Conditions ) )
    call TriggerAddAction( gg_trg_fiverockets, function Trig_fiverockets_Actions )
endfunction
Немного переделал код - теперь всё благополучно отменяется сменой приказа,вылетает 5 ракет,даже летят они по прямой - правда по неведомой причине всегда на разное расстояние(в разных четвертях карты на разное расстояние) - сделал чтобы при выпуске ракет выводило сообщение обо всем - номере ракеты,х и у кастера,расстояние полета ракет и угол(в радианах)
В разных четвертях меняется лишь дистанция - зависимость должна быть 200,400,600,800,1000 - а с каждым кастом ракеты она ведет по разному - то 50,100,150,200,250,иногда даже в обратном порядке(!) - 1000,800,600,400,200
Уже не знаю даже что не так
Старый 01.08.2011, 19:21
Ответ

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

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

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

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



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