Заклинание с движением огненного шара для новичков и не только. С правильным рассчётом в движении и плавностью.
Видео
Код
globals
hashtable HT = InitHashtable()
group Group = CreateGroup()
unit Caster
unit Dummy
unit Target
real Angle
real CasterX
real CasterY
real DummyX
real DummyY
timer Timer
integer TimerId
integer Tick
real Time
real TimeEase //Переменная для просчёта плавности
constant real Fireball_TimerPeriod = 0.03
constant real Fireball_Distance = 1000
constant real Fireball_Speed = 900
constant real Fireball_Range = 250
constant real Fireball_Damage = 3
constant integer Fireball_EffectLimit = 3
endglobals
native UnitAlive takes unit id returns boolean
function Fireball_Group takes nothing returns nothing
set Target = GetEnumUnit()
if UnitAlive( Target ) and IsUnitEnemy( Target, GetOwningPlayer( Caster ) ) and not IsUnitType( Target, UNIT_TYPE_STRUCTURE ) then
call UnitDamageTarget( Caster, Target, Fireball_Damage, true, false, ATTACK_TYPE_MAGIC, DAMAGE_TYPE_UNKNOWN, WEAPON_TYPE_WHOKNOWS )
endif
endfunction
function Fireball_Timer takes nothing returns nothing
set Timer = GetExpiredTimer()
set TimerId = GetHandleId( Timer )
set Caster = LoadUnitHandle( HT, TimerId, 'cstr' )
set Dummy = LoadUnitHandle( HT, TimerId, 'dumm' )
set Tick = LoadInteger( HT, TimerId, 'tick' )
set Time = ( Tick * Fireball_TimerPeriod ) / ( Fireball_Distance / Fireball_Speed ) //Пройденное время делится на общее время
set TimeEase = Time * Time //Для плавности, если она не нужна, то удалить строчку, удалить переменную TimeEase, и ниже везде в 2 функциях заменить эту переменную на Time
//set TimeEase = Sin( Time * bj_PI ) / 2 //Ещё одна приколюха :)
set DummyX = LoadReal( HT, TimerId, 'minX' ) * ( 1 - TimeEase ) + LoadReal( HT, TimerId, 'maxX' ) * TimeEase //Для правильного движения фаерболла по оси X
set DummyY = LoadReal( HT, TimerId, 'minY' ) * ( 1 - TimeEase ) + LoadReal( HT, TimerId, 'maxY' ) * TimeEase //Тоже самое но с Y
if GetRectMinX( bj_mapInitialPlayableArea ) <= DummyX and DummyX <= GetRectMaxX( bj_mapInitialPlayableArea ) and GetRectMinY( bj_mapInitialPlayableArea ) <= DummyY and DummyY <= GetRectMaxY( bj_mapInitialPlayableArea ) then //Условие что-бы фаерболл не вылетел за карту, и не произошёл Fatal Error
call SetUnitX( Dummy, DummyX )
call SetUnitY( Dummy, DummyY )
if Tick == ( Tick / Fireball_EffectLimit ) * Fireball_EffectLimit then //Ограничение по эффектам, менять как и всё остальное сверху в константах
call DestroyEffect( AddSpecialEffect( "Objects\\Spawnmodels\\Other\\NeutralBuildingExplosion\\NeutralBuildingExplosion.mdl", DummyX, DummyY ) )
call DestroyEffect( AddSpecialEffect( "Abilities\\Spells\\Other\\Doom\\DoomDeath.mdl", DummyX, DummyY ) )
endif
endif
call GroupEnumUnitsInRange( Group, DummyX, DummyY, Fireball_Range, null )
call ForGroup( Group, function Fireball_Group )
call GroupClear( Group )
call SaveInteger( HT, TimerId, 'tick', Tick + 1 )
if Time >= 1 then
call RemoveUnit( Dummy )
call PauseTimer( Timer )
call DestroyTimer( Timer )
call FlushChildHashtable( HT, TimerId )
endif
endfunction
function Fireball_Actions takes nothing returns nothing
if GetSpellAbilityId() == 'A000' then
set Caster = GetTriggerUnit()
set CasterX = GetUnitX( Caster )
set CasterY = GetUnitY( Caster )
set Angle = Atan2( GetSpellTargetY() - CasterY, GetSpellTargetX() - CasterX ) //Просчитывается угол от позиции кастера в сторону каста
set CasterX = CasterX + 50 * Cos( Angle ) //Просчитывается смещение в сторону ранее просчитанного угла
set CasterY = CasterY + 50 * Sin( Angle ) //Тоже что и CasterX но CasterY
set Timer = CreateTimer()
set TimerId = GetHandleId( Timer )
call SaveUnitHandle( HT, TimerId, 'cstr', Caster )
call SaveUnitHandle( HT, TimerId, 'dumm', CreateUnit( GetTriggerPlayer(), 'h001', CasterX, CasterY, Angle ) )
call SaveReal( HT, TimerId, 'minX', CasterX )
call SaveReal( HT, TimerId, 'minY', CasterY )
call SaveReal( HT, TimerId, 'maxX', CasterX + Fireball_Distance * Cos( Angle ) ) //Тут сохраняется координата X, но смещённая на + 1000 в сторону каста
call SaveReal( HT, TimerId, 'maxY', CasterY + Fireball_Distance * Sin( Angle ) ) //Тоже самое что и X но Y
call SaveInteger( HT, TimerId, 'tick', 0 )
call TimerStart( Timer, Fireball_TimerPeriod, true, function Fireball_Timer )
endif
endfunction
function InitTrig_Fireball takes nothing returns nothing
local trigger t = CreateTrigger()
local integer i = 0
loop
call TriggerRegisterPlayerUnitEvent( t, Player( i ), EVENT_PLAYER_UNIT_SPELL_EFFECT, null )
set i = i + 1
exitwhen i == bj_MAX_PLAYER_SLOTS
endloop
call TriggerAddAction( t, function Fireball_Actions )
set t = null
call FogEnable( false )
call FogMaskEnable( false )
endfunction
Edited by KaneThaumaturge
чего не хватает, чтобы избежать его?
Edited by RvzerBro
Что ешо за фпс дроп?
Edited by Extremator
Типа, вот Fireball_EffectLimit = 3, и чё это 3 значит? Мне надо больше или меньше ставить чтобы не лагало?
А так спелл норм, но этот момент непонятен вообще.
Edited by fenathesnake
Edited by LastUchiha
Можно же ещё красотуль натаскать...