Добавлен , опубликован
Алгоритмы, Наработки и Способности
Способ реализации:
vJass
Тип:
Способность
Версия Warcraft:
1.26 (default)
Решил потестировать параболу и сделал такую способность спасибо UselessLORD за помощь. Механика способности такая - герой вместо стандартной атаки запускает огненный снаряд, который взрывается в точки падения, наносит урон в 200% от интелекта и отскакивает к ближайшим противникам 1-5 раз.
Код1
globals
    hashtable H = InitHashtable() //можете приравнять к вашей таблице
	location LocationZ = Loaction(0, 0)
    integer NimbedoId = 'O000' //Id героя
    integer FireBomb = 'A00C' //Id способности
    integer FireBombUnitId = 'e005' //Id дамми юнита, который летит
    integer FireBombChance = 100 //Шанс на прок способности
endglobals

library FilterLib
    function IsDead takes unit u returns boolean
        return GetWidgetLife(u) < 0.405 or IsUnitType(u,UNIT_TYPE_DEAD)
    endfunction

    function Enemy takes nothing returns boolean
        return IsDead(GetFilterUnit())==false and IsPlayerAlly(GetOwningPlayer(LoadUnitHandle(H,'Unit','Unit')), GetOwningPlayer(GetFilterUnit())) == false and GetUnitAbilityLevel(GetFilterUnit(),'Aloc')==0 and GetUnitAbilityLevel(GetFilterUnit(),'Avul')==0 and GetUnitAbilityLevel(GetFilterUnit(),'Bcyc')==0
    endfunction
endlibrary

function GetLocalZ takes real x, real y returns real
    call MoveLocation(LocationZ, x, y)
    return GetLocationZ(LocationZ)
endfunction

function GetUnitZ takes unit u returns real
    return GetLocalZ(GetUnitX(u),GetUnitY(u)) + GetUnitFlyHeight(u)
endfunction 
Код2 (создать триггер с названием FireBomb)
function Trig_FireBomb_Actions takes nothing returns nothing
    local unit Caster = GetAttacker()
    local unit Target = GetTriggerUnit()
    local real x0 = GetUnitX(Caster)
    local real y0 = GetUnitY(Caster)
    local real x1 = GetUnitX(Target)
    local real y1 = GetUnitY(Target) 
    local real d = SquareRoot( (x1 - x0) * (x1 - x0) + (y1 - y0) * (y1 - y0) )
    local real h = d / 4.0
    local real h0 = GetUnitZ(Caster) + 40.0
    local real h1 = GetUnitFlyHeight(Target)
    local real a = bj_RADTODEG * Atan2(y1 - y0, x1 - x0)
    local player Owner = GetOwningPlayer(Caster)
    local timer Timer = CreateTimer()
    local integer id = GetHandleId(Timer)
    local unit dummy

	call IssueImmediateOrder(Caster, "stop")
    call SetUnitAnimation(Caster, "attack" )
    call IssueTargetOrder(Caster, "attack", Target)
    
    if GetRandomInt(1, 100) <= FireBombChance then
        set dummy = CreateUnit(GetOwningPlayer(Caster), FireBombUnitId, x0 + 100.0 * Cos(a * bj_DEGTORAD), y0 + 100.0 * Sin(a * bj_DEGTORAD), a)
        
        call ShowUnit(dummy, false) 
    
        call TimerStart(Timer, 0.03, true, function FireBomb_Move)
        
        call SaveUnitHandle(H, id, StringHash("Fire Bomb"), dummy)
        call SaveUnitHandle(H, id, 'Targ', Target)
        call SaveReal(H, id, StringHash("Start X"), x0)
        call SaveReal(H, id, StringHash("Start Y"), y0)
        call SaveReal(H, id, StringHash("End X"), x1)
        call SaveReal(H, id, StringHash("End Y"), y1)
        call SaveReal(H, id, StringHash("Distance"), d)
        call SaveReal(H, id, StringHash("Max Height"), h)
        call SaveReal(H, id, StringHash("Start Height"), h0)
        call SaveReal(H, id, StringHash("End Height"), h1)
        call SaveReal(H, id, 'time', 0.0)
        call SaveEffectHandle(H, id, 'effe', AddSpecialEffectTarget("Abilities\\Weapons\\PhoenixMissile\\Phoenix_Missile_mini.mdl", Caster, "weapon"))
        call SaveInteger(H, GetHandleId(dummy), 'boun', GetUnitAbilityLevel(Caster, FireBomb))
        call SaveUnitHandle(H, GetHandleId(dummy), 'nimb', Caster)
    endif
        
    set Caster = null
    set Target = null
    set Timer = null
    set dummy = null
