Добавлен , опубликован
Алгоритмы, Наработки и Способности
Способ реализации:
Jass
Тип:
Способность
Дело было вечером, делать было нечего
Описание: Юнит бежит определенное расстояние в указанном направлении, расталкивая всех наземных противников на своем пути. Учитываются клиффы и здания, от которых герой отталкивается.
Не действует на союзников. Ломает декорации, не может вылететь за границы карты.
Способность полностью MUI (может использоваться любым количеством игроков и юнитов).
Используемые глобальные переменные: 1 единственная глобалка для хэш-таблицы.
Как импортировать себе:
раскрыть
  1. Копируем триггеры Charge и ChargeMove
  2. Копируем способности
  3. Даем способность "Рывок" своему герою, настраиваем ее как нам нужно
  4. ???
  5. PROFIT!
Сам код способности:
раскрыть
globals
    // Скорость движения юнита
    real CR_Speed = 600.0
    // Максимально возможное расстояние движения
    real CR_Range_Max = 900.0
    // Дальность обнаружения юнитов
    real CR_Range_F = 128.0
    // Дальность отброса юнитов
    real CR_Range_M = 150.0
    // Дальность отброса юнитов за 1 тик
    real CR_Range_OM = 15.0
    // Урон по юнитам, которые будут оттолкнуты
    real CR_Damage = 50.0
    // Максимальное изменение высоты юнитов, которые будут оттолкнуты
    real CR_Height = 125.0
    // Скорость проигрования анимации
    // сейчас стоит скорость анимации для паладина, подправь на нужную тебе
    real CR_Anim_Speed = 0.0766
    // индекс для воcпроизведения анимации
    integer CR_Anim_Index = 12
    // группа для чарджа
    group CR_Group = CreateGroup()
    // еффект для движения
    string CR_Eff_Move = "Abilities\\Spells\\Orc\\MirrorImage\\MirrorImageDeathCaster.mdl"
    // еффект при ударе в клиф или здание
    string CR_Eff_Str = "Abilities\\Spells\\Other\\Volcano\\VolcanoDeath.mdl"
endglobals

function Trig_ChargeMove_Conditions takes nothing returns boolean
    local unit u = FirstOfGroup(CR_Group)    
    if u == null then
        return false
    else
        set u = null
        return true
    endif
endfunction

function Trig_ChargeMove_Actions takes nothing returns nothing
local group g = CreateGroup()
local integer h 
local unit u 
local real angle 
local real range 
local real cur_z 
local real start_z 
local real x
local real y 
local real z
    
    call GroupAddGroup(CR_Group, g)
    loop
        set u = FirstOfGroup(g)
        call GroupRemoveUnit(g, u)
    exitwhen u == null
        set h = GetHandleId(u)
        set angle = LoadReal (udg_Hash, h, StringHash ("angle"))
        set range = LoadReal (udg_Hash, h, StringHash ("range"))
        set cur_z = LoadReal (udg_Hash, h, StringHash ("cur_z"))
        set start_z = LoadReal (udg_Hash, h, StringHash ("start_z"))
        
    if range < CR_Range_M then
            set x = GetUnitX(u) + CR_Range_OM * Cos(angle* bj_DEGTORAD)
            set y = GetUnitY(u) + CR_Range_OM * Sin(angle* bj_DEGTORAD)
        if cur_z < start_z + CR_Height then
            set z = cur_z + (CR_Height/10*2)
        else
            set z = cur_z - (CR_Height/10*2)
        endif
            call SetUnitPathing(u, false)
            call SetUnitX(u, x)
            call SetUnitY(u, y)
            call SetUnitFlyHeight (u, z, 0.0)
            call IssueImmediateOrder(u, "stop")
        call DestroyEffect(AddSpecialEffect(CR_Eff_Move, GetUnitX(u), GetUnitY(u)))    
        call SaveReal (udg_Hash, h, StringHash ("cur_z"), z )
        call SaveReal (udg_Hash, h, StringHash ("range"),  range + CR_Range_OM)       
    else
        call GroupRemoveUnit(CR_Group, u)
        call FlushChildHashtable (udg_Hash, h)
        call SetUnitFlyHeight (u, start_z, 0.00)
        call SetUnitPathing(u, true)
    endif
    endloop

    call DestroyGroup(g)
    
set g = null
set u = null
endfunction

//===========================================================================
function InitTrig_ChargeMove takes nothing returns nothing
    set gg_trg_ChargeMove = CreateTrigger(  )
    call TriggerRegisterTimerEvent( gg_trg_ChargeMove, 0.04, true )
    call TriggerAddCondition( gg_trg_ChargeMove, Condition( function Trig_ChargeMove_Conditions ) )
    call TriggerAddAction( gg_trg_ChargeMove, function Trig_ChargeMove_Actions )
endfunction



function DestroyTrees takes nothing returns nothing
local destructable tree = GetEnumDestructable()
    call KillDestructable (tree)
set tree = null
endfunction

