Добавлен , опубликован
Существует специальная тема Способности и алгоритмы на заказ, где любой желающий может помочь с вашими фантазиями и где я тоже иногда зависаю. Кроме того, есть платные заказы, например, можете обратиться к Hate - Заклинания на заказ для Warcraft 3 (Платные) или поискать ещё темы на сайте
Я хочу развивать своё резюме, поэтому можете оставлять заявки и там, и тут. Имейте ввиду, заказы я выполняю бесплатно, на чистом энтузиазме, трачу на это своё свободное время, поскольку воспринимаю это как хобби, всё выполняю при возможности и желании
раскрыть
Я не буду вливаться в ваши проекты и не принимаю деньги, для этого есть платные темы. Авторство или упоминания меня в карте делать не нужно, ибо я буду менять ник. Если появится желание отблагодарить - лайка достаточно
Могу сделать анонимно заклинание, для этого можно обратиться ко мне в личку, но меня расстроит невозможность поделиться им, если оно интересное
Отдаю приоритет именно способностям, алгоритмы/системы, вроде 3д камеры/физики, меня особо не интересуют, да и не всё умею, и не за все заказы возьмусь, не стоит ожидать от меня движущихся птиц и чайники на молниях, матрицу не изучал и с математикой не дру
Работаю на 1.26, могу воспользоваться UjAPI, при создании спелла для рефа
Для меня предпочтительнее пользоваться вджассом, но могу сделать заклинание на чистом джассе и даже гуи, однако имейте ввиду, гуи может многократно усложнить работу, ибо на нём может не хватать функционала для создания вашего спелла. Есть вариант скрестить джасс с гуи, пользуясь TriggerEvaluate

Форма составления заявки

При создании заявки не забудьте указать тип комментария Заказ на работу
# Заказ
**Название:** Название способности (опционально, если заказ один)
**Метод:** GUI/Jass/cJass/vJass/Zinc
**Версия Warcraft III:** Версия варкрафта для этого заказа
**Техническое описание:** Распишите механику способности в деталях
Заявки оставлять в комментариях под этим ресурсом
раскрыть
Название - можно любое указать, вплоть до символа, это поможет в навигации по мере сдачи работ. Не нужно указывать, если в заказе только одна способность, работа сдаётся в ответах под заказом
Метод - выберите для себя комфортный метод, на котором будет выполнена способность. При методе кодом, я укажу комментариями где нужно будет что-то отредактировать. Комфортные для меня методы в порядке убывания: vJass > Jass > cJass > Zinc > GUI
Версия Warcraft III - на определённых версиях не доступен мемхак и сджасс. Чтобы взять ориентир на рефорджед, могу воспользоваться UjAPI. Это необходимо для специфических заказов, к примеру, повышение бонусной силы атаки, где на старых версиях требуется мемхак/южапи/костыли/база данных, а на более новых для этого присутствуют нативки
Техническое описание - укажите что должна делать ваша способность, например:
1 уровень: выпускается волна в точку каста
2 уровень: 2 волны в точку каста с разницей в 20 градусов по бокам
3 уровень: 5 волн, одна посередине и по 2 по бокам с разницей в 10 градусов
Каждая волна движется со скоростью 2000 и дальностью 1000. Радиус поражения 200 и с каждым уровнем увеличивается на 50 вместе с размером волны. Я хочу наносить урон юнитам самостоятельно, на гуи, с помощью TriggerEvaluate, мне нужны будут переменные применяющего юнита и уровень его способности на момент каста абилки, оставь пример нанесения урона с использованием этих переменных
Красивое форматирование приветствуется

Примеры работ

