Способ реализации:
Версия Warcraft:
Наработка для летящей отталкивающей способности.
MUI - да

Видео

Код

globals
    hashtable HT = InitHashtable()
    group Group = CreateGroup()
    
    timer Timer
    integer TimerId
    integer Tick
    
    unit Caster
    unit Dummy
    unit Enum
    
    real CasterX
    real CasterY
    real NewX
    real NewY
    real DummyX
    real DummyY
    real Angle
    real Time
    real Scale
    real Range

    // ID способности и периодичности таймера
    constant integer WaterFlow_SpellId = 'A000'
    constant real WaterFlow_TimerPeriod = 0.02
    
    // Стартовые значения
    constant real WaterFlow_StartScale = 1
    constant real WaterFlow_StartRange = 150
    
    // Основные настройки
    constant real WaterFlow_Damage = 2
    constant real WaterFlow_Speed = 1000
    constant real WaterFlow_Distance = 2000
    constant real WaterFlow_RepulsiveForce = 25

    // Множители
    constant real WaterFlow_RangeIncrease = 3.8
    constant real WaterFlow_ScaleIncrease = 0.02
    constant real WaterFlow_DummyTimeScale = 0.1
    
    // Тип атаки и урона
    constant attacktype WaterFlow_AttackType = ATTACK_TYPE_MAGIC
    constant damagetype WaterFlow_DamageType = DAMAGE_TYPE_UNKNOWN
endglobals

native UnitAlive takes unit id returns boolean

function WaterFlow_Remove takes nothing returns nothing
    set Timer = GetExpiredTimer()
    set TimerId = GetHandleId( Timer )
    
    call RemoveUnit( LoadUnitHandle( HT, TimerId, 'dumy' ) )
    call DestroyTimer( Timer )
    call FlushChildHashtable( HT, GetHandleId( Timer ) )
endfunction

function WaterFlow_Group takes nothing returns nothing
    set Enum = GetEnumUnit()
    
    if IsUnitInRangeXY( Enum, DummyX, DummyY, Range ) and UnitAlive( Enum ) and IsUnitEnemy( Enum, GetOwningPlayer( Caster ) ) and not IsUnitType( Enum, UNIT_TYPE_STRUCTURE ) then
        call SetUnitX( Enum, GetUnitX( Enum ) + WaterFlow_RepulsiveForce * Cos( Angle ) )
        call SetUnitY( Enum, GetUnitY( Enum ) + WaterFlow_RepulsiveForce * Sin( Angle ) )
        call UnitDamageTarget( Caster, Enum, WaterFlow_Damage, true, false, WaterFlow_AttackType, WaterFlow_DamageType, WEAPON_TYPE_WHOKNOWS )
    endif
endfunction

function WaterFlow_Timer takes nothing returns nothing
    set Timer = GetExpiredTimer()
    set TimerId = GetHandleId( Timer )
    
    set Caster = LoadUnitHandle( HT, TimerId, 'cstr' )
    set Dummy = LoadUnitHandle( HT, TimerId, 'dumy' )
    set Angle = LoadReal( HT, TimerId, 'angl' )
    
    set Tick = LoadInteger( HT, TimerId, 'tick' ) + 1
    call SaveInteger( HT, TimerId, 'tick', Tick )
    
    set Range = LoadReal( HT, TimerId, 'rang' ) + WaterFlow_RangeIncrease
    call SaveReal( HT, TimerId, 'rang', Range )
    
    set Scale = LoadReal( HT, TimerId, 'scal' ) + WaterFlow_ScaleIncrease
    call SaveReal( HT, TimerId, 'scal', Scale )
    call SetUnitScale( Dummy, Scale, Scale, Scale )
    
    set Time = ( Tick * WaterFlow_TimerPeriod ) / ( WaterFlow_Distance / WaterFlow_Speed )
    set NewX = LoadReal( HT, TimerId, 'strX' ) * ( 1 - Time ) + LoadReal( HT, TimerId, 'endX' ) * Time
    set NewY = LoadReal( HT, TimerId, 'strY' ) * ( 1 - Time ) + LoadReal( HT, TimerId, 'endY' ) * Time
    
    if GetRectMinX( bj_mapInitialPlayableArea ) <= NewX and NewX <= GetRectMaxX( bj_mapInitialPlayableArea ) and GetRectMinY( bj_mapInitialPlayableArea ) <= NewY and NewY <= GetRectMaxY( bj_mapInitialPlayableArea ) then
        call SetUnitX( Dummy, NewX )
        call SetUnitY( Dummy, NewY )
    endif
    
    set DummyX = GetUnitX( Dummy )
    set DummyY = GetUnitY( Dummy )

    call GroupEnumUnitsInRange( Group, DummyX, DummyY, Range + 200, null )
    call ForGroup( Group, function WaterFlow_Group )
    call GroupClear( Group )
    
    if Time >= 1 then
        call PauseTimer( Timer )
        call SetUnitTimeScale( Dummy, 1 )
        call TimerStart( Timer, 1, false, function WaterFlow_Remove )
    endif
endfunction

function WaterFlow_Actions takes nothing returns nothing
    if GetSpellAbilityId() != WaterFlow_SpellId then
        return
    endif
    
    set Caster = GetSpellAbilityUnit()
    set CasterX = GetUnitX( Caster )
    set CasterY = GetUnitY( Caster )
    set Angle = GetUnitFacing( Caster ) * bj_DEGTORAD
    
    set Dummy = CreateUnit( GetOwningPlayer( Caster ), 'h001', CasterX, CasterY, Angle * bj_RADTODEG )
    call SetUnitTimeScale( Dummy, WaterFlow_DummyTimeScale )
    
    set Timer = CreateTimer()
    set TimerId = GetHandleId( Timer )
    
    call SaveUnitHandle( HT, TimerId, 'cstr', Caster )
    call SaveUnitHandle( HT, TimerId, 'dumy', Dummy )
    call SaveReal( HT, TimerId, 'angl', Angle )
    call SaveReal( HT, TimerId, 'scal', WaterFlow_StartScale )
    call SaveReal( HT, TimerId, 'rang', WaterFlow_StartRange )
    call SaveReal( HT, TimerId, 'strX', CasterX )
    call SaveReal( HT, TimerId, 'strY', CasterY )
    call SaveReal( HT, TimerId, 'endX', CasterX + WaterFlow_Distance * Cos( Angle ) )
    call SaveReal( HT, TimerId, 'endY', CasterY + WaterFlow_Distance * Sin( Angle ) )
    call TimerStart( Timer, WaterFlow_TimerPeriod, true, function WaterFlow_Timer )
endfunction

function InitTrig_RepulsiveWaterFlow 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 >= 16
    endloop
    
    call TriggerAddAction( t, function WaterFlow_Actions )
    set t = null
endfunction

Требования

Скопировать код из шапки карты, скопировать триггер со спеллом к себе на карту, если такие глобальные переменные уже имеются, то копировать их не надо. Поменять равкод способности на свой.
`
ОЖИДАНИЕ РЕКЛАМЫ...
Чтобы оставить комментарий, пожалуйста, войдите на сайт.