function Charge_Timer takes nothing returns nothing
local timer t = GetExpiredTimer()
local integer h = GetHandleId(t)
local unit caster = LoadUnitHandle(udg_Hash, h, StringHash("caster"))
local real anim_time = LoadReal (udg_Hash, h, StringHash("anim_time"))
local real range = LoadReal(udg_Hash, h, StringHash("range"))
local real x
local real y
local real angle
local real rxy
local group g = CreateGroup()
local unit dummy
local location loc
local location loc_cas
local boolean b = false
local integer h_a 
    if GetUnitState(caster, UNIT_STATE_LIFE) > 0.405 then
        if range < CR_Range_Max then
            set loc = Location(GetUnitX(caster), GetUnitY(caster))
            call EnumDestructablesInCircleBJ(192.0, loc , function DestroyTrees)
            call RemoveLocation(loc)
            call GroupEnumUnitsInRange(g, GetUnitX(caster), GetUnitY(caster), CR_Range_F, null)
            call GroupRemoveUnit(g, caster)
            loop
                set dummy = FirstOfGroup(g)
                call GroupRemoveUnit(g, dummy)
                exitwhen dummy == null
                    if not IsUnitType(dummy, UNIT_TYPE_STRUCTURE) then
                        if not IsUnitInGroup(dummy, CR_Group) and GetUnitState(dummy, UNIT_STATE_LIFE) > 0.405 and IsUnitEnemy (dummy, GetOwningPlayer(caster)) then
                            if IsUnitType (dummy, UNIT_TYPE_GROUND) and GetUnitAbilityLevel(dummy, 'Avul') == 0 then
                                call UnitDamageTarget (caster, dummy, CR_Damage, true, false, ATTACK_TYPE_NORMAL, DAMAGE_TYPE_NORMAL, WEAPON_TYPE_WHOKNOWS)
                                call UnitAddAbility (dummy, 'Amrf')
                                call UnitRemoveAbility (dummy, 'Amrf')
                                set h_a = GetHandleId(dummy)
                                set angle = bj_RADTODEG * Atan2(GetUnitY(dummy)- GetUnitY(caster), GetUnitX(dummy) - GetUnitX(caster))
                                call SaveReal(udg_Hash, h_a, StringHash("angle"), angle)
                                call SaveReal(udg_Hash, h_a, StringHash("range"), 0.0)
                                set loc = Location (GetUnitX(dummy), GetUnitY(dummy))
                                call SaveReal(udg_Hash, h_a, StringHash("cur_z"), GetLocationZ(loc)  + GetUnitFlyHeight(dummy))
                                call SaveReal(udg_Hash, h_a, StringHash("start_z"), GetLocationZ(loc)  + GetUnitFlyHeight(dummy))
                                call RemoveLocation(loc)                               
                           endif
                            call GroupAddUnit (CR_Group, dummy)
                        endif
                    else
                        set b = true
                    endif
            endloop
            set angle = LoadReal(udg_Hash, h, StringHash("angle"))
            call SetUnitFacing(caster, angle)
            call SetUnitPathing(caster, false)
            set x = GetUnitX(caster) + (CR_Speed * 0.04) * Cos(GetUnitFacing(caster)* bj_DEGTORAD)
            set y = GetUnitY(caster) + (CR_Speed * 0.04) * Sin(GetUnitFacing(caster)* bj_DEGTORAD)
            set rxy = SquareRoot((GetUnitX(caster) - x) * (GetUnitX(caster) - x) + (GetUnitY(caster) - y) * (GetUnitY(caster) - y) )
            set loc = Location(x, y)
            set loc_cas = Location(GetUnitX(caster), GetUnitY(caster))
            
            if GetLocationZ(loc) > GetLocationZ(loc_cas) + 15.0 or b or GetUnitX(caster) >= GetRectMaxX(GetPlayableMapRect()) or GetUnitY(caster) >= GetRectMaxY(GetPlayableMapRect()) or GetUnitX(caster) <= GetRectMinX(GetPlayableMapRect()) or GetUnitY(caster) <= GetRectMinY(GetPlayableMapRect())then
                call DestroyTimer(t)
                call FlushChildHashtable(udg_Hash, h)

                set h_a = GetHandleId(caster)
                call SaveReal(udg_Hash, h_a, StringHash("angle"), 360.0 - GetUnitFacing(caster))
                call SaveReal(udg_Hash, h_a, StringHash("range"), 0.0)
                set loc = Location (GetUnitX(caster), GetUnitY(caster))
                call SaveReal(udg_Hash, h_a, StringHash("cur_z"), GetLocationZ(loc) + GetUnitFlyHeight(caster) )
                call SaveReal(udg_Hash, h_a, StringHash("start_z"), GetLocationZ(loc)  + GetUnitFlyHeight(caster))
                call GroupAddUnit (CR_Group, caster)
                call RemoveLocation(loc)
                  
                call SetUnitPathing(caster, true)
                call SetUnitAnimation (caster, "stand")
                call DestroyEffect(AddSpecialEffect(CR_Eff_Str, GetUnitX(caster), GetUnitY(caster)))
                set dummy = CreateUnit(Player(PLAYER_NEUTRAL_PASSIVE), 'dum0', GetUnitX(caster), GetUnitY(caster), 0.0)
                call UnitAddAbility (dummy, 'Ast0')
                call UnitApplyTimedLife (dummy, 'BTFL', 1.0)
                call IssueTargetOrder (dummy, "thunderbolt", caster)
                call RemoveLocation(loc)
                call RemoveLocation(loc_cas)
            else
                set angle = LoadReal (udg_Hash, h, StringHash("angle"))
                call SetUnitX(caster, x)
                call SetUnitY(caster, y)
                call SetUnitFacing(caster, angle)
                call IssueImmediateOrder(caster, "stop")
                if anim_time >= CR_Anim_Speed then
                    set anim_time = 0.0
                    call SetUnitAnimationByIndex(caster, CR_Anim_Index)
                endif
                call SaveReal (udg_Hash, h, StringHash("range"), range + rxy)
                call SaveReal (udg_Hash, h, StringHash("anim_time"), anim_time + 0.04)
                call DestroyEffect(AddSpecialEffect(CR_Eff_Move, GetUnitX(caster), GetUnitY(caster)))
            endif
        else
            call DestroyTimer(t)
            call FlushChildHashtable(udg_Hash, h)
            call SetUnitPathing(caster, true)
            call SetUnitAnimation (caster, "stand")
        endif
        call TimerStart(t, 0.04, false, function Charge_Timer)
    else
        call DestroyTimer(t)
        call FlushChildHashtable(udg_Hash, h)
        call SetUnitPathing(caster, true)
        call SetUnitAnimation (caster, "stand")
    endif
    
    call DestroyGroup(g)
    