Всё у меня в ресурсах: xgm.guru/u/rsfghd
`
ОЖИДАНИЕ РЕКЛАМЫ...

Показан только небольшой набор комментариев вокруг указанного. Перейти к актуальным.
2
Вот ещё идея, простая, но всё же (потом возможно ещё идеи оригинальнее накину):
Пассивная способность! Чем меньше у вражеского юнита HP в %, тем больше урона ему наносится! За каждые 10% недостающего HP у врага ему наносится больше урона! К примеру за каждые 10% отсутствующих HP прибавляется 15 ед урона, на 2 лвл 30 ед урона, на 3 лвл 45 ед урона и тд! А если у врага 100% HP, то пассивка ничего не наносит (начинает наносить при 90% HP и менее). Ну или как-то так.
И ещё одна пассивка "наоборот": тоже самое, но урон наносится чем больше у врага HP. При 100% макс урон у пассивки, при 10% HP у врага пассивка урона не наносит!
Вот! Видел похожий спелл на хайве, но там он был сделан криво, глюченый и не MUI. Так что нужен норм такой спелл, хорошо сделанный!
3
Название: Молот древних (Rolling Slam)
Метод: любой
MUI: нет
Версия: 2.0.1
Цель: Точка на карте
Количество уровней: 4
Описание: Герой бьет перед собой эфирным молотом древних два раза. Сначала он разбивает землю в небольшом радиусе и наносит урон от своей атаки в виде магического урона, перемещаясь чуть вперед. Потом после паузы в 0,5 сек. бьет еще раз и так же перемещается чуть вперед. но уже с большем радиусом поражения.
Радиус первого удара об землю 250 АоЕ (Малый эффект).
Радиус второго удара об землю 375 АоЕ (Большой эффект).
Урон от каждого удара молота древних: 100% урона от атаки + 60/110/160/210 ед. в виде магического урона.
Перезарядка: 8 сек.
  • Если не сложно то сделать отображение урона как при крите над героем только оранжевого цвета;
  • В момент использования способности надо что бы остальный способности становились неактивными пока не пройдут два удара или не собьют способность;
  • Перезарядка начинается только с момента последнего (второго) удара или если собьют заклинание;
  • Не проходит сквозь текстуры, хай и лоу грануды;
  • Без багов если застрянет или герой умрет в процессе каста.
С чего брал идею: www.youtube.com/watch?v=NrMpmUg9Y7g PoE 2 - Rolling Slam со своими доработками :)
.
Предмет 1: "Сотрясатель земли"
Улучшает способность "Молот древних":
! Усиливает дополнительный магический урон до 120/220/360/420.
Если герой убивает противника способностью "Молотом древних", то c 15%-й вероятностью на его месте появляется Землетрясение (Даммик), которое наносит 100 ед. магического урона в сек и замедляет цели в радиусе 300 АоЕ на 35%.
Время существования Землетрясения: 6 сек.
Предмет 2: "Корона титана"
По окончанию действия способности "Молот древних", есть 30% шанс мгновенно ее перезарядить и улучшить ____урон от атаки следующей способности "Молот древних" до 250% (Анимация горения оружия на кончике клинка, с возможностью изменения эффекта) на 5 сек. Шанс на перезарядку не срабатывает от улучшенной версии способности!
Буду использовать это на анимациях Самуро (Мастер клинка) из Reforged
1 удар по земле: Attack 1
2 удар по земле: Attack Slam 1
Можно сразу подогнать спел под его анимации.
Ответы (8)
28
SebastianCarrey, а что насчёт кубиков рандома у атаки? Там есть минимальное и максимальное значение
28
Выполнение заказа

Заклинание готово!

Молот древних (Rolling Slam)

инструкция по импорту
удалить из папки Initialization триггеры, отделённые комментарием (нижние), скопировать папку и вставить в свою карту
поскольку у тебя уже есть триггер AllGlobals из прошлого заказа, тебе нужно просто скопировать строки 56-81 и вставить где-нибудь в своей библиотеке AllGlobalsLib
в триггере Spell всё, что тебе нужно/можно изменить, помечено комментарием
поскольку у тебя уже есть библиотека SpellLib из прошлого заказа, нужно переименовать библиотеку перед импортом, например, на SpellOneLib
на 291 строке укажи абилку ауры замедления у даммика землетрясения
строки 105-109 и 96-100 можно стереть, это дополнительный эффект при наличии усиления абилки, при усилении абилки так же могу порекомендовать изменять иконку способности на более усиленную версию
на строках 89-90 оффсет для удара (чтобы удар происходил на уровне меча, а не прямо под юнитом)
ну и перекопируй редактор объектов

Код
AllGlobals
library AllGlobalsLib
globals
    constant hashtable H = InitHashtable( )
    constant real UNIT_MAX_COLLISION = 200.00
endglobals

native UnitAlive takes unit id returns boolean

function UnitHasItemOfType takes unit u, integer id returns boolean
    local integer i = 0
    
    loop
        if GetItemTypeId( UnitItemInSlot( u, i ) ) == id then
            return true
        endif
        
        set i = i + 1
        exitwhen i >= bj_MAX_INVENTORY
    endloop
    
    return false
endfunction

struct vector
    real x
    real y
    real z
    
    method length takes nothing returns real
        return SquareRoot( x * x + y * y + z * z )
    endmethod
    
    method normalize takes nothing returns nothing
        local real l = length( )
        
        if l == 0.00 then
            set l = 1.00
        endif
        
        set x = x / l
        set y = y / l
        set z = z / l
    endmethod
    
    static method create takes real x, real y, real z returns thistype
        local thistype this = thistype.allocate( )
        
        set this.x = x
        set this.y = y
        set this.z = z
        
        return this
    endmethod
endstruct

function SetUnitAnimationByIndexTimer takes nothing returns nothing
    local timer t = GetExpiredTimer( )
    local integer i = GetHandleId( t )
    local unit u = LoadUnitHandle( H, i, 0 )
    
    call SetUnitAnimationByIndex( u, LoadInteger( H, i, 1 ) )
    call QueueUnitAnimation( u, "stand ready" )
    call QueueUnitAnimation( u, "stand" )
    
    call FlushChildHashtable( H, i )
    call DestroyTimer( t )
    
    set u = null
    set t = null
endfunction

function SetUnitAnimationByIndexEx takes unit u, integer i returns nothing
    local timer t = CreateTimer( )
    
    call SaveUnitHandle( H, GetHandleId( t ), 0, u )
    call SaveInteger( H, GetHandleId( t ), 1, i )
    
    call TimerStart( t, 0.00, false, function SetUnitAnimationByIndexTimer )
    
    set t = null
endfunction
endlibrary

//===========================================================================
//function InitTrig_AllGlobals takes nothing returns nothing
    //set gg_trg_AllGlobals = CreateTrigger(  )
//endfunction

Spell
library SpellLib
globals
    private constant group TempGroup = CreateGroup( )
    private item TempItem = null
    private integer UpgradedKill = 0
    
    constant key SpellUpgrade
endglobals

private struct SpellS
    timer t
    unit caster
    unit dummy
    player p
    effect e = null
    ability abil
    integer attack
    integer upgrade1
    integer upgrade2
    
    vector v
    
    real time
    real timePause
    
    real speed
    
    real radius
    real radiusMax
    
    real damage
    
    attacktype attackType
    damagetype damageType
    weapontype weaponType
endstruct

private function RemoveBuff takes nothing returns nothing
    local timer t = GetExpiredTimer( )
    local integer i = GetHandleId( t )
    
    call DestroyEffect( LoadEffectHandle( H, i, 0 ) )
    call RemoveSavedHandle( H, GetHandleId( LoadUnitHandle( H, i, 1 ) ), SpellUpgrade )
    
    call FlushChildHashtable( H, i )
    call DestroyTimer( t )
    
    set t = null
endfunction

private function Move takes nothing returns nothing
    local SpellS A = LoadInteger( H, GetHandleId( GetExpiredTimer( ) ), 0 )
    local real x = GetUnitX( A.caster ) + A.speed * A.v.x
    local real y = GetUnitY( A.caster ) + A.speed * A.v.y
    local real x1
    local real y1
    local unit u
    local boolean stunned = GetUnitAbilityLevel( A.caster, 'BPSE' ) > 0
    
    if not stunned then
        if A.timePause > 0.00 then
            set A.timePause = A.timePause - 0.01
            
            if A.timePause <= 0.00 then
                call SetUnitAnimationByIndex( A.caster, 3 ) // анимация второй атаки
            endif
        endif
        
        if A.timePause <= 0.00 then
            call SetItemPosition( TempItem, x, y )
            call SetItemVisible( TempItem, false )
            
            set x1 = GetItemX( TempItem )
            set y1 = GetItemY( TempItem )
            
            if not ( ( x - 1.00 > x1 or x + 1.00 < x1 ) or ( ( y - 1.00 > y1 ) or ( y + 1.00 < y1 ) ) ) then
                call SetUnitX( A.caster, x )
                call SetUnitY( A.caster, y )
            endif
            
            set A.time = A.time - 0.01
        endif
    else
        call SetUnitAnimation( A.caster, "stand" )
    endif
    
    if A.time <= 0.00 or stunned then
        if not stunned then
            set x = x + 100.00 * A.v.x
            set y = y + 100.00 * A.v.y
            
            if A.attack == 0 then
                call DestroyEffect( AddSpecialEffect( "Abilities\\Spells\\Human\\Thunderclap\\ThunderClapCaster.mdl", x, y ) ) // эффект первого удара
                
                // доп. эффект от усиления "Корона титана"
                if A.e != null then
                    set bj_lastCreatedEffect = AddSpecialEffect( "Abilities\\Spells\\Other\\Doom\\DoomDeath.mdl", x, y )
                    call BlzSetSpecialEffectScale( bj_lastCreatedEffect, 0.75 )
                    call DestroyEffect( bj_lastCreatedEffect )
                endif
            else
                call DestroyEffect( AddSpecialEffect( "Abilities\\Spells\\Orc\\WarStomp\\WarStompCaster.mdl", x, y ) ) // эффект второго удара
                
                // доп. эффект от усиления "Корона титана"
                if A.e != null then
                    set bj_lastCreatedEffect = AddSpecialEffect( "Abilities\\Spells\\Other\\Doom\\DoomDeath.mdl", x, y )
                    call BlzSetSpecialEffectScale( bj_lastCreatedEffect, 1.15 )
                    call DestroyEffect( bj_lastCreatedEffect )
                endif
                
                set A.radius = A.radiusMax
            endif
            
            call GroupEnumUnitsInRange( TempGroup, x, y, A.radius + UNIT_MAX_COLLISION, null )
            
            loop
                set u = FirstOfGroup( TempGroup )
                exitwhen u == null
                call GroupRemoveUnit( TempGroup, u )
                
                if IsUnitInRangeXY( u, x, y, A.radius ) then
                    if UnitAlive( u ) and IsUnitEnemy( u, A.p ) then
                        if A.upgrade1 == 1 and GetRandomInt( 1, 100 ) <= 15 then // шанс заспавнить землетрясение при убийстве (15%)
                            set UpgradedKill = 1
                        endif
                        
                        call UnitDamageTarget( A.caster, u, A.damage, false, false, A.attackType, A.damageType, A.weaponType )
                        
                        set UpgradedKill = 0
                    endif
                endif
            endloop
            
            // плавающий текст
            set bj_lastCreatedTextTag = CreateTextTag( )
            call SetTextTagText( bj_lastCreatedTextTag, I2S( R2I( A.damage ) ) + "!", 12.50 * 0.023 / 10.00 )
            call SetTextTagPosUnit( bj_lastCreatedTextTag, A.caster, 75.00 ) 
            call SetTextTagColor( bj_lastCreatedTextTag, 255, 75, 0, 255 )
            call SetTextTagVelocity( bj_lastCreatedTextTag, 0.00, 0.0355 )
            call SetTextTagPermanent( bj_lastCreatedTextTag, false )
            call SetTextTagLifespan( bj_lastCreatedTextTag, 1.50 )
            call SetTextTagFadepoint( bj_lastCreatedTextTag, 0.00 )
        endif
        
        if A.attack == 0 and not stunned then
            set A.attack = 1
            
            set A.speed = A.speed * 2.00 // ускорение второго удара
            set A.time = 0.70 // время для второго удара
            set A.timePause = 0.50 // пауза перед вторым ударом
        else
            call PauseTimer( A.t )
            call FlushChildHashtable( H, GetHandleId( A.t ) )
            call DestroyTimer( A.t )
            
            call IssueImmediateOrder( A.caster, "stop" )
            
            if A.upgrade2 == 1 and not stunned then
                if GetRandomInt( 1, 100 ) <= 30 then // шанс усилить следующий каст абилки и сбросить перезарядку
                    set A.t = CreateTimer( )
                    
                    call SaveTimerHandle( H, GetHandleId( A.caster ), SpellUpgrade, A.t )
                    
                    call SaveEffectHandle( H, GetHandleId( A.t ), 0, AddSpecialEffectTarget( "Abilities\\Weapons\\PhoenixMissile\\Phoenix_Missile_mini.mdl", A.caster, "weapon" ) ) // эффект усиления
                    call SaveUnitHandle( H, GetHandleId( A.t ), 1, A.caster )
                    
                    call TimerStart( A.t, 5.00, false, function RemoveBuff ) // время усиления
                    
                    if A.e != null then
                        call BlzStartAbilityCooldown( A.abil, BlzGetAbilityCooldown( A.abil ) )
                    endif
                else
                    call BlzStartAbilityCooldown( A.abil, BlzGetAbilityCooldown( A.abil ) )
                endif
            else
                call BlzStartAbilityCooldown( A.abil, BlzGetAbilityCooldown( A.abil ) )
            endif
            
            call PauseUnit( A.caster, false )
            
            if A.e != null then
                call DestroyEffect( A.e )
                set A.e = null
            endif
            
            set A.t = null
            set A.abil = null
            set A.caster = null
            call A.v.destroy( )
            call A.destroy( )
        endif
    endif
endfunction

private function Spell_Actions takes nothing returns nothing
    local SpellS A = SpellS.create( )
    local integer lvl
    local timer t
    
    set A.t = CreateTimer( )
    set A.caster = GetTriggerUnit( )
    set A.p = GetOwningPlayer( A.caster )
    set A.abil = GetSpellAbility( )
    
    set A.v = vector.create( GetSpellTargetX( ) - GetUnitX( A.caster ), GetSpellTargetY( ) - GetUnitY( A.caster ), 0.00 )
    call A.v.normalize( )
    
    set A.damage = BlzGetUnitBaseDamageByIndex( A.caster, 0 ) + BlzGetUnitBonusDamageByIndex( A.caster, 0 )
    
    set lvl = GetUnitAbilityLevel( A.caster, GetSpellAbilityId( ) )
    
    if lvl == 1 then // уровень
        set A.damage = A.damage + 60.00 // доп. урон
    elseif lvl == 2 then
        set A.damage = A.damage + 110.00
    elseif lvl == 3 then
        set A.damage = A.damage + 160.00
    else
        set A.damage = A.damage + 210.00
    endif
        
    set A.radius = 250.00 // радиус первого удара
    set A.radiusMax = 375.00 // радиус второго удара
    
    if UnitHasItemOfType( A.caster, 'afac' ) then // "Сотрясатель земли"
        set A.damage = A.damage * 2.00 // доп. урон (х2)
        set A.upgrade1 = 1
    else
        set A.upgrade1 = 0
    endif
    
    if UnitHasItemOfType( A.caster, 'spsh' ) then // "Корона титана", настройки в других частях кода
        set A.upgrade2 = 1
    else
        set A.upgrade2 = 0
    endif
    
    set t = LoadTimerHandle( H, GetHandleId( A.caster ), SpellUpgrade )
    
    if t != null then
        set A.e = LoadEffectHandle( H, GetHandleId( t ), 0 )
       
        call PauseTimer( t )
        call FlushChildHashtable( H, GetHandleId( t ) )
        call DestroyTimer( t )
        
        call RemoveSavedHandle( H, GetHandleId( A.caster ), SpellUpgrade )
        
        set A.damage = A.damage * 2.50 // дополнительный урон от усиления "Корона титана"
        
        set t = null
    endif
    
    set A.attackType = ATTACK_TYPE_MAGIC
    set A.damageType = DAMAGE_TYPE_DEMOLITION
    set A.weaponType = null
    
    set A.time = 0.40 // время для первого удара
    set A.timePause = 0.00
    set A.speed = 1.20 // скорость перемещения
    set A.attack = 0
    
    call PauseUnit( A.caster, true )
    call SetUnitAnimationByIndexEx( A.caster, 2 ) // анимация первой атаки
    
    call SaveInteger( H, GetHandleId( A.t ), 0, A )
    call TimerStart( A.t, 0.01, true, function Move )
endfunction

private function Damage takes nothing returns nothing
    local SpellS A = LoadInteger( H, GetHandleId( GetExpiredTimer( ) ), 0 )
    local unit u
    
    call GroupEnumUnitsInRange( TempGroup, A.v.x, A.v.y, A.radius + UNIT_MAX_COLLISION, null )
            
    loop
        set u = FirstOfGroup( TempGroup )
        exitwhen u == null
        call GroupRemoveUnit( TempGroup, u )
        
        if IsUnitInRangeXY( u, A.v.x, A.v.y, A.radius ) then
            if UnitAlive( u ) and IsUnitEnemy( u, A.p ) then
                call DestroyEffect( AddSpecialEffectTarget( "Abilities\\Weapons\\LordofFlameMissile\\LordofFlameMissile.mdl", u, "chest" ) ) // доп. эффект при попадании
                call UnitDamageTarget( A.caster, u, A.damage, false, false, A.attackType, A.damageType, A.weaponType )
            endif
        endif
    endloop
    
    set A.time = A.time - 1.00 // периодичность урона землетрясения
    
    if A.time <= 0.00 then
        call PauseTimer( A.t )
        call FlushChildHashtable( H, GetHandleId( A.t ) )
        call DestroyTimer( A.t )
        
        call SetUnitAnimation( A.dummy, "death" )
        call UnitRemoveAbility( A.dummy, 'A001' )
        call UnitApplyTimedLife( A.dummy, 'BTLF', 3.00 ) // время анимации смерти
        
        set A.t = null
        set A.caster = null
        set A.dummy = null
        call A.v.destroy( )
        call A.destroy( )
    endif
endfunction

private function Spell_Actions_Death takes nothing returns nothing
    local SpellS A
    
    if UpgradedKill == 1 then
        set A = SpellS.create( )
        
        set A.t = CreateTimer( )
        set A.caster = GetKillingUnit( )
        set A.p = GetOwningPlayer( A.caster )
        set A.v = vector.create( GetUnitX( GetTriggerUnit( ) ), GetUnitY( GetTriggerUnit( ) ), 0.00 )
        
        set A.dummy = CreateUnit( A.p, 'u000', A.v.x, A.v.y, GetRandomReal( 0.00, 360.00 ) ) // даммик землетрясения
        
        call SetUnitX( A.dummy, A.v.x )
        call SetUnitY( A.dummy, A.v.y )
        call SetUnitAnimation( A.dummy, "birth" )
        call QueueUnitAnimation( A.dummy, "stand" )
        
        set A.radius = 300.00 // радиус землетрясения
        set A.damage = 100.00 // урон землетрясения
        set A.attackType = ATTACK_TYPE_MAGIC // тип атаки
        set A.damageType = DAMAGE_TYPE_FIRE // тип урона
        set A.weaponType = null // тип оружия (звук)
        set A.time = 6.00 // время землетрясения
        
        call SaveInteger( H, GetHandleId( A.t ), 0, A )
        call TimerStart( A.t, 1.00, true, function Damage ) // периодичность урона землетрясения
    endif
endfunction

//===========================================================================
private function Spell_Conditions takes nothing returns boolean
    return GetSpellAbilityId() == 'A000' // равкод абилки
endfunction

function InitTrig_Spell takes nothing returns nothing
    local trigger trg = CreateTrigger( )
    
    call TriggerRegisterAnyUnitEventBJ( trg, EVENT_PLAYER_UNIT_DEATH )
    call TriggerAddAction( trg, function Spell_Actions_Death )
    
    set trg = null
    
    set gg_trg_Spell = CreateTrigger(  )
    call TriggerRegisterAnyUnitEventBJ( gg_trg_Spell, EVENT_PLAYER_UNIT_SPELL_CAST )
    call TriggerAddCondition( gg_trg_Spell, Condition( function Spell_Conditions ) )
    call TriggerAddAction( gg_trg_Spell, function Spell_Actions )
    
    set TempItem = CreateItem( 'spsh', 0.00, 0.00 )
    call SetItemVisible( TempItem, false )
endfunction
endlibrary

Загруженные файлы
28
SebastianCarrey, бле, забыл добавить учёт того, что кастер жив. но комп уже выключил. В общем найди следующую строку в триггере Spell в функции Move: local boolean stunned = GetUnitAbilityLevel( A.caster, 'BPSE' ) > 0 и добавь or not UnitAlive( A.caster )
Должно выйти так:
local boolean stunned = GetUnitAbilityLevel( A.caster, 'BPSE' ) > 0 or not UnitAlive( A.caster )

И чтобы вдруг он при смерти не проиграл анимку Stand, чуть ниже найди call SetUnitAnimation( A.caster, "stand" ), и замени на
if UnitAlive( A.caster ) then
    call SetUnitAnimation( A.caster, "stand" )
endif
3
rsfghd:
Попробую сам поменять))
Тут правда нюанс с КД как я понимаю. Ругается)
Загруженные файлы
3
rsfghd:
Можно сделать от мин до макс значения что бы урон выглядел не статично.
И там же получается суммарный урон выводится? Урон от атаки + фиксированный магический же?
28
SebastianCarrey, посмотрел, к сожалению южапи немного скривил, либо реф с новым патчем изменил аргументы и выглядит следующим образом
BlzGetAbilityCooldown takes integer abilId, integer level returns real
Первым аргументом принимает равкод, а вторым уровень абилки, так что замени все эти строки на
BlzGetAbilityCooldown( 'A000', GetUnitAbilityLevel( A.caster, 'A000' ) )
Где А000 - равкод основной абилки
28
SebastianCarrey, я спрашивал у тебя за мин и макс атаку. Найди строку set A.damage = GetUniBaseDamageByIndex( ... ) и замени ее на
set A.damage = GetRandomInt( BlzGetUnitWeaponIntegerField( A.caster, UNIT_WEAPON_IF_ATTACK_DAMAGE_BASE_MINIMUM, 0 ), BlzGetUnitWeaponIntegerField( A.caster, UNIT_WEAPON_IF_ATTACK_DAMAGE_BASE_MAXIMUM, 0 ) ) + BlzGetUnitBonusDamageByIndex( A.caster, 0 )
Да, там суммарный урон выводится. Если нужно отдельный, то урон от атаки и абилки нужно записать в разные переменные, если нужно, могу объяснить, там буквально 2 строки написать в разных местах
28
SebastianCarrey, если не справляешься, то могу добавить вышеуказанное и скинуть код/карту
2
Заказ на работу
Придумал ещё спелл, которого нет (по крайней мере нормально сделанного, без багов):
Герой отталкивает вражеского юнита или героя (1 лвл - на 700 дистанцию, 2 лвл - на 800 дистанцию и тд. 5 лвлов всего у способности и враг получает стан на 2-3-5-6-7 сек в конце отталкивания, в зависимости от лвл способности). Knockback
И далее - всех кого этот враг задел, пока он летел назад - они тоже отталкиваются на 300 дистанцию и получают урон (в зависимости от лвл способности) и стан 1 сек!
Также сам враг получает урон каждый раз, когда он отталкивает юнитов собой (какой именно урон - зависит от лвл способности). Т.е. чем больше он оттолкнул, тем больше урона ему наносится! Ну и тем более урона он наносит сам своим юнитам.
Думаю в игре будет круто смотреться.
Ответы (5)
31
ShadowNinja, я даже такую наработку видел. Видать с фантазией у тебя беда...
2
nazarpunk, в этом я крайне сомневаюсь... Где тогда такая наработка, что бы я её скачал? Мне бы она не помешала
2
rsfghd, да, но это не совсем то... Тут смысл в том, что мы именно вражеским героем или юнитом раскидываем армию врага (+ чем больше своих он задел, тем больше ему урон)
Кстати - если он умрёт (враг, который летит) тогда абилка прекращается, и он больше никого раскинуть не сможет! Т.е. лучше выбрать цель на фулл хп
А у этой аббилки самим своим героем жертвуем - в толпу врагов врываемся (а таких абилок на самом деле много)
В геймплейном плане это 2 разные абилки и их в разных ситуациях используют
28
Выполнение заказа

Заклинание готово!

инструкция по импорту
скопировать папку Initialization и вставить в свою карту, перекопировать нестандартное ро и вставить в свою карту
в триггере Spell настроить всё, что помечено комментарием, на своё усмотрение, остальное требует минимальных знаний джасса
выполнено на UjAPI

Код

AllGlobals
library AllGlobalsLib
globals
    constant hashtable H = InitHashtable( )
    constant real UNIT_MAX_COLLISION = 200.00
    
    real MaxX
    real MinX
    real MaxY
    real MinY
endglobals

native UnitAlive takes unit id returns boolean

struct vector
    real x
    real y
    real z
    
    method length takes nothing returns real
        return SquareRoot( x * x + y * y + z * z )
    endmethod
    
    method normalize takes nothing returns nothing
        local real l = length( )
        
        if l == 0.00 then
            set l = 1.00
        endif
        
        set x = x / l
        set y = y / l
        set z = z / l
    endmethod
    
    static method create takes real x, real y, real z returns thistype
        local thistype this = thistype.allocate( )
        
        set this.x = x
        set this.y = y
        set this.z = z
        
        return this
    endmethod
endstruct

function RemoveStun takes nothing returns nothing
    local timer t = GetExpiredTimer( )
    local integer i = GetHandleId( t )
    
    call SetUnitStunned( LoadUnitHandle( H, i, 0 ), false )
    call DestroyEffect( LoadEffectHandle( H, i, 1 ) )
    
    call FlushChildHashtable( H, i )
    call DestroyTimer( t )
    
    set t = null
endfunction

function StunUnit takes unit u, real time, effect e returns nothing
    local timer t = CreateTimer( )
    
    call SetUnitStunned( u, true )
    
    call SaveUnitHandle( H, GetHandleId( t ), 0, u )
    call SaveEffectHandle( H, GetHandleId( t ), 1, e )
    call TimerStart( t, time, false, function RemoveStun )
    
    set t = null
endfunction

//===========================================================================
function InitTrig_AllGlobals takes nothing returns nothing
    //set gg_trg_AllGlobals = CreateTrigger(  )
    local rect r = GetWorldBounds( )
    
    set MaxX = GetRectMaxX( r )
    set MinX = GetRectMinX( r )
    set MaxY = GetRectMaxY( r )
    set MinY = GetRectMinY( r )
    
    call RemoveRect( r )
    set r = null
endfunction
endlibrary

Spell
library SpellLib
globals
    private constant group TempGroup = CreateGroup( )
    private item TempItem = null
endglobals

private struct ProjectileS
    timer t
    effect e
    effect e1
    
    real a
    
    vector array v[4]
    vector last
    
    real time
    real timeMax
endstruct

private struct SpellS
    timer t
    unit caster
    unit target
    player p
    vector v
    group g
    integer b
    integer lvl
    
    effect e
    effect e1
    
    real radius
    real damage
    real speed
    real distance
    real time
    
    attacktype attackType
    damagetype damageType
    weapontype weaponType
endstruct

private function Move takes nothing returns nothing
    local SpellS A = LoadInteger( H, GetHandleId( GetExpiredTimer( ) ), 0 )
    local SpellS B
    local real x = GetUnitX( A.target )
    local real y = GetUnitY( A.target )
    local real x1
    local real y1
    local unit u
    
    if A.b == 1 then
        set A.b = 2
        
        set bj_lastCreatedEffect = AddSpecialEffect( "Abilities\\Weapons\\DemolisherFireMissile\\DemolisherFireMissile.mdl", x, y )
        call SetSpecialEffectZ( bj_lastCreatedEffect, GetSpecialEffectZ( bj_lastCreatedEffect ) + 50.00 )
        call SetSpecialEffectOrientation( bj_lastCreatedEffect, Atan2( A.v.y, A.v.x ) * bj_RADTODEG, -90.00, 0.00 )
        call DestroyEffect( bj_lastCreatedEffect )
        
        set bj_lastCreatedEffect = AddSpecialEffect( "Abilities\\Spells\\Orc\\WarStomp\\WarStompCaster.mdl", x, y )
        call SetSpecialEffectZ( bj_lastCreatedEffect, GetSpecialEffectZ( bj_lastCreatedEffect ) + 50.00 )
        call SetSpecialEffectOrientation( bj_lastCreatedEffect, Atan2( A.v.y, A.v.x ) * bj_RADTODEG, -90.00, 0.00 )
        call DestroyEffect( bj_lastCreatedEffect )
        
        set bj_lastCreatedEffect = AddSpecialEffect( "Abilities\\Spells\\Other\\Doom\\DoomDeath.mdl", x, y )
        call SetSpecialEffectZ( bj_lastCreatedEffect, GetSpecialEffectZ( bj_lastCreatedEffect ) + 50.00 )
        call SetSpecialEffectOrientation( bj_lastCreatedEffect, Atan2( A.v.y, A.v.x ) * bj_RADTODEG, -90.00, 0.00 )
        call DestroyEffect( bj_lastCreatedEffect )
        
        call UnitDamageTarget( A.caster, A.target, A.damage, false, false, A.attackType, A.damageType, A.weaponType )
        
        call DestroyEffect( A.e )
        call DestroyEffect( A.e1 )
        
        set A.e = AddSpecialEffectTarget( "Abilities\\Spells\\Human\\FlameStrike\\FlameStrikeEmbers.mdl", A.target, "origin" )
        set A.e1 = AddSpecialEffectTarget( "Abilities\\Spells\\Other\\BreathOfFire\\BreathOfFireDamage.mdl", A.target, "origin" )
    endif
    
    if A.speed > A.distance then
        set A.speed = A.distance
    endif
    
    set x = x + A.speed * A.v.x
    set y = y + A.speed * A.v.y
    
    if A.b >= 2 then
        set A.b = A.b + 1
        
        if A.b == 6 then
            set bj_lastCreatedEffect = AddSpecialEffect( "Abilities\\Weapons\\PhoenixMissile\\Phoenix_Missile_mini.mdl", x, y )
            call SetSpecialEffectZ( bj_lastCreatedEffect, GetSpecialEffectZ( bj_lastCreatedEffect ) + 30.00 )
            call DestroyEffect( bj_lastCreatedEffect )
            
            set A.b = 2
        endif
    endif
    
    set A.distance = A.distance - A.speed
    
    call SetItemPosition( TempItem, x, y )
    call SetItemVisible( TempItem, false )
    
    set x1 = GetItemX( TempItem )
    set y1 = GetItemY( TempItem )
    
    if ( x - 1.00 > x1 or x + 1.00 < x1 ) or ( y - 1.00 > y1 or y + 1.00 < y1 ) then
        set A.distance = 0.00
        call DestroyEffect( AddSpecialEffect( "Abilities\\Spells\\Other\\Volcano\\VolcanoDeath.mdl", x, y ) )
    else
        call SetUnitX( A.target, x )
        call SetUnitY( A.target, y )
    endif
    
    if A.g != null then
        call GroupEnumUnitsInRange( TempGroup, x, y, A.radius + UNIT_MAX_COLLISION, null )
        
        loop
            set u = FirstOfGroup( TempGroup )
            exitwhen u == null
            call GroupRemoveUnit( TempGroup, u )
            
            if not IsUnitInGroup( u, A.g ) and IsUnitInRange( u, A.target, A.radius ) then
                if UnitAlive( u ) and IsUnitEnemy( u, A.p ) then
                    call GroupAddUnit( A.g, u )
                    
                    call DestroyEffect( AddSpecialEffectTarget( "Abilities\\Weapons\\LordofFlameMissile\\LordofFlameMissile.mdl", u, "chest" ) )
                    call DestroyEffect( AddSpecialEffectTarget( "Abilities\\Spells\\Items\\AIfb\\AIfbSpecialArt.mdl", u, "chest" ) )
                    
                    call UnitDamageTarget( A.caster, A.target, A.damage, false, false, A.attackType, A.damageType, A.weaponType )
                    call UnitDamageTarget( A.caster, u, A.damage, false, false, A.attackType, A.damageType, A.weaponType )
                    call StunUnit( u, 1.00, AddSpecialEffectTarget( "Abilities\\Spells\\Human\\Thunderclap\\ThunderclapTarget.mdl", u, "overhead" ) )
                    
                    set B = SpellS.create( )
                    
                    set B.t = CreateTimer( )
                    set B.target = u
                    set B.v = vector.create( GetUnitX( u ) - x, GetUnitY( u ) - y, 0.00 )
                    call B.v.normalize( )
                    set B.b = 0
                    
                    call SetUnitStunned( u, true )
                    
                    set A.speed = A.speed * 0.90
                    set B.speed = A.speed
                    set B.distance = B.speed / 0.015 * 0.50
                    set A.distance = A.distance * 0.90
                    
                    call SaveInteger( H, GetHandleId( B.t ), 0, B )
                    call TimerStart( B.t, 0.01, false, function Move )
                endif
            endif
        endloop
    endif
    
    if A.distance <= 0.00 or not UnitAlive( A.target ) then
        call PauseTimer( A.t )
        call FlushChildHashtable( H, GetHandleId( A.t ) )
        call DestroyTimer( A.t )
        
        if A.b >= 2 then
            call DestroyEffect( A.e )
            call DestroyEffect( A.e1 )
            set A.e = null
            set A.e1 = null
            
            if UnitAlive( A.target ) then
                call DestroyEffect( AddSpecialEffectTarget( "Abilities\\Weapons\\PhoenixMissile\\Phoenix_Missile.mdl", A.target, "chest" ) )
                call StunUnit( A.target, 1.00 + 1.00 * A.lvl, AddSpecialEffectTarget( "Abilities\\Spells\\Human\\Thunderclap\\ThunderclapTarget.mdl", A.target, "overhead" ) )
            endif
        endif
        
        call SetUnitStunned( A.target, false )
        
        call DestroyGroup( A.g )
        
        set A.t = null
        set A.g = null
        set A.caster = null
        set A.target = null
        call A.v.destroy( )
        call A.destroy( )
    else
        call TimerStart( A.t, 0.01, false, function Move )
    endif
endfunction

private function MoveProjectile takes nothing returns nothing
    local ProjectileS A = LoadInteger( H, GetHandleId( GetExpiredTimer( ) ), 0 )
    local real array x
    local real array y
    local real array z
    local integer k = 0
    local integer i
    
    set A.time = A.time + 0.01 / A.timeMax
    
    if A.time >= 0.50 then
        set A.time = A.time + 0.01 / A.timeMax
    endif
    
    if A.time > 1.00 then
        set A.time = 1.00
    endif
    
    loop
        set x[k] = A.v[k].x
        set y[k] = A.v[k].y
        set z[k] = A.v[k].z
        
        set k = k + 1
        exitwhen k >= 4
    endloop
    
    set k = 0
    
    loop
        set i = 0
        
        loop
            set x[i] = ( 1.00 - A.time ) * x[i] + A.time * x[i + 1]
            set y[i] = ( 1.00 - A.time ) * y[i] + A.time * y[i + 1]
            set z[i] = ( 1.00 - A.time ) * z[i] + A.time * z[i + 1]
            
            set i = i + 1
            exitwhen i > 4 - k
        endloop
        
        set k = k + 1
        exitwhen k >= 4 - 1
    endloop
    
    call SetSpecialEffectPositionWithZ( A.e, x[0], y[0], z[0] )
    call SetSpecialEffectPositionWithZ( A.e1, x[0], y[0], z[0] )
    call SetSpecialEffectOrientation( A.e, A.a, Atan2( z[0] - A.last.z, SquareRoot( ( x[0] - A.last.x ) * ( x[0] - A.last.x ) + ( y[0] - A.last.y ) * ( y[0] - A.last.y ) ) ) * bj_RADTODEG, 0.00 )
    call SetSpecialEffectOrientation( A.e1, A.a, Atan2( z[0] - A.last.z, SquareRoot( ( x[0] - A.last.x ) * ( x[0] - A.last.x ) + ( y[0] - A.last.y ) * ( y[0] - A.last.y ) ) ) * bj_RADTODEG, 0.00 )
    
    if A.time >= 1.00 then
        call PauseTimer( A.t )
        call FlushChildHashtable( H, GetHandleId( A.t ) )
        call DestroyTimer( A.t )
        
        call DestroyEffect( A.e )
        call DestroyEffect( A.e1 )
        
        set i = 0
        
        loop
            call A.v[i].destroy( )
            
            set i = i + 1
            exitwhen i >= 4
        endloop
        
        set A.e = null
        set A.e1 = null
        call A.last.destroy( )
        call A.destroy( )
    else
        set A.last.x = x[0]
        set A.last.y = y[0]
        set A.last.z = z[0]
    endif
endfunction

private function Spell_Actions takes nothing returns nothing
    local SpellS A = SpellS.create( )
    local ProjectileS B
    local real x
    local real y
    local real z
    local real a
    local real d
    
    set A.t = CreateTimer( )
    set A.caster = GetTriggerUnit( )
    set A.target = GetSpellTargetUnit( )
    set A.p = GetOwningPlayer( A.caster )
    set A.g = CreateGroup( )
    set A.b = 1
    set A.radius = 64.00 // радиус столкновения
    
    set A.e = AddSpecialEffectTarget( "Abilities\\Weapons\\LavaSpawnMissile\\LavaSpawnMissile.mdl", A.caster, "left hand" )
    set A.e1 = AddSpecialEffectTarget( "Abilities\\Weapons\\LavaSpawnMissile\\LavaSpawnMissile.mdl", A.caster, "right hand" )
    
    set x = GetUnitX( A.caster )
    set y = GetUnitY( A.caster )
    set z = GetAxisZ( x, y ) + GetUnitFlyHeight( A.caster ) + 50.00
    
    set A.v = vector.create( GetUnitX( A.target ) - x, GetUnitY( A.target ) - y, 0.00 )
    set d = A.v.length( )
    call A.v.normalize( )
    set a = Atan2( A.v.y, A.v.x )
    
    set A.lvl = GetUnitAbilityLevel( A.caster, GetSpellAbilityId( ) )
    
    set A.distance = 600.00 + 100.00 * A.lvl // дистанция
    set A.speed = A.distance * 0.015 // скорость
    set A.damage = 25.00 + 10.00 * A.lvl // урон
    
    set A.attackType = ATTACK_TYPE_MAGIC // тип атаки
    set A.damageType = DAMAGE_TYPE_FIRE // тип урона
    set A.weaponType = null // тип оружия (звук)
    
    call SetUnitStunned( A.target, true )
    call GroupAddUnit( A.g, A.caster )
    call GroupAddUnit( A.g, A.target )
    
    call SaveInteger( H, GetHandleId( A.t ), 0, A )
    call TimerStart( A.t, 1.10, false, function Move )
    
    //===
    set B = ProjectileS.create( )
    set B.t = CreateTimer( )
    
    set B.a = a + bj_PI * 0.20
    
    set B.last = vector.create( x, y, z )
    set B.v[0] = vector.create( B.last.x, B.last.y, B.last.z )
    set B.v[1] = vector.create( B.v[0].x - ( d / 2.00 + 500.00 ) * Cos( B.a ), B.v[0].y - ( d / 2.00 + 500.00 ) * Sin( B.a ), B.v[0].z + 300.00 )
    set B.v[2] = vector.create( B.v[0].x + ( d - 200.00 ) * Cos( B.a + bj_PI * 0.10 ), B.v[0].y + ( d - 200.00 ) * Sin( B.a + bj_PI * 0.10 ), B.v[0].z )
    set B.v[3] = vector.create( GetUnitX( A.target ), GetUnitY( A.target ), 0.00 )
    set B.v[3].z = GetAxisZ( B.v[3].x, B.v[3].y ) + 50.00
    
    set B.e = AddSpecialEffect( "units\\human\\phoenix\\phoenix.mdl", B.v[0].x, B.v[0].y )
    call SetSpecialEffectZ( B.e, B.v[0].z )
    call SetSpecialEffectScale( B.e, 0.60 )
    call SetSpecialEffectAlpha( B.e, 155 )
    
    set B.e1 = AddSpecialEffect( "Abilities\\Weapons\\PhoenixMissile\\Phoenix_Missile.mdl", B.v[0].x, B.v[0].y )
     
    set B.a = B.a * bj_RADTODEG
    set B.time = 0.00
    set B.timeMax = 1.50
    
    call SaveInteger( H, GetHandleId( B.t ), 0, B )
    call TimerStart( B.t, 0.01, true, function MoveProjectile )
    
    //===
    set B = ProjectileS.create( )
    set B.t = CreateTimer( )
    
    set B.a = a - bj_PI * 0.20
    
    set B.last = vector.create( x, y, z )
    set B.v[0] = vector.create( B.last.x, B.last.y, B.last.z )
    set B.v[1] = vector.create( B.v[0].x - ( d / 2.00 + 500.00 ) * Cos( B.a ), B.v[0].y - ( d / 2.00 + 500.00 ) * Sin( B.a ), B.v[0].z + 300.00 )
    set B.v[2] = vector.create( B.v[0].x + ( d - 200.00 ) * Cos( B.a - bj_PI * 0.10 ), B.v[0].y + ( d - 200.00 ) * Sin( B.a - bj_PI * 0.10 ), B.v[0].z )
    set B.v[3] = vector.create( GetUnitX( A.target ), GetUnitY( A.target ), 0.00 )
    set B.v[3].z = GetAxisZ( B.v[3].x, B.v[3].y ) + 50.00
    
    set B.e = AddSpecialEffect( "units\\human\\phoenix\\phoenix.mdl", B.v[0].x, B.v[0].y )
    call SetSpecialEffectZ( B.e, B.v[0].z )
    call SetSpecialEffectScale( B.e, 0.60 )
    call SetSpecialEffectAlpha( B.e, 155 )
    
    set B.e1 = AddSpecialEffect( "Abilities\\Weapons\\PhoenixMissile\\Phoenix_Missile.mdl", B.v[0].x, B.v[0].y )
    
    set B.a = B.a * bj_RADTODEG
    set B.time = 0.00
    set B.timeMax = 1.50
    
    call SaveInteger( H, GetHandleId( B.t ), 0, B )
    call TimerStart( B.t, 0.01, true, function MoveProjectile )
endfunction

//===========================================================================
private function Spell_Conditions takes nothing returns boolean
    return GetSpellAbilityId() == 'A000' // равкод
endfunction

function InitTrig_Spell takes nothing returns nothing
    set gg_trg_Spell = CreateTrigger(  )
    call TriggerRegisterAnyUnitEventBJ( gg_trg_Spell, EVENT_PLAYER_UNIT_SPELL_EFFECT )
    call TriggerAddCondition( gg_trg_Spell, Condition( function Spell_Conditions ) )
    call TriggerAddAction( gg_trg_Spell, function Spell_Actions )
    
    set TempItem = CreateItem( 'spsh', 0.00, 0.00 )
    call SetItemVisible( TempItem, false )
endfunction
endlibrary

Загруженные файлы
31

Заказ

Название: Щит
Метод: UjAPI
Версия Warcraft III: На свой вкус
Техническое описание:
Две способности в синергии:
  • Первая кастует channel щит, который ловит все летящие прожектайлы. Даже от автоатаки.
  • Вторая направляет все пойманные прожектайлы в выбранную цель.
Ответы (1)
28
nazarpunk, мб когда апи с прожектайлами починятся и дополнятся, то сделаю заказы с копированием снарядов, сейчас каждый раз на грабли натыкаюсь и тильтую
31

Заказ

Название: Союз крови
Метод: UjAPI
Версия Warcraft III: На свой вкус
Техническое описание:
Три способности в синергии:
  • Первая вешает бафф который распределяет урон по юнитам имеющим этот баф между всеми юнитами имеющими этот бафф.
  • Вторая и третья это channel молния, которая кастуется только в юнита имеющая этот баф. Одна вливает весь урон по кастеру в юнитов имеющих этот баф. Вторая вливает всё лечение кастера в юнитов имеющих этот баф.
31

Заказ

Название: Возмездие
Метод: UjAPI
Версия Warcraft III: На свой вкус
Техническое описание:
Бафф на одиночную цель. Любой прожектайл запущенный юнитом с баффом будет скопирован и запущен от кастера в этого юнита.
31

Заказ

Название: Аркан способности
Метод: UjAPI
Версия Warcraft III: На свой вкус
Техническое описание:
Пассивная способность. Любая способность с целью скастованная на героя с этой пассивкой сжигает у героя затраченную на неё ману и создаёт в инвентаре предмет, который позволяет скастовать эту способность. Лимит стака предметов равен уровню героя.
10
Заказ на работу
Название: наездник
Метод: GUI
Версия Warcraft III: 1.26
Техническое описание:
Герой садится на лошадь, овцу, свинью, при условии что у героя в инвентаре есть седло ( можно любой другой предмет). У животного появляется шкала усталости.
По седлам: 1 ур седла 200м, 2 ур. 400м.
После того как герой слез, усталость животного восполняется 1 ед в пол секунды. Максимально 100
Ответы (1)
28
ME_RiDi, тз с результатом хз. Животным абилку дирижабля дать или это трансформация юнита как с лучница и и гиппогрифами? Или просто периодически героя перемещать в позицию животного? Как затрачивается шкала усталости? Что будет при полном нуле? Нужно ли отображать шкалу? Если да, то каким способом?
2
Хотел ещё одну способность описать... Но кажется автор всё, выгорел)
Или у него больше нет времени. А спамить способностями не хочется
Ответы (2)
28
ShadowNinja, да не выгорел. Пытался заказ назарпанка сделать, а на южапи функции не работали должным образом, анрайз что-то поправил и продолжает исправлять, но я потратил на это выходной. Оставляй заказы, по мере заинтересованности буду делать. Вечером отталкиванием займусь, возьму анимку spell у чародея крови, выпущу двух фениксов по дуге в сторону цели и вместе со свистелками реализую отталкивание. Единственное что мне не очень нравится, это то, что цель может двигаться, из-за этого проблемы логические могут возникнуть. Впрочем, если делать мгновенное отталкивание без украшений, то всё будет оке, но у тебя технические задачи на полёт моей собственной фантазии. Буду делать на южапи
У меня в будние очень мало времени на хобби
28
ShadowNinja, чтоб ты не думал, что я ничем не занимался
Кроме этого в планах сделать кат со всеми выполненными заказами в самом ресурсе, чтобы люди могли искать интересующие спеллы не бегая по страницам комментариев
2
Заказ на работу
Пассивный спелл для определённой модели
Нашёл я на просторах Хайва такую модель, и у неё есть анимация Spell Slam.
Он стреляет перед собой лазерами вот так
Так вот, спелл такой: есть 20% что при каждом выстреле проиграется такая анимация и этот зелёный лазер нанесёт 150 ед урона всем наземным врагам! Именно что бы лазер попал по врагу, как в анимации. Если это возможно, т.е. под кораблём он никого не должен задамажить, а только там где лазер пройдёт (ну или примерно). Притом сама атака тоже должна пройти (помимо этого спелла).
Ну или это будет вместо атаки, если так не получится норм сделать!
Ну или примерно сделать как получится для этой анимации Spell Slam, но спелл должен быть пассивный, а не активный т.к. таких кораблей может быть много
Модельку и картинку прилагаю!
Загруженные файлы
Ответы (11)
28
Выполнение заказа

Заклинание готово!

я немного не понял нужен ли учёт сферических координат, если корабль только по наземным должен дамажить, поэтому просто пихнул проверку, что юнит не летающий
на видосе 100% шанс срабатывания, пассивка срабатывает после получения урона противником, могу переделать под старт вылета снаряда либо при замахе
инструкция по импорту
скопировать папку Initialization и вставить в свою карту
в триггере DamageEvent:
78 строка - указать абилку и шанс такой атаки (абилку выдать юнитам, что должны проводить эту атаку)
85 строка - начальный оффсет угла от взгляда атакующего
86 строка - скорость вращения лазеров
93 строка - через сколько секунд появляются лазеры после начала проигрывания анимки Spell Slam
21-24 строки - оффсеты для лазеров
30 строка - радиус вокруг атакующего
38 строка - ширина лазера (32.00)
47, 49-52 строки - шаг лазера (чем больше тем менее точно, но более оптимизировано, лучше не ставить больше радиуса лазера)
48 строка - дальность лазера
54-55 - эффекты, использовал по сути как дебаг для ориентации скорости, оффсета и угла лазеров, можно удалить строки
58 - максимальный угол лазеров
71 - периодичность таймера (чем больше, тем оптимизированнее и менее точно, при изменении этой строки на 86 строке (0.05) тоже изменить периодичность)
делал на южапи

Код

AllGlobals
library AllGlobalsLib
globals
    constant hashtable H = InitHashtable( )
    constant real UNIT_MAX_COLLISION = 200.00
endglobals

native UnitAlive takes unit id returns boolean

//===========================================================================
//function InitTrig_AllGlobals takes nothing returns nothing
    //set gg_trg_AllGlobals = CreateTrigger(  )
//endfunction
endlibrary

DamageEvent
library DamageEventLib
globals
    private constant group TempGroup = CreateGroup( )
endglobals

private struct SpellS
    timer t
    unit caster
    player p
    group g
    real angle
    real speed
endstruct

private function Damage takes nothing returns nothing
    local SpellS A = LoadInteger( H, GetHandleId( GetExpiredTimer( ) ), 0 )
    local real d = 0.00 
    local real a = GetUnitFacing( A.caster ) * bj_DEGTORAD
    local real x = GetUnitX( A.caster )
    local real y = GetUnitY( A.caster )
    local real x1 = x + 125.00 * Cos( a + bj_PI * 0.30 )
    local real y1 = y + 125.00 * Sin( a + bj_PI * 0.30 )
    local real x2 = x + 125.00 * Cos( a - bj_PI * 0.30 )
    local real y2 = y + 125.00 * Sin( a - bj_PI * 0.30 )
    local unit u
    
    call GroupEnumUnitsInRange( TempGroup, x, y, 400.00 + UNIT_MAX_COLLISION, null )
    
    set A.angle = A.angle + A.speed
    
    loop
        loop
            set u = GroupForEachUnit( TempGroup )
            exitwhen u == null
            
            if not IsUnitInGroup( u, A.g ) then
                if IsUnitInRangeXY( u, x1, y1, 32.00 ) or IsUnitInRangeXY( u, x2, y2, 32.00 )then
                    if UnitAlive( u ) and IsUnitEnemy( u, A.p ) and not IsUnitType( u, UNIT_TYPE_FLYING ) then
                        call GroupAddUnit( A.g, u )
                        call UnitDamageTarget( A.caster, u, 150.00, false, false, null, null, null )
                    endif
                endif
            endif
        endloop
        
        set d = d + 32.00
        exitwhen d >= 200.00
        set x1 = x1 + 32.00 * Cos( a + A.angle )
        set y1 = y1 + 32.00 * Sin( a + A.angle )
        set x2 = x2 + 32.00 * Cos( a - A.angle )
        set y2 = y2 + 32.00 * Sin( a - A.angle )
        
        call DestroyEffect( AddSpecialEffect( "Abilities\\Weapons\\IllidanMissile\\IllidanMissile.mdl", x1, y1 ) )
        call DestroyEffect( AddSpecialEffect( "Abilities\\Weapons\\IllidanMissile\\IllidanMissile.mdl", x2, y2 ) )
    endloop
    
    call GroupClear( TempGroup )
    
    if A.angle * bj_RADTODEG >= 120.00 or not UnitAlive( A.caster ) then
        call PauseTimer( A.t )
        call DestroyTimer( A.t )
        call FlushChildHashtable( H, GetHandleId( A.t ) )
        
        call SetUnitStunned( A.caster, false )
        call DestroyGroup( A.g )
        
        set A.t = null
        set A.g = null
        set A.caster = null
        call A.destroy( )
    else
        call TimerStart( A.t, 0.05, false, function Damage )
    endif
endfunction

private function DamageEvent_Actions takes nothing returns nothing
    local SpellS A
    
    if GetUnitAbilityLevel( GetEventDamageSource( ), 'A000' ) > 0 and GetEventIsAttack( ) and GetRandomInt( 1, 100 ) <= 20 then
        set A = SpellS.create( )
        
        set A.t = CreateTimer( )
        set A.caster = GetEventDamageSource( )
        set A.p = GetOwningPlayer( A.caster )
        set A.g = CreateGroup( )
        set A.angle = 60.00 * bj_DEGTORAD
        set A.speed = 60.00 / 0.75 * 0.05 * bj_DEGTORAD
        
        call SetUnitStunned( A.caster, true )
        call SetUnitAnimation( A.caster, "spell slam" )
        call QueueUnitAnimation( A.caster, "stand" )
        
        call SaveInteger( H, GetHandleId( A.t ), 0, A )
        call TimerStart( A.t, 0.25, false, function Damage )
    endif
endfunction

//===========================================================================
function InitTrig_DamageEvent takes nothing returns nothing
    set gg_trg_DamageEvent = CreateTrigger(  )
    call TriggerRegisterAnyUnitEventBJ( gg_trg_DamageEvent, EVENT_PLAYER_UNIT_DAMAGED )
    call TriggerAddAction( gg_trg_DamageEvent, function DamageEvent_Actions )
endfunction
endlibrary

Загруженные файлы
12
rsfghd, крутой спелл... А можно его для Reforget версии? А то он на ней не работает (ошибку выписывает)
28
FIRERANGER, скрин ошибки нужен, я просто названия функций не знаю на рефе, но скорее будет жаловаться только на GetEventIsAttack( ) где нужно добавить Blz вначале названия функции
12
rsfghd, вот такие ошибки... Какие-то непонятные! Хотелось бы этот спелл в свою карту в рефоржете
Загруженные файлы
12
rsfghd, да точно... Забыл что эта галочка в каждой новой карте слетает.
Только теперь такая ошибка! Можешь плз пофиксить для рефа?
Загруженные файлы
28
FIRERANGER, добавь приставки Blz к каждой из функций, что показывает тебе ошибка. То есть не SetUnitStunned а BlzSetUnitStunned и всё заработает (если эти функции там есть конечно, иначе действительно придется переписывать некоторые моменты и добавить систему стана)
12
rsfghd, к сожалению нет... Эти 3 ошибки остались... Можешь под реф переделать спелл плз?
А то получается что любая карта с этим спелом на рефе не пойдёт. Хотя большинство старых карт идут хорошо
28
Вышла новая версия! Прокрутить к ресурсу
FIRERANGER, убрал GroupForEachUnit и воспользовался обычным FirstOfGroup, заменил SetUnitStunned на BlzPauseUnitEx
DamageEvent
library DamageEventLib
globals
    private constant group TempGroup = CreateGroup( )
endglobals

private struct SpellS
    timer t
    unit caster
    player p
    group g
    real angle
    real speed
endstruct

private function Damage takes nothing returns nothing
    local SpellS A = LoadInteger( H, GetHandleId( GetExpiredTimer( ) ), 0 )
    local real d = 0.00 
    local real a = GetUnitFacing( A.caster ) * bj_DEGTORAD
    local real x = GetUnitX( A.caster )
    local real y = GetUnitY( A.caster )
    local real x1 = x + 125.00 * Cos( a + bj_PI * 0.30 )
    local real y1 = y + 125.00 * Sin( a + bj_PI * 0.30 )
    local real x2 = x + 125.00 * Cos( a - bj_PI * 0.30 )
    local real y2 = y + 125.00 * Sin( a - bj_PI * 0.30 )
    local unit u
    
    set A.angle = A.angle + A.speed
    
    loop
        call GroupEnumUnitsInRange( TempGroup, x, y, 400.00 + UNIT_MAX_COLLISION, null )
        
        loop
            set u = FirstOfGroup( TempGroup )
            exitwhen u == null
            call GroupRemoveUnit( TempGroup, u )
            
            if not IsUnitInGroup( u, A.g ) then
                if IsUnitInRangeXY( u, x1, y1, 32.00 ) or IsUnitInRangeXY( u, x2, y2, 32.00 )then
                    if UnitAlive( u ) and IsUnitEnemy( u, A.p ) and not IsUnitType( u, UNIT_TYPE_FLYING ) then
                        call GroupAddUnit( A.g, u )
                        call UnitDamageTarget( A.caster, u, 150.00, false, false, null, null, null )
                    endif
                endif
            endif
        endloop
        
        set d = d + 32.00
        exitwhen d >= 200.00
        set x1 = x1 + 32.00 * Cos( a + A.angle )
        set y1 = y1 + 32.00 * Sin( a + A.angle )
        set x2 = x2 + 32.00 * Cos( a - A.angle )
        set y2 = y2 + 32.00 * Sin( a - A.angle )
        
        call DestroyEffect( AddSpecialEffect( "Abilities\\Weapons\\IllidanMissile\\IllidanMissile.mdl", x1, y1 ) )
        call DestroyEffect( AddSpecialEffect( "Abilities\\Weapons\\IllidanMissile\\IllidanMissile.mdl", x2, y2 ) )
    endloop
    
    if A.angle * bj_RADTODEG >= 120.00 or not UnitAlive( A.caster ) then
        call PauseTimer( A.t )
        call DestroyTimer( A.t )
        call FlushChildHashtable( H, GetHandleId( A.t ) )
        
        call BlzPauseUnitEx( A.caster, false )
        call DestroyGroup( A.g )
        
        set A.t = null
        set A.g = null
        set A.caster = null
        call A.destroy( )
    else
        call TimerStart( A.t, 0.05, false, function Damage )
    endif
endfunction

private function DamageEvent_Actions takes nothing returns nothing
    local SpellS A
    
    if GetUnitAbilityLevel( GetEventDamageSource( ), 'A000' ) > 0 and BlzGetEventIsAttack( ) and GetRandomInt( 1, 100 ) <= 100 then
        set A = SpellS.create( )
        
        set A.t = CreateTimer( )
        set A.caster = GetEventDamageSource( )
        set A.p = GetOwningPlayer( A.caster )
        set A.g = CreateGroup( )
        set A.angle = 60.00 * bj_DEGTORAD
        set A.speed = 60.00 / 0.75 * 0.05 * bj_DEGTORAD
        
        call BlzPauseUnitEx( A.caster, true )
        call SetUnitAnimation( A.caster, "spell slam" )
        call QueueUnitAnimation( A.caster, "stand" )
        
        call SaveInteger( H, GetHandleId( A.t ), 0, A )
        call TimerStart( A.t, 0.25, false, function Damage )
    endif
endfunction

//===========================================================================
function InitTrig_DamageEvent takes nothing returns nothing
    set gg_trg_DamageEvent = CreateTrigger(  )
    call TriggerRegisterAnyUnitEventBJ( gg_trg_DamageEvent, EVENT_PLAYER_UNIT_DAMAGED )
    call TriggerAddAction( gg_trg_DamageEvent, function DamageEvent_Actions )
endfunction
endlibrary


стоит 100% шанс, как изменить я уже описывал выше
Загруженные файлы
1

Заказ

Название: Название способности (опционально, если заказ один)
Метод: JASS/vJASS
Версия Warcraft III: Любая версия
Загруженные файлы
Ответы (6)
28
UndeadFisher, на стандартных эффектах это будет менее эффектно выглядеть, но попробую что-нибудь придумать
28
Выполнение заказа

Заклинание готово!

инструкция по импорту
удалить триггеры ниже триггера Spell
скопировать папку Initialization и вставить в свою карту
указать равкод абилки на 367 строке триггера Spell
изменить строки 340-344 на свой вкус
всё остальное требует минимальных знаний джасса
сделано на южапи

Код

AllGlobals
library AllGlobalsLib
globals
    constant hashtable H = InitHashtable( )
    constant real UNIT_MAX_COLLISION = 200.00
endglobals

native UnitAlive takes unit id returns boolean

struct vector
    real x
    real y
    real z
    
    method length takes nothing returns real
        return SquareRoot( x * x + y * y + z * z )
    endmethod
    
    method normalize takes nothing returns nothing
        local real l = length( )
        
        if l == 0.00 then
            set l = 1.00
        endif
        
        set x = x / l
        set y = y / l
        set z = z / l
    endmethod
    
    static method create takes real x, real y, real z returns thistype
        local thistype this = thistype.allocate( )
        
        set this.x = x
        set this.y = y
        set this.z = z
        
        return this
    endmethod
endstruct
endlibrary

//===========================================================================
//function InitTrig_AllGlobals takes nothing returns nothing
    //set gg_trg_AllGlobals = CreateTrigger(  )
//endfunction

Spell
library SpellLib
globals
    private constant group TempGroup = CreateGroup( )
endglobals

private struct SpellS
    timer t
    unit caster
    effect e
    player p
    vector v
    vector l
    integer i
    group g
    
    real damage
    real speed
    real distance
    real time
    real radius
    handlelist effectList
    
    attacktype attackType
    damagetype damageType
    weapontype weaponType
endstruct

private function Move takes nothing returns nothing
    local SpellS A = LoadInteger( H, GetHandleId( GetExpiredTimer( ) ), 0 )
    
    if A.speed > A.distance then
        set A.speed = A.distance
    endif
    
    set A.distance = A.distance - A.speed
    
    set A.l.x = A.l.x + A.speed * A.v.x
    set A.l.y = A.l.y + A.speed * A.v.y
    set A.l.z = A.l.z + A.speed * A.v.z
    
    call SetSpecialEffectPositionWithZ( A.e, A.l.x, A.l.y, A.l.z )
    
    if A.distance <= 0.00 or A.l.z <= GetAxisZ( A.l.x, A.l.y ) + 32.00 then
        call PauseTimer( A.t )
        call FlushChildHashtable( H, GetHandleId( A.t ) )
        call DestroyTimer( A.t )
        
        call DestroyEffect( A.e )
        
        if A.i == 1 then
            call SetSpecialEffectVisible( A.e, false )
            
            set A.e = AddSpecialEffect( "Abilities\\Spells\\Orc\\MirrorImage\\MirrorImageCaster.mdl", A.l.x, A.l.y )
            call SetSpecialEffectZ( A.e, A.l.z )
            call SetSpecialEffectOrientation( A.e, Atan2( A.v.y, A.v.x ) * bj_RADTODEG, 45.00, 0.00 )
            call SetSpecialEffectTimeScale( A.e, 2.00 )
            call DestroyEffect( A.e )
        endif
        
        set A.e = null
        set A.t = null
        call A.l.destroy( )
        call A.v.destroy( )
        call A.destroy( )
    endif
endfunction

private function Damage takes nothing returns nothing
    local SpellS A = LoadInteger( H, GetHandleId( GetExpiredTimer( ) ), 0 )
    local unit u
    
    loop
        set u = FirstOfGroup( A.g )
        exitwhen u == null
        call GroupRemoveUnit( A.g, u )
        
        call SetUnitStunned( u, false )
        call SetUnitTimeScale( u, 1.00 )
        call DestroyEffect( AddSpecialEffectTarget( "Abilities\\Weapons\\PhoenixMissile\\Phoenix_Missile.mdl", u, "chest" ) )
        
        call UnitDamageTarget( A.caster, u, A.damage, false, false, A.attackType, A.damageType, A.weaponType )
    endloop
    
    call PauseUnit( A.caster, false )
    
    set A.l.z = GetUnitFacing( A.caster ) * bj_DEGTORAD
    set A.l.x = A.l.x + 100.00 * Cos( A.l.z )
    set A.l.y = A.l.y + 100.00 * Sin( A.l.z )
    
    call DestroyEffect( A.e )
    
    set A.e = AddSpecialEffect( "Objects\\Spawnmodels\\Other\\NeutralBuildingExplosion\\NeutralBuildingExplosion.mdl", A.l.x, A.l.y )
    call DestroyEffect( A.e )
    
    loop
        call DestroyEffect( HandleListGetEffectByIndex( A.effectList, A.i ) )
        
        set A.i = A.i - 1
        exitwhen A.i < 0
    endloop
    
    call HandleListDestroy( A.effectList )
    
    call PauseTimer( A.t )
    call FlushChildHashtable( H, GetHandleId( A.t ) )
    call DestroyTimer( A.t )
    
    call DestroyGroup( A.g )
    
    set A.g = null
    set A.t = null
    set A.e = null
    set A.caster = null
    call A.l.destroy( )
    call A.destroy( )
endfunction

private function AddHitEffect takes nothing returns nothing
    local integer i = GetRandomInt( 0, 5 )
    
    if i == 0 then
        call DestroyEffect( AddSpecialEffectTarget( "Abilities\\Weapons\\LavaSpawnMissile\\LavaSpawnMissile.mdl", GetEnumUnit( ), "chest" ) )
    elseif i == 1 then
        call DestroyEffect( AddSpecialEffectTarget( "Abilities\\Weapons\\LavaSpawnMissile\\LavaSpawnMissile.mdl", GetEnumUnit( ), "head" ) )
    elseif i == 2 then
        call DestroyEffect( AddSpecialEffectTarget( "Abilities\\Weapons\\LavaSpawnMissile\\LavaSpawnMissile.mdl", GetEnumUnit( ), "left hand" ) )
    elseif i == 3 then
        call DestroyEffect( AddSpecialEffectTarget( "Abilities\\Weapons\\LavaSpawnMissile\\LavaSpawnMissile.mdl", GetEnumUnit( ), "right hand" ) )
    elseif i == 4 then
        call DestroyEffect( AddSpecialEffectTarget( "Abilities\\Weapons\\LavaSpawnMissile\\LavaSpawnMissile.mdl", GetEnumUnit( ), "left foot" ) )
    else
        call DestroyEffect( AddSpecialEffectTarget( "Abilities\\Weapons\\LavaSpawnMissile\\LavaSpawnMissile.mdl", GetEnumUnit( ), "right foot" ) )
    endif
endfunction

private function SpawnEffects takes nothing returns nothing
    local SpellS A = LoadInteger( H, GetHandleId( GetExpiredTimer( ) ), 0 )
    local SpellS B = SpellS.create( )
    local real a = GetRandomReal( -bj_PI, bj_PI )
    local integer i
    
    call ForGroup( A.g, function AddHitEffect )
    
    set B.t = CreateTimer( )
    
    set B.i = 0
    set B.l = vector.create( A.l.x + GetRandomReal( A.radius * 0.80, A.radius ) * Cos( a ), A.l.y + GetRandomReal( A.radius * 0.80, A.radius ) * Sin( a ), A.l.z + GetRandomReal( -900.00, 0.00 ) )
    set a = a + bj_PI + GetRandomReal( -bj_PI, bj_PI ) * 0.25
    set B.v = vector.create( A.l.x + GetRandomReal( A.radius * 0.80, A.radius ) * Cos( a ), A.l.y + GetRandomReal( A.radius * 0.80, A.radius ) * Sin( a ), 0.00 )
    set B.v.z = GetAxisZ( B.v.x, B.v.y ) + B.l.z + GetRandomReal( -400.00, 100.00 )
    set B.v.x = B.v.x - B.l.x
    set B.v.y = B.v.y - B.l.y
    set B.v.z = B.v.z - B.l.z
    
    set B.e = AddSpecialEffect( "Abilities\\Spells\\Orc\\MirrorImage\\MirrorImageCaster.mdl", B.l.x, B.l.y )
    call SetSpecialEffectZ( B.e, B.l.z )
    call SetSpecialEffectOrientation( B.e, Atan2( B.v.y, B.v.x ) * bj_RADTODEG, Atan2( B.v.z, SquareRoot( B.v.x * B.v.x + B.v.y * B.v.y ) ) * bj_RADTODEG, 0.00 )
    call SetSpecialEffectTimeScale( B.e, 2.00 )
    call DestroyEffect( B.e )
    
    set B.e = AddSpecialEffect( "Abilities\\Weapons\\PhoenixMissile\\Phoenix_Missile_mini.mdl", B.l.x, B.l.y )
    call SetSpecialEffectZ( B.e, B.l.z )
    call SetSpecialEffectOrientation( B.e, Atan2( B.v.y, B.v.x ) * bj_RADTODEG, Atan2( B.v.z, SquareRoot( B.v.x * B.v.x + B.v.y * B.v.y ) ) * bj_RADTODEG, 0.00 )
    call SetSpecialEffectAnimation( B.e, "stand" )
    call SetSpecialEffectScale( B.e, 0.50 )
    
    set B.distance = B.v.length( )
    call B.v.normalize( )
    
    set B.speed = B.distance / 0.15 * 0.01
    
    call SaveInteger( H, GetHandleId( B.t ), 0, B )
    call TimerStart( B.t, 0.01, true, function Move )
    
    set A.time = A.time - 0.05
    
    if A.time <= 0.00 then
        call SetUnitFlyHeight( A.caster, 0.00, 0.00 )
        call ShowUnit( A.caster, true )
        call SetUnitAnimation( A.caster, "stand ready" )
        call QueueUnitAnimationByIndex( A.caster, 3 )
        call QueueUnitAnimation( A.caster, "stand" )
        
        set i = 6
    
        loop
            set B = SpellS.create( )
            set B.t = CreateTimer( )
            
            set B.i = 0
            set B.l = vector.create( A.l.x + A.radius * Cos( a ), A.l.y + A.radius * Sin( a ), A.l.z )
            set B.v = vector.create( A.l.x, A.l.y, 0.00 )
            set B.v.z = GetAxisZ( B.v.x, B.v.y ) + 100.00
            set B.v.x = B.v.x - B.l.x
            set B.v.y = B.v.y - B.l.y
            set B.v.z = B.v.z - B.l.z
            
            set B.e = AddSpecialEffect( "Abilities\\Spells\\Orc\\MirrorImage\\MirrorImageCaster.mdl", B.l.x, B.l.y )
            call SetSpecialEffectZ( B.e, B.l.z )
            call SetSpecialEffectOrientation( B.e, Atan2( B.v.y, B.v.x ) * bj_RADTODEG, Atan2( B.v.z, SquareRoot( B.v.x * B.v.x + B.v.y * B.v.y ) ) * bj_RADTODEG, 0.00 )
            call SetSpecialEffectTimeScale( B.e, 2.00 )
            call DestroyEffect( B.e )
            
            set B.e = AddSpecialEffect( "Abilities\\Weapons\\PhoenixMissile\\Phoenix_Missile_mini.mdl", B.l.x, B.l.y )
            call SetSpecialEffectZ( B.e, B.l.z )
            call SetSpecialEffectOrientation( B.e, Atan2( B.v.y, B.v.x ) * bj_RADTODEG, Atan2( B.v.z, SquareRoot( B.v.x * B.v.x + B.v.y * B.v.y ) ) * bj_RADTODEG, 0.00 )
            call SetSpecialEffectAnimation( B.e, "stand" )
            call SetSpecialEffectScale( B.e, 0.50 )
            
            set B.distance = B.v.length( )
            call B.v.normalize( )
            
            set B.speed = B.distance / 0.20 * 0.01
            
            call SaveInteger( H, GetHandleId( B.t ), 0, B )
            call TimerStart( B.t, 0.01, true, function Move )
            
            set i = i - 1
            exitwhen i <= 0
            set a = a - bj_PI / 6.00 * 2.00
        endloop
        
        call DestroyEffect( A.e )
        
        set A.e = AddSpecialEffect( "Abilities\\Spells\\Orc\\MirrorImage\\MirrorImageCaster.mdl", A.l.x, A.l.y )
        call SetSpecialEffectYaw( A.e, GetUnitFacing( A.caster ) )
        call DestroyEffect( A.e )
        
        set A.e = AddSpecialEffectTarget( "Abilities\\Weapons\\PhoenixMissile\\Phoenix_Missile.mdl", A.caster, "weapon" )
        
        if GetLocalPlayer( ) == A.p then
            call ClearSelection( )
            call SelectUnit( A.caster, true )
        endif
        
        call TimerStart( A.t, 2.10, false, function Damage )
    endif
endfunction

private function JumpClones takes nothing returns nothing
    local SpellS A = LoadInteger( H, GetHandleId( GetExpiredTimer( ) ), 0 )
    local SpellS B
    local integer i = 6
    local real a = -bj_PI
    local unit u
    
    call GroupEnumUnitsInRange( TempGroup, A.l.x, A.l.y, A.radius, null )
    
    loop
        set u = FirstOfGroup( TempGroup )
        exitwhen u == null
        call GroupRemoveUnit( TempGroup, u )
        
        if IsUnitInRangeXY( u, A.l.x, A.l.y, A.radius + UNIT_MAX_COLLISION ) then
            if UnitAlive( u ) and IsUnitEnemy( u, A.p ) then
                call GroupAddUnit( A.g, u )
                call SetUnitStunned( u, true )
                call SetUnitTimeScale( u, 0.00 )
            endif
        endif
    endloop
    
    call PauseUnit( A.caster, true )
    call ShowUnit( A.caster, false )
    
    set A.l.z = GetAxisZ( A.l.x, A.l.y ) + GetUnitFlyHeight( A.caster )
    
    set A.e = AddSpecialEffect( "Abilities\\Spells\\Orc\\MirrorImage\\MirrorImageCaster.mdl", A.l.x, A.l.y )
    call SetSpecialEffectZ( A.e, A.l.z )
    call SetSpecialEffectYaw( A.e, GetUnitFacing( A.caster ) )
    call DestroyEffect( A.e )
    
    set A.e = AddSpecialEffect( "Abilities\\Spells\\Orc\\Bloodlust\\BloodlustTarget.mdl", A.l.x, A.l.y )
    call SetSpecialEffectZ( A.e, A.l.z / 2.00 )
    call SetSpecialEffectTimeScale( A.e, 0.10 )
    call SetSpecialEffectScale( A.e, 50.00 )
    call SetSpecialEffectAlpha( A.e, 175 )
    
    loop
        set B = SpellS.create( )
        
        set B.t = CreateTimer( )
        
        set B.l = vector.create( A.l.x, A.l.y, A.l.z )
        set B.v = vector.create( Cos( a ), Sin( a ), Cos( bj_PI * 0.50 ) )
        
        set B.i = 1
        set B.speed = 40.00
        set B.distance = A.radius
        
        set B.e = AddSpecialEffect( "Abilities\\Spells\\Orc\\MirrorImage\\MirrorImageMissile.mdl", B.l.x, B.l.y )
        call SetSpecialEffectZ( B.e, B.l.z )
        call SetSpecialEffectOrientation( B.e, a * bj_RADTODEG, 45.00, 0.00 )
        
        call SaveInteger( H, GetHandleId( B.t ), 0, B )
        call TimerStart( B.t, 0.01, true, function Move )
        
        set i = i - 1
        exitwhen i <= 0
        set a = a - bj_PI / 5.00
    endloop
    
    set A.radius = A.radius * 1.50
    set A.time = 2.00
    call TimerStart( A.t, 0.05, true, function SpawnEffects )
endfunction

private function Jump takes nothing returns nothing
    local SpellS A = LoadInteger( H, GetHandleId( GetExpiredTimer( ) ), 0 )
    
    if UnitAddAbility( A.caster, 'Arav' ) then
        call UnitRemoveAbility( A.caster, 'Arav' )
    endif
    
    call SetUnitFlyHeight( A.caster, 800.00, 800.00 / 0.20 )
    
    call DestroyEffect( A.e )
    
    set A.e = AddSpecialEffect( "Units\\NightElf\\Wisp\\WispExplode.mdl", A.l.x, A.l.y )
    call SetSpecialEffectAnimationOffsetPercent( A.e, 0.20 )
    call SetSpecialEffectTimeScale( A.e, 3.00 )
    call DestroyEffect( A.e )
    
    call TimerStart( A.t, 0.20, false, function JumpClones )
endfunction

private function Spell_Actions takes nothing returns nothing
    local SpellS A = SpellS.create( )
    local integer i
    local real a = GetRandomReal( -bj_PI, bj_PI )
    
    set A.t = CreateTimer( )
    set A.caster = GetTriggerUnit( )
    set A.p = GetOwningPlayer( A.caster )
    set A.l = vector.create( GetUnitX( A.caster ), GetUnitY( A.caster ), 0.00 )
    set A.g = CreateGroup( )
    set A.e = AddSpecialEffect( "Abilities\\Spells\\Undead\\DarkRitual\\DarkRitualTarget.mdl", A.l.x, A.l.y )
    call SetSpecialEffectScale( A.e, 2.00 )
    
    set A.damage = 200.00 // урон
    set A.radius = 600.00 // радиус
    set A.attackType = ATTACK_TYPE_CHAOS // тип атаки
    set A.damageType = DAMAGE_TYPE_SONIC // тип урона
    set A.weaponType = null
    
    set A.effectList = HandleListCreate( )
    
    set A.i = 60 // количество эффектов отображения радиуса
    set i = A.i
    
    loop
        set bj_lastCreatedEffect = AddSpecialEffect( "Abilities\\Spells\\Orc\\Bloodlust\\BloodlustTarget.mdl", A.l.x + A.radius * Cos( a ), A.l.y + A.radius * Sin( a ) )
        call SetSpecialEffectZ( bj_lastCreatedEffect, GetSpecialEffectZ( bj_lastCreatedEffect ) + 50.00 )
        call HandleListAddHandle( A.effectList, bj_lastCreatedEffect )
        
        set i = i - 1
        exitwhen i <= 0
        set a = a + bj_PI / A.i * 2.00
    endloop
    
    call SaveInteger( H, GetHandleId( A.t ), 0, A )
    call TimerStart( A.t, 1.50, false, function Jump )
endfunction

//===========================================================================
private function Spell_Conditions takes nothing returns boolean
    return GetSpellAbilityId() == 'A000'
endfunction

function InitTrig_Spell takes nothing returns nothing
    set gg_trg_Spell = CreateTrigger(  )
    call TriggerRegisterAnyUnitEventBJ( gg_trg_Spell, EVENT_PLAYER_UNIT_SPELL_EFFECT )
    call TriggerAddCondition( gg_trg_Spell, Condition( function Spell_Conditions ) )
    call TriggerAddAction( gg_trg_Spell, function Spell_Actions )
endfunction
endlibrary

Загруженные файлы
28
UndeadFisher, странно, только сейчас заметил на видосе, что при втором касте не заспавнились эффекты, но я не первый раз встречаю такую проблему, возможно дело в компе либо в самом варе, он не отображает порой эффекты, я из-за этой проблемы даже к даммикам возвращался когда-то, с ними всегда всё корректно было
1
rsfghd, Да, встроенные функции спецэффектов имеют свои проблемы, которые остаются нерешёнными. "Фальшивые" юниты не устарели и по-прежнему остаются актуальными.
28
UndeadFisher, мне кажется дело не в самих функциях, эффекты то создаются, но не отображаются
Показан только небольшой набор комментариев вокруг указанного. Перейти к актуальным.
Чтобы оставить комментарий, пожалуйста, войдите на сайт.