endfunction

function Trig_FireBomb_Cond takes nothing returns boolean
    return GetUnitTypeId(GetAttacker()) == NimbedoId
endfunction

//===========================================================================
function InitTrig_FireBomb takes nothing returns nothing
    local integer index
    local trigger T1 = CreateTrigger()
    
    set index = 0
    loop
        call TriggerRegisterPlayerUnitEvent(T1, Player(index), EVENT_PLAYER_UNIT_ATTACKED, null)
        
        set index = index + 1
        exitwhen index == bj_MAX_PLAYER_SLOTS
    endloop
    
    call TriggerAddCondition(T1,function Trig_FireBomb_Cond)
    call TriggerAddAction(T1, function Trig_FireBomb_Actions)
    
    set T1 = null
endfunction
Код3 (создать триггер с названием FireBombMove)
library FireBombMove
function IsDead2 takes unit u returns boolean
    return GetWidgetLife(u) < 0.405 or IsUnitType(u,UNIT_TYPE_DEAD)
endfunction

function Enemy2 takes nothing returns boolean
    return GetFilterUnit() != LoadUnitHandle(H, 'Targ', 'Unit') and IsDead(GetFilterUnit())==false and IsPlayerAlly(GetOwningPlayer(LoadUnitHandle(H,'Cast','Unit')), GetOwningPlayer(GetFilterUnit())) == false and GetUnitAbilityLevel(GetFilterUnit(),'Aloc')==0 and GetUnitAbilityLevel(GetFilterUnit(),'Avul')==0 and GetUnitAbilityLevel(GetFilterUnit(),'Bcyc')==0
endfunction

function ParabolaZ2 takes real h0, real h1, real h, real d, real d1 returns real
    return ((4 * h / d) * (d - d1) + h1 - h0) * (d1 / d) + h0
endfunction