set t = null
set caster = null
set g = null
set dummy = null
set loc = null
set loc_cas = null
endfunction


function Trig_Charge_Conditions takes nothing returns boolean
    return GetSpellAbilityId() == 'Acr1'
endfunction

function Trig_Charge_Actions takes nothing returns nothing
    local unit caster = GetSpellAbilityUnit()
    local timer t = CreateTimer()
    local integer h = GetHandleId(t)
    
        // Сохраняем все переменные в хэш таблицу
        // наш кастер
        call SaveUnitHandle(udg_Hash, h, StringHash("caster"), caster)
        // время проигранной нимации
        call SaveReal (udg_Hash, h, StringHash("anim_time"), 0.0)
        // пройденное расстояние
        call SaveReal (udg_Hash, h, StringHash("range"), 0.0)
        // сохраняем угол поворота юнита
        call SaveReal(udg_Hash, h, StringHash("angle"), GetUnitFacing(caster))
        // группа для того что бы не бить одних и тех же юнитов по много раз
        call SaveGroupHandle(udg_Hash, h, StringHash("g1"), CreateGroup())
        call SetUnitAnimationByIndex (caster, CR_Anim_Index )

        call TimerStart(t, 0.04, false, function Charge_Timer)
        
    set t = null
    set caster = null
endfunction

//===========================================================================
function InitTrig_Charge takes nothing returns nothing
    set gg_trg_Charge = CreateTrigger(  )
    call TriggerRegisterAnyUnitEventBJ( gg_trg_Charge, EVENT_PLAYER_UNIT_SPELL_EFFECT )
    call TriggerAddCondition( gg_trg_Charge, Condition( function Trig_Charge_Conditions ) )
    call TriggerAddAction( gg_trg_Charge, function Trig_Charge_Actions )
endfunction


Скачать: ТЫК
Change logs:
Version 1.1
Пофикшена работа с таймерами
Добавлено более реалистичное движение при ударении об препятствие
Исправлена возможность взаимодействовать с трупами юнитов
Теперь корректно работает с парящими юнитами
0
25
9 лет назад
0
Вперед в ленту!
0
15
9 лет назад
0
Не мог чтоль в одной функции с движением перебирать отталкиваемых юнитов? На каждого юнита личный таймер это не совсем ок.
2
25
9 лет назад
2
Tobi123, мог, но так веселее.
0
30
9 лет назад
0
На каждого юнита личный таймер
ну это просто жесть какая-то, правь
0
15
9 лет назад
0
И еще скажу, что высоту юнита нужно ставить на дефолтную. Могут быть парящие юниты, а ты высоту на ноль установил.
0
25
9 лет назад
0
Tobi123, высоту на 0 я не ставил, но нашел другой прикол с ней.
Все пофикшу на днях и перезалью сюда.
0
25
9 лет назад
Отредактирован Ancient
0
Обновил. Читаем ченжлог.
0
5
9 лет назад
0
Кому-то баратрум нужен? Если уж делать нечего, то вокруг кучи недоделанных проектов. Ну, а чардж как чардж. Прикольно его дать рыцарю с копьём и на средневековую ярмарку отправить.
Этот комментарий удален
Чтобы оставить комментарий, пожалуйста, войдите на сайт.