function FireBomb_Move takes nothing returns nothing
    local timer Timer = GetExpiredTimer()
    local integer id = GetHandleId(Timer)
    local unit dummy = LoadUnitHandle(H, id, StringHash("Fire Bomb"))
    local real x0 = LoadReal(H, id, StringHash("Start X"))
    local real y0 = LoadReal(H, id, StringHash("Start Y"))
    local real x1 = LoadReal(H, id, StringHash("End X"))
    local real y1 = LoadReal(H, id, StringHash("End Y"))
    local real d = LoadReal(H, id, StringHash("Distance"))
    local real h = LoadReal(H, id, StringHash("Max Height"))
    local real h0 = LoadReal(H, id, StringHash("Start Height"))
    local real h1 = LoadReal(H, id, StringHash("End Height"))
    local real a = bj_RADTODEG * Atan2(y1 - y0, x1 - x0)
    local real dx
    local real dy
    local real d1
    local real d2
    local real height
    local group g = CreateGroup()
    local unit Target
    local real Time = LoadReal(H, id, 'time') + 0.03
    
    call SaveReal(H, id, 'time', Time)
    
    if Time >= 0.48 then
        if Time == 0.48 then
            call UnitRemoveAbility(dummy, 'Aloc')
            call ShowUnit(dummy, true)
            call UnitAddAbility(dummy, 'Aloc')
            call DestroyEffect(LoadEffectHandle(H, id, 'effe'))
        endif
        
        set dx = GetUnitX(dummy)
        set dy = GetUnitY(dummy)
        set d1 = SquareRoot( (dx - x0) * (dx - x0) + (dy - y0) * (dy - y0) )
        set d2 = SquareRoot( (x1 - dx) * (x1 - dx) + (y1 - dy) * (y1 - dy) )
        set height = ParabolaZ2(h0, h1, h, d, d1)
        
        if d2 <= 20.0 then
            call ShowUnit(dummy, false)
            call DestroyEffect(AddSpecialEffect("Abilities\\Spells\\Other\\Doom\\DoomDeath.mdl", dx, dy))
            call PauseTimer(Timer)
            call DestroyTimer(Timer)
            
            call SaveUnitHandle(H, 'Unit', 'Unit', LoadUnitHandle(H, GetHandleId(dummy), 'nimb'))
            call GroupEnumUnitsInRange(g, dx, dy, 200.0, function Enemy)
            
            loop
                set Target = FirstOfGroup(g)
                exitwhen Target == null
                call UnitDamageTarget(LoadUnitHandle(H, GetHandleId(dummy), 'nimb'), Target, GetHeroInt(LoadUnitHandle(H, GetHandleId(dummy), 'nimb'), true) * 2.0, true, false, ATTACK_TYPE_HERO, DAMAGE_TYPE_NORMAL, WEAPON_TYPE_WHOKNOWS)
                call GroupRemoveUnit(g, Target)
            endloop
            
            call GroupClear(g)
            if LoadInteger(H, GetHandleId(dummy), 'boun') > 0 then
                call SaveUnitHandle(H, 'Cast', 'Unit', dummy)
                call SaveUnitHandle(H, 'Targ', 'Unit', LoadUnitHandle(H, id, 'Targ'))
                call GroupEnumUnitsInRange(g, dx, dy, 770.0, function Enemy2)                
                loop
                    set Target = GroupPickRandomUnit(g)
                    exitwhen Target == null
                    
                    set dx = GetUnitX(Target)
                    set dy = GetUnitY(Target)
                    set d2 = SquareRoot( (x1 - dx) * (x1 - dx) + (y1 - dy) * (y1 - dy) )
                    
                    if d2 < 300.0 or d2 > 700.0 then
                        call GroupRemoveUnit(g, Target)
                    else
                        call FlushChildHashtable(H, id)
                        call SaveUnitHandle(H, 'Targ', 'Unit', Target)
                        call SaveInteger(H, GetHandleId(dummy), 'boun', LoadInteger(H, GetHandleId(dummy), 'boun') - 1)
                        call TriggerExecute(gg_trg_FireBombBounce)
                        exitwhen Target != null
                    endif
                endloop
            else
                call RemoveUnit(dummy)
                call FlushChildHashtable(H, GetHandleId(dummy))
            endif
        else
            call SetUnitX(dummy, dx + 25.0 * Cos(a * bj_DEGTORAD))
            call SetUnitY(dummy, dy + 25.0 * Sin(a * bj_DEGTORAD))
            call SetUnitFlyHeight(dummy, height, 0.0)
        endif
    endif
    
    call GroupClear(g)
    call DestroyGroup(g)
    
    set Timer = null
    set dummy = null
    set g = null
    set Target = null
endfunction
endlibrary
Код4 (создать триггер с названием FireBombBounce)
function Trig_FireBombBounce_Actions takes nothing returns nothing
    local unit Caster = LoadUnitHandle(H, 'Cast', 'Unit')
    local unit Target = LoadUnitHandle(H, 'Targ', 'Unit')
    local real x0 = GetUnitX(Caster)
    local real y0 = GetUnitY(Caster)
    local real x1 = GetUnitX(Target)
    local real y1 = GetUnitY(Target) 
    local real d = SquareRoot( (x1 - x0) * (x1 - x0) + (y1 - y0) * (y1 - y0) )
    local real h = d / 4.0
    local real h0 = GetUnitFlyHeight(Caster)
    local real h1 = GetUnitFlyHeight(Caster)
    local real a = bj_RADTODEG * Atan2(y1 - y0, x1 - x0)
    local player Owner = GetOwningPlayer(Caster)
    local timer Timer = CreateTimer()
    local integer id = GetHandleId(Timer)
    
    call TimerStart(Timer, 0.03, true, function FireBomb_Move)
    
    call SaveUnitHandle(H, id, StringHash("Fire Bomb"), Caster)
    call SaveUnitHandle(H, id, 'Targ', Target)
    call SaveReal(H, id, StringHash("Start X"), x0)
    call SaveReal(H, id, StringHash("Start Y"), y0)
    call SaveReal(H, id, StringHash("End X"), x1)
    call SaveReal(H, id, StringHash("End Y"), y1)
    call SaveReal(H, id, StringHash("Distance"), d)
    call SaveReal(H, id, StringHash("Max Height"), h)
    call SaveReal(H, id, StringHash("Start Height"), h0)
    call SaveReal(H, id, StringHash("End Height"), h1)
    call SaveReal(H, id, 'time', 0.0)
    call SaveEffectHandle(H, id, 'effe', AddSpecialEffectTarget("Abilities\\Weapons\\PhoenixMissile\\Phoenix_Missile_mini.mdl", Caster, "weapon"))
    
    set Caster = null
    set Target = null
    set Timer = null
endfunction

//===========================================================================
function InitTrig_FireBombBounce takes nothing returns nothing
    set gg_trg_FireBombBounce = CreateTrigger()
    call TriggerAddAction(gg_trg_FireBombBounce, function Trig_FireBombBounce_Actions)
endfunction
Как импортировать
1). Скопировать код и вставить в карту.
2). Создать пустую способность
3). Создать дамми юнита
4). Внести все необходимые правки в глобальные переменные из Код1
5). Добавить способность герою
П.с. понимаю что гифка не очень, но если смотреть на х3, то норм
Другие способности героя можно посмотреть у меня в блоге))
`
ОЖИДАНИЕ РЕКЛАМЫ...
0
27
2 года назад
Отредактирован rsfghd
0
Потестил, к сожалению парабола вышла кривой если ланд не плоский
Заметил другие баги пока тестировал и на видео тоже можно их наблюдать, огни порой не отскакивают даже, след от огня пропадает куда-то, летающие юниты под игнор идут, нормализацию анимации атаки вообще поленился сделать
вот формулы параболы, юзай вторую xgm.guru/p/wc3/parabolicmovement
могу предположить только что ты спелл не для юза другими игроками делал, то есть не для импорта, а просто показать, что ты можешь сделать на данный момент, в таком случае неплохо, но можешь лучше)

забыл потестить ещё как оно будет балансировать между летающими юнитами, но думаю там очевидно, что оно с земли стартовать будет

в плане кода опять куча непоняток, на первой ошибке остановился и закрыл карту

Другие способности героя можно посмотреть у меня в блоге))
можно было ссылки оставить на них))
Загруженные файлы
0
11
2 года назад
0
rsfghd, касательно того, что некоторые юниты в игноре, то это потому-что там условие на расстояние до крипа

могу предположить только что ты спелл не для юза другими игроками делал, то есть не для импорта, а просто показать, что ты можешь сделать на данный момент
В целом да)
0
14
2 года назад
0
хорошая система, но код толком не читал, а почему бы не сделать все в одном триггере?
0
11
2 года назад
0
Гуванч:
хорошая система, но код толком не читал, а почему бы не сделать все в одном триггере?
не смог
0
11
2 года назад
0
Немного отредактировал код, чтобы правильно учитывать высоту юнита
0
14
2 года назад
Отредактирован Гуванч
0
если отменять атаку много раз зависаний не будет?
переменную типа игрок не обнулил
0
11
2 года назад
0
Гуванч:
если отменять атаку много раз зависаний не будет?
переменную типа игрок не обнулил
пофиксил
0
11
2 года назад
0
Хотя нет не пофиксил
0
1
2 года назад
0
Прикольно
Чтобы оставить комментарий, пожалуйста, войдите на сайт.