Добавлен , опубликован
Существует специальная тема Способности и алгоритмы на заказ, где любой желающий может помочь с вашими фантазиями и где я тоже иногда зависаю. Кроме того, есть платные заказы, например, можете обратиться к 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
`
ОЖИДАНИЕ РЕКЛАМЫ...

Показан только небольшой набор комментариев вокруг указанного. Перейти к актуальным.
34
Заказ на работу

Заказ

Название: Боевая тревога
Метод: GUI
Версия Warcraft III: 1.26
Техническое описание: Надо сделать чтобы логово орков принимало не только рабов но и бугаёв и троллей. И скорость атака чтобы росла у логова при большем кол-ве юнитов.
Ответы (2)
28
Выполнение заказа

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

инструкция по импорту
скопировать триггер Melee Initialization и вставить в свою карту
выдать всем юнитам, которых можно погрузить в бункер, абилку пустышку и указать её в триггерах
в остальном просто скопировать нестандартное в редакторе объектов и закинуть в свою карту
Загруженные файлы
11
Заказ на работу
Название: Песня доблести
Метод: GUI
Версия Warcraft III: 1.26
Техническое описание: Способность можно активировать и деактивировать по желанию, но чтобы была перезарядка после деактивации.
Активирующий "поёт" находится анимации channel и неподвижен, пока не перестанет петь.
При активации, все кто слышит получают следующие эффекты и затем каждые 3 секунды :
-Союзники получают шанс крит. урона 150/200/250% на 15/25/35%, затем каждые 3 секунды восполняют ману на 3/5/9% и здоровье на 1/2/3х интеллекта героя,
-Противники получают штраф промахов 10/15/25%, затем каждые 3 секунды они оглушены на 0.5/1/1.5 секунд. (герои оглушены на 0.5 всегда)
После деактивации, герой отбрасывает врагов рядом и если он пел минимум 9 секунд, то получает бонус к урону 10/20/30.
Название: Воронка смерти
Метод: GUI
Версия Warcraft III: 1.26
Техническое описание: Способность активируется и деактивируется без перезарядки, как огненный плащ иллидана.
При активации постоянно тратит ману, но взамен, все находящиеся рядом лежащие трупы юнитов поглощаются героем и восполняют ему здоровье и ману, на 5%. Это те вида трупы, которые можно было каннибализировать. При этом можно сделать какой нибудь снаряд летящий из трупа в героя типа его частица поглощается в него, а после взорвать труп, чтобы нельзя было повторно его поглотить.
Ответы (16)
28
Shermanator00, какой радиус песни доблести? Баффы/дебаффы (Крит/промах) утрачиваются при окончании песни (или выхода из её радиуса)? Если да, то мгновенно или через 3 секунды? Если герой пел дольше 9 секунд, он получает бонус к урону навсегда? Он стакается или обновляется? Возможен ли вариант написания абилок на джассе/вджассе?
11
rsfghd, радиус 1200, баффы дебаффы утрачиваются через 3 секунды, бонус героя временный скажем 30 секунд и не стакается. Можно на Джассе если на GUI закоплексовано
28
Выполнение заказа

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

Песня доблести

инструкция по импорту
скопировать папку Initialization и вставить в свою карту, копировать элементы из редактора объектов и вставлять в свою карту
делал на гуи с использованием кастомскриптов для выбора юнитов и удаления точек, в целях оптимизации можешь изменить периодичность таймера TimerMove и его связывающих с 0.01 до 0.03. Таймер Timer и его связывающие с 0.01 до 0.10
Спелл муи
второй спелл завтра сделаю, если с этим всё оке
Загруженные файлы
28
Shermanator00, а, и не забудь сделать прелоад абилок из ро, чтобы первый каст не подлагивал
11
rsfghd, ух ты, спасибо. Готовлю реворк модели бардессы, потом добавлю чтоб проигрывал анимацию Spell slam, где сделан конец заклинания) Да и для какого-нибудь отважного лидера подойдет типа командира-запугивателя
28
Выполнение заказа

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

Воронка смерти

инструкция по импорту
скопировать папку Initialization и вставить в свою карту, копировать элементы из редактора объектов и вставлять в свою карту
делал на гуи с использованием кастомскриптов для выбора юнитов и удаления точек, в целях оптимизации можешь изменить периодичность таймера TempTimer с 0.01 до 0.10. Таймер TempTimerMove с 0.01 до 0.03, и полностью убрать дополнительного даммика (тёмный хвостик фиолетовой птицы Dummy1)
Спелл муи
Загруженные файлы
11
rsfghd, круто!
я уверен немало кому пригодится такой спелл, снаряд птички наконец - то где то прикольно смотрится
28
Shermanator00, птички везде прикольно смотрятся если знать как их юзать, к примеру, демонстрация Частицы/Particles от Vlod'a
11
Заказ на работу
rsfghd,
Название: Dodge
Метод: GUI
Версия Warcraft III: 1.26
Техническое описание: есть еще идея, www.hiveworkshop.com/threads/knightess-in-plate-armor.352884
я сделал эту модель, и там есть анимация, которая как в дарк соулсе перекат Spell Throw Alternate и уворот spell throw gold. Надо три варианта спеллов:
Первый вариант: расстояние до 400, проиграв анимацию герой быстро переместился перекатом на точку, которую указал игрок и получает сопротивление урону заклинаниям 100% и защиту 1000 на 2 секунд, а затем на 5 секунд получает скорость бега от свитка скорости 25%\50%\75% (необязательно для визуальности можешь в редакторе в разделе "графика" скорости бега поставить 350, а ходьбы 300 так как там walk fast есть).
Второй вариант: шанс 15\20\25% будучи атакованным, герой рандомно переместился вправо ЛИБО (рандомно) влево (влево пока не анимировал еще) и следующий удар будет критическим 150%\200%\250%. Анимация уворота длится 1.2 секунд. Надо чтобы после уклона герой авто-атаку сделал обычную, может быть такое что после уклона анимация атаки не сыграет вроде.
Третий вариант: это для другого персонажа, пусть временным тестером будет Мэв, при нажатии герой высоко отскакивает в противоположную сторону куда она смотрит (назад т.е.) анимацией Spell Slam (вроде), а зона, где она изначально была взрывается через 0.5 сек и наносит 100\200\300 урона в радиусе взрыва, скажем 600
Я думаю что уклон влево\вправо анимация очень медленная, я б хотел посмотреть как оно работает против группы противников) Поэтому добавлю измененный файл снизу. Там Spell throw Gold 0.6 секунд длится вместо 1.2
И еще чтобы эти абилки работали на всех, кто ее может изучить 😀
Загруженные файлы
28
Shermanator00, как долго длится усиление крита во втором варианте после уворота? Пока не будет нанесена автоатака? На ванилке, заставить сделать автоатаку можно только приказом, а значит, её можно будет отменить. После уворота атаковать ближнюю цель или того, кто атаковал?
28
Shermanator00, и заказы, пожалуйста, отдельным комментарием, а не в ветке ответов, потому что другие не увидят этот заказ, если не полезут сюда в ответы
15
rsfghd, выглядит здорово. Кстати, напоминает неуязвимость близзов (ну в частности, из-за эффекта, который ты использовал конечно), уж лучше бы они так сделали, чтобы хп постоянно восстанавливалось сильно, чем просто тупую неуязвимость, когда нельзя атаковать даже противника, что на мой взгляд попросту ломает игру, когда оппонент вынужден убегать или пытаться любой ценой застанить или убить кастующего.
28
Meddin, ломает игру потка неуязвимости, которая делает channel ульты имбовыми
11
rsfghd, да, пока не будет нанесена автоатака, и пусть атакует того кто прокнул
2
Заказ на работу
Я как понимаю нужны оригинальные идеи для спелов!
У меня есть идея: герой стреляет лучом лазера в определенную цель, длится 6/7/8 сек. В это время герой ничего не может делать, а только поворачивается ко врагу передом (из живота или типа того лазер постоянно стреляет). И все вражеские юниты, на которых попал лазер - им постоянно наносится урон и они замедляются (как и цель, если её достаёт лазер). Также если цель будет убегать, то герой разворачивается к ней постоянно и атакует лазером (и наносит урон всем, кого лазер докоснулся). Дальность 900. Если цель убежит или героя потревожат - спелл закончится!
С лвлом повышается урон, замедление передвижения и длительность.
Ответы (12)
28
Выполнение заказа

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

инструкция по импорту
скопировать папку Initialization и вставить в свою карту
перекопировать редактор объектов и вставить в свою карту
настроить равкоды (кроме BTLF) в триггере Spell в соответствии с редактором
всё остальное, что нужно/можно отредактировать помечено комментариями, на остальное нужны базовые знания джасса

Код

AllGlobals
library AllGlobalsLib
globals
    constant hashtable H = InitHashtable( )
    constant location LFZ = Location( 0.00, 0.00 )
    
    private real MaxX
    private real MinX
    private real MaxY
    private real MinY
endglobals

native UnitAlive takes unit id returns boolean

function GetCorX takes real x returns real
    if x > MaxX then
        return MaxX
    elseif x < MinX then
        return MinX
    endif
    
    return x
endfunction

function GetCorY takes real y returns real
    if y > MaxY then
        return MaxY
    elseif y < MinY then
        return MinY
    endif
    
    return y
endfunction

function GetLocZ takes real x, real y returns real
    call MoveLocation( LFZ, x, y )
    return GetLocationZ( LFZ )
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 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 constant group TempGroup1 = CreateGroup( )
    private unit TempUnit = null
endglobals

struct SpellS
    timer t
    player p
    
    unit caster
    unit target
    unit eye
    unit field
    unit laser
    unit laserBig
    
    vector l
    vector array v[4]
    
    integer lvl
    
    real radius
    real radiusEnd
    
    real damage
    real damagePeriodic
    
    real distance
    
    real time
    real timeMax
    
    attacktype attackType
    damagetype damageType
    weapontype weaponType
endstruct

private function Rotation takes nothing returns nothing
    local SpellS A = LoadInteger( H, GetHandleId( GetExpiredTimer( ) ), 0 )
    local real ax
    local real ay
    local real d
    local unit u
    
    if GetUnitCurrentOrder( A.caster ) == OrderId( "channel" ) then
        set A.time = A.time + 0.01
        set A.timeMax = A.timeMax + 0.01
        
        call SetUnitFacing( A.caster, Atan2( GetUnitY( A.target ) - A.l.y, GetUnitX( A.target ) - A.l.x ) * bj_RADTODEG )
        
        set d = GetUnitFacing( A.caster )
        
        set ax = Cos( d * bj_DEGTORAD )
        set ay = Sin( d * bj_DEGTORAD )
        
        call SetUnitX( A.eye, A.l.x + 275.00 * ax )
        call SetUnitY( A.eye, A.l.y + 275.00 * ay )
        
        call SetUnitX( A.field, A.l.x + 125.00 * ax )
        call SetUnitY( A.field, A.l.y + 125.00 * ay )
        
        call SetUnitFacing( A.eye, d )
        call SetUnitFacing( A.laser, d )
        call SetUnitFacing( A.laserBig, d )
        
        if A.time == 1.15 then
            set A.laser = CreateUnit( A.p, 'u005', A.l.x + 100.00 * ax, A.l.y + 100.00 * ay, d )
            call SetUnitX( A.laser, A.l.x + 100.00 * ax )
            call SetUnitY( A.laser, A.l.y + 100.00 * ay )
            call SetUnitFlyHeight( A.laser, 80.00, 0.00 )
            call UnitApplyTimedLife( A.laser, 'BTLF', 3.00 )
        endif
        
        if A.time >= 1.50 then
            set A.time = 0.00
            
            call SetUnitAnimation( A.field, "birth" )
            call QueueUnitAnimation( A.field, "stand" )
            
            set A.laser = CreateUnit( A.p, 'u007', A.l.x, A.l.y, d )
            call SetUnitFlyHeight( A.laser, 80.00, 0.00 )
            call SetUnitAnimation( A.laser, "death" )
            call UnitApplyTimedLife( A.laser, 'BTLF', 5.00 )
            
            set A.laser = CreateUnit( A.p, 'u001', A.l.x + 125.00 * ax, A.l.y + 125.00 * ay, d )
            call SetUnitX( A.laser, A.l.x + 125.00 * ax )
            call SetUnitY( A.laser, A.l.y + 125.00 * ay )
            call SetUnitFlyHeight( A.laser, 80.00, 0.00 )
            call UnitApplyTimedLife( A.laser, 'BTLF', 3.00 )
        endif
        
        if A.timeMax >= A.damagePeriodic then
            set A.timeMax = 0.00
            
            set d = 0.00
            
            loop
                call GroupEnumUnitsInRange( TempGroup, A.l.x + d * ax, A.l.y + d * ay, A.radius - ( A.radius - A.radiusEnd ) * ( d / A.distance ) + 200.00, null )
                
                loop
                    set u = FirstOfGroup( TempGroup )
                    exitwhen u == null
                    call GroupRemoveUnit( TempGroup, u )
                    
                    if not IsUnitInGroup( u, TempGroup1 ) then
                        if UnitAlive( u ) and IsUnitEnemy( u, A.p ) then // условия для нанесения урона
                            if IsUnitInRangeXY( u, A.l.x + d * ax, A.l.y + d * ay, A.radius - ( A.radius - A.radiusEnd ) * ( d / A.distance ) ) then
                                call SetUnitAbilityLevel( TempUnit, 'A001', A.lvl )
                                call IssueTargetOrder( TempUnit, "slow", u )
                                
                                call DestroyEffect( AddSpecialEffectTarget( "Abilities\\Spells\\Undead\\CarrionSwarm\\CarrionSwarmDamage.mdl", u, "origin" ) )
                                call UnitDamageTarget( A.caster, u, A.damage, false, false, A.attackType, A.damageType, A.weaponType )
                                call GroupAddUnit( TempGroup1, u )
                            endif
                        endif
                    endif
                endloop
                
                if d + 32.00 > A.distance then
                    set d = A.distance
                else
                    set d = d + 32.00
                endif
                
                exitwhen d >= A.distance
            endloop
            
            call GroupClear( TempGroup1 )
        endif
    else
        call PauseTimer( A.t )
        call FlushChildHashtable( H, GetHandleId( A.t ) )
        call DestroyTimer( A.t )
        
        call SetUnitAnimation( A.eye, "death" )
        call UnitApplyTimedLife( A.eye, 'BTLF', 3.00 )
        
        call SetUnitAnimation( A.field, "death" )
        call UnitApplyTimedLife( A.field, 'BTLF', 5.00 )
        
        call SetUnitAnimation( A.laserBig, "death" )
        call UnitApplyTimedLife( A.laserBig, 'BTLF', 6.00 )
        
        set A.t = null
        set A.eye = null
        set A.field = null
        set A.laser = null
        set A.laserBig = null
        set A.caster = null
        set A.target = null
        call A.l.destroy( )
        call A.destroy( )
    endif
endfunction

private function CreateEye takes nothing returns nothing
    local SpellS A = LoadInteger( H, GetHandleId( GetExpiredTimer( ) ), 0 )
    local SpellS B = LoadInteger( H, GetHandleId( GetExpiredTimer( ) ), 1 )
    local integer k = 0
    local integer i
    local real array x
    local real array y
    local real array z
    local real array x1
    local real array y1
    local real array z1
    local unit u
    
    set A.time = A.time + 0.01 / A.timeMax
    
    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 x1[k] = B.v[k].x
        set y1[k] = B.v[k].y
        set z1[k] = B.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 x1[i] = ( 1.00 - A.time ) * x1[i] + A.time * x1[i + 1]
            set y1[i] = ( 1.00 - A.time ) * y1[i] + A.time * y1[i + 1]
            set z1[i] = ( 1.00 - A.time ) * z1[i] + A.time * z1[i + 1]
            
            set i = i + 1
            exitwhen i > 4 - k
        endloop
        
        set k = k + 1
        exitwhen k >= 4 - 1
    endloop
    
    set x[0] = GetCorX( x[0] )
    set y[0] = GetCorY( y[0] )
    
    call SetUnitX( A.eye, x[0] )
    call SetUnitY( A.eye, y[0] )
    call SetUnitFlyHeight( A.eye, z[0] - GetLocZ( x[0], y[0] ), 0.00 )
    
    set x1[0] = GetCorX( x1[0] )
    set y1[0] = GetCorY( y1[0] )
    
    call SetUnitX( B.eye, x1[0] )
    call SetUnitY( B.eye, y1[0] )
    call SetUnitFlyHeight( B.eye, z1[0] - GetLocZ( x1[0], y1[0] ), 0.00 )
    
    if A.time >= 1.00 then
        call PauseTimer( A.t )
        
        call KillUnit( A.eye )
        call KillUnit( B.eye )
        
        set A.v[3].z = GetUnitFacing( A.caster )
        
        set A.eye = CreateUnit( A.p, 'u003', A.v[3].x, A.v[3].y, A.v[3].z )
        call UnitAddAbility( A.eye, 'Arav' )
        call SetUnitX( A.eye, A.v[3].x )
        call SetUnitY( A.eye, A.v[3].y )
        call SetUnitFlyHeight( A.eye, 80.00, 0.00 )
        call KillUnit( A.eye )
        
        set A.eye = CreateUnit( A.p, 'u004', A.v[3].x, A.v[3].y, A.v[3].z )
        call UnitAddAbility( A.eye, 'Arav' )
        call SetUnitX( A.eye, A.v[3].x )
        call SetUnitY( A.eye, A.v[3].y )
        call SetUnitFlyHeight( A.eye, 80.00, 0.00 )
        call KillUnit( A.eye )
        
        set A.field = CreateUnit( A.p, 'u006', A.v[3].x, A.v[3].y, A.v[3].z )
        call SetUnitX( A.field, A.v[3].x )
        call SetUnitY( A.field, A.v[3].y )
        call SetUnitAnimation( A.field, "birth" )
        call QueueUnitAnimation( A.field, "stand" )
            
        set A.laserBig = CreateUnit( A.p, 'u007', A.l.x, A.l.y, A.v[3].z )
        call SetUnitX( A.laserBig, A.l.x )
        call SetUnitY( A.laserBig, A.l.y )
        call SetUnitFlyHeight( A.laserBig, 80.00, 0.00 )
        call SetUnitAnimation( A.laserBig, "birth" )
        call QueueUnitAnimation( A.laserBig, "stand" )
        
        set A.v[3].x = A.v[3].x + 150.00 * Cos( A.v[3].z * bj_DEGTORAD )
        set A.v[3].y = A.v[3].y + 150.00 * Sin( A.v[3].z * bj_DEGTORAD )
        
        set A.eye = CreateUnit( A.p, 'u000', A.v[3].x, A.v[3].y, A.v[3].z )
        call SetUnitX( A.eye, A.v[3].x )
        call SetUnitY( A.eye, A.v[3].y )
        call SetUnitFlyHeight( A.eye, 80.00, 0.00 )
        call SetUnitAnimation( A.eye, "birth" )
        call QueueUnitAnimation( A.eye, "stand" )
        
        set i = 0
        loop
            call A.v[i].destroy( )
            call B.v[i].destroy( )
            
            set i = i + 1
            exitwhen i >= 4
        endloop
        
        call B.destroy( )
        
        set A.time = 1.50
        
        call TimerStart( A.t, 0.01, true, function Rotation )
    endif
endfunction

function Spell_Actions takes nothing returns nothing
    local SpellS A = SpellS.create( )
    local SpellS B = SpellS.create( )
    local real a
    
    set A.t = CreateTimer( )
    
    set A.caster = GetTriggerUnit( )
    set A.target = GetSpellTargetUnit( )
    
    set A.p = GetOwningPlayer( A.caster )
    
    set A.l = vector.create( GetUnitX( A.caster ), GetUnitY( A.caster ), 0.00 )
    
    set A.lvl = GetUnitAbilityLevel( A.caster, GetSpellAbilityId( ) )
    
    if A.lvl == 1 then // уровень абилки
        set A.damage = 10.00 // урон
    elseif A.lvl == 2 then
        set A.damage = 25.00
    else
        set A.damage = 40.00
    endif
    
    set A.damagePeriodic = 0.30 // периодичность урона
    
    set A.distance = 900.00 // дистанция
    
    set A.radius = 200.00 // начальный радиус
    set A.radiusEnd = 50.00 // конечный радиус
    
    set A.attackType = null // тип атаки
    set A.damageType = null // тип урона
    set A.weaponType = null // тип оружия (звук)
    
    set A.time = 0.00
    set A.timeMax = 0.80
    
    set A.v[0] = vector.create( A.l.x, A.l.y, 0.00 )
    set A.v[0].z = GetLocZ( A.l.x, A.l.y ) + GetUnitFlyHeight( A.caster ) + 50.00
    
    set a = Atan2( GetUnitY( A.target ) - A.l.y, GetUnitX( A.target ) - A.l.x )
    
    set A.v[1] = vector.create( A.v[0].x - 500.00 * Cos( a - bj_PI * 0.15 ), A.v[0].y - 500.00 * Sin( a - bj_PI * 0.15 ), A.v[0].z + 200.00 )
    set A.v[2] = vector.create( A.v[0].x - 100.00 * Cos( a - bj_PI * 0.15 ), A.v[0].y - 100.00 * Sin( a - bj_PI * 0.15 ), A.v[0].z + 200.00 )
    set A.v[3] = vector.create( A.v[0].x + 125.00 * Cos( a ), A.v[0].y + 125.00 * Sin( a ), 0.00 )
    set A.v[3].z = GetLocZ( A.v[3].x, A.v[3].y ) + 75.00
    
    set A.eye = CreateUnit( A.p, 'u002', A.v[0].x, A.v[0].y, a * bj_RADTODEG )
    call UnitAddAbility( A.eye, 'Arav' )
    call SetUnitX( A.eye, A.v[0].x )
    call SetUnitY( A.eye, A.v[0].y )
    call SetUnitFlyHeight( A.eye, 50.00, 0.00 )
    call SetUnitAnimation( A.eye, "birth" )
    call QueueUnitAnimation( A.eye, "stand" )
    
    set B.v[0] = vector.create( A.l.x, A.l.y, A.l.z )
    set B.v[1] = vector.create( B.v[0].x - 500.00 * Cos( a + bj_PI * 0.15 ), B.v[0].y - 500.00 * Sin( a + bj_PI * 0.15 ), A.v[1].z )
    set B.v[2] = vector.create( B.v[0].x - 100.00 * Cos( a + bj_PI * 0.15 ), B.v[0].y - 100.00 * Sin( a + bj_PI * 0.15 ), A.v[2].z )
    set B.v[3] = vector.create( A.v[3].x, A.v[3].y, A.v[3].z )
    
    set B.eye = CreateUnit( A.p, 'u002', B.v[0].x, B.v[0].y, a * bj_RADTODEG )
    call SetUnitX( B.eye, B.v[0].x )
    call SetUnitY( B.eye, B.v[0].y )
    call UnitAddAbility( B.eye, 'Arav' )
    call SetUnitFlyHeight( B.eye, 50.00, 0.00 )
    call SetUnitAnimation( B.eye, "birth" )
    call QueueUnitAnimation( B.eye, "stand" )
    
    call SaveInteger( H, GetHandleId( A.t ), 0, A )
    call SaveInteger( H, GetHandleId( A.t ), 1, B )
    call TimerStart( A.t, 0.01, true, function CreateEye )
endfunction

//===========================================================================

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 TempUnit = CreateUnit( Player( PLAYER_NEUTRAL_PASSIVE ), 'u008', 0.00, 0.00, 0.00 )
endfunction
endlibrary

Загруженные файлы
28
ShadowNinja, идея не самая оригинальная, в морозко делал уже подобное для босса, но пока делал именно этот заказ, появилась идея чтобы око саргараса спавнить над головой кастера и создавать такой же луч, который будет учитывать сферические координаты и направлен под наклоном в землю соответственно, клик правой кнопкой мыши позволит перенаправить такой луч на новую точку, но чтобы такое сделать нужен мемхак/южапи, поскольку требуется динамическое управление ориентацией модели, можно и на ванилке через кость и SetUnitLookAt, но не хочу этими костылями мазаться, тем более вне заказа
31
Я как понимаю нужны оригинальные идеи для спелов!
И что в луче лазаря уникального?
2
rsfghd, есть типа такого спелла на Хайве, но только луч за мышкой следует (за курсором)
Однако... В мультиплеере из-за этого спела у половины игроков карта вылетает
28
ShadowNinja, координаты мышки можно отловить только на мемхаке/южапи, во втором случае оно даже сразу засинханным будет, на ванилке разве что с помощью пкм управлять направлением луча
31
rsfghd, далана. На ваниле мышь ловили спамом трекаблов, а на рефе спамом фреймов.
28
nazarpunk, такими жуткими костылями я не хочу развлекаться, в особенности если это какая-то 480х480 карта
2
rsfghd, кстати говоря, можно ещё сделать этот луч не по юниту, а просто в определённую область! (думаю кому-то это будет полезно)
Можно даже сделать так: что бы этот луч влево и вправо поворачивался, вернее сам герой сам автоматически его поворачивал во время использования этой способности (в лево, потом в право и так далее до конца способности)
Так можно больше вражеских юнитов задеть
28
ShadowNinja, а я о чём говорю, когда предлагаю через пкм сделать луч. Кликнул во время каста и юнит повернулся в точку, куда кликнул, если кликнул на юнита, то кастер будет всё время поворачиваться на него, пока в другое место не кликнешь. Единственная проблема это невозможность отменить каст спелла движением. Но можно отменить, например, нажав на S
28
ShadowNinja, в принципе, отменить приказ движением всё же можно, но не через smart, а move
11
Заказ на работу
Дублирую сообщение, чтобы было видно всем:
"Название: Dodge
Метод: GUI
Версия Warcraft III: 1.26
Техническое описание: есть еще идея, www.hiveworkshop.com/threads/knightess-in-plate-armor.352884
я сделал эту модель, и там есть анимация, которая как в дарк соулсе перекат Spell Throw Alternate и уворот spell throw gold. Надо три варианта спеллов:
Первый вариант: расстояние до 400, проиграв анимацию герой быстро переместился перекатом на точку, которую указал игрок и получает сопротивление урону заклинаниям 100% и защиту 1000 на 2 секунд, а затем на 5 секунд получает скорость бега от свитка скорости 25%\50%\75% (необязательно для визуальности можешь в редакторе в разделе "графика" скорости бега поставить 350, а ходьбы 300 так как там walk fast есть).
Второй вариант: шанс 15\20\25% будучи атакованным, герой рандомно переместился вправо ЛИБО (рандомно) влево (влево пока не анимировал еще) и следующий удар будет критическим 150%\200%\250%. Анимация уворота длится 1.2 секунд. Надо чтобы после уклона герой авто-атаку сделал обычную, может быть такое что после уклона анимация атаки не сыграет вроде.
Третий вариант: это для другого персонажа, пусть временным тестером будет Мэв, при нажатии герой высоко отскакивает в противоположную сторону куда она смотрит (назад т.е.) анимацией Spell Slam (вроде), а зона, где она изначально была взрывается через 0.5 сек и наносит 100\200\300 урона в радиусе взрыва, скажем 600
Я думаю что уклон влево\вправо анимация очень медленная, я б хотел посмотреть как оно работает против группы противников) Поэтому добавлю измененный файл снизу. Там Spell throw Gold 0.6 секунд длится вместо 1.2
И еще чтобы эти абилки работали на всех, кто ее может изучить 😀"
Ответы (19)
28
Выполнение заказа

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

Dodge (первый вариант)

инструкция по импорту
скопировать папку Initialization и вставить в свою карту, копировать элементы из редактора объектов и вставлять в свою карту
всё остальное гуишное, думаю разберёшься, (указать в триггерах абилки из ро, ну и можешь с параметрами побаловаться, вроде скорости переката и времени для баффов)
чисто из спеллмейкерского рационализма, я бы всё же добавил учёт преград для переката и сделал скорость переката (и анимации соответственно) в зависимости от скорости бега, а то глупо выглядит, когда бегает быстрее чем перекатывается, ну, и добавил бы минимальную дистанцию для переката, впрочем, прикладываю ещё одну версию с более быстрым перекатом (0.50 сек вместо 1.00)
Загруженные файлы
28
Выполнение заказа

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

Dodge (второй вариант)

инструкция по импорту
скопировать папку Initialization и вставить в свою карту, копировать элементы из редактора объектов и вставлять в свою карту
всё остальное гуишное, думаю разберёшься, (указать в триггерах абилки из ро, ну и можешь с параметрами побаловаться, вроде скорости уворота, дальности, угла)
на видео демонстрация 100% уворота, чтобы не дожидаться выпадения шансов (в карте 15/20/25%)
кроме этого, длительность уворота поставил не 1.20, а 0.50, потому что ну это капес перебор дружище, впрочем, всё в твоих руках, угол настроил не под 90 градусов, а 50, чтобы кружился вокруг атакующего противника и делал нырки при беге к дальнику ближе к его стороне, но опять же, всё настраиваемо
кроме того, пока юнит не нанесёт критический удар, он добавлен в группу для проверки, планировал это делать только на время самого уворота, но понял, что слишком большая потеря контроля происходит, если тебя устраивает шанс того, что игрок может всё время в уворотах находиться на поле боя и не иметь возможности убежать/ударить - убери всё, что связано с TempGroup
Загруженные файлы
28
Shermanator00, хотел сделать спеллпак на эту модель, но она конченная какая-то, лишние звуки, нет точек крепления нормальных, забил короче
28
Shermanator00, а, только сейчас увидел что ты там изменённую модельку кинул, ну импортируешь заменой свою модель и посмотришь как оно выглядит
11
rsfghd, лишние звуки и точки крепления? И спасибо за работу, но на видео видно, что она уклоняется но при этом урон проходит
28
Shermanator00, не вижу во втором варианте что-то связанное с блокированием урона. Только перемещение влево/вправо и добавление критического шанса для следующей автоатаки. Есть 2 варианта, либо заблокировать урон с автоатаки во время рывка, либо добавить 100% уклонение на время рывка, что подходит?
28
лишние звуки и точки крепления?
Да, во время рывка ты слышишь какой-то лишний звук, во время критического удара то же самое, точек крепления будто вовсе нет, хотел эффект прикрепить к оружию/правой руке. Но мне уже всё равно даже если исправленную модель зальют
28
Shermanator00, есть ещё 2 варианта, это переделать не под "юнит атакован", а "юнит получает урон", но в данном случае уклонение уже не сработает вроде, только блокирование урона, при этом, не будет казусов, учитывающих факторы старта вылета снаряда и скорость снаряда (потому что абилка срабатывает, когда снаряд ещё даже не появился, при запахе атакующего)
Либо кастомная автоатака в карте)
11
Shermanator00, есть ещё 2 варианта, это переделать не под "юнит атакован", а "юнит получает урон", но в данном случае уклонение уже не сработает вроде, только блокирование урона, при этом, не будет казусов, учитывающих факторы старта вылета снаряда и скорость снаряда (потому что абилка срабатывает, когда снаряд ещё даже не появился, при запахе атакующего)
Либо кастомная автоатака в карте)
Я сделал эту модель и странно, в Magosе посмотрел вроде все атачменты есть. Модель мою промодерировали и сказали что все ок. Звуки я добавил через магос чтобы в игре триггерами не писать. Насчет получение урона: такое возможно сделать только с damage engine (увы старых версия нет только на 1.35+)? Там вроде все есть и блокирование урона и получение урона. Так можно сделать например удар в спину чтобы не нажимать кнопку S постоянно когда юнит атакован и тригерить собсвенно удар в спину.
Юнит получает урон эта функция добавлена в новом патче варкрафта. В старом ее нет(
28
Shermanator00, есть всё на ванилке. Если я предлагаю какие-то варианты недоступные стандартными методами, я говорю, что данный метод нестандартный
Я пытался прикрепить эффекты юниту, но мне не удалось прикрепить туда, где я ожидал их увидеть, ни на правой руке, ни на оружии, а значит, соответствующих аттачментов нет
Мне, как спеллмейкеру, звуки в модели порой мешают. Я хочу сам решать какой звук создавать и какой громкости
11
rsfghd, странно, что никто не писал до этого про точки крепления, но я гляну что там с ними, спасибо.
28
Shermanator00, вот с блоком урона и началом уворота при получении урона, а не замахе
Загруженные файлы
28
Выполнение заказа

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

Dodge (третий вариант )

инструкция по импорту
скопировать папку Initialization и вставить в свою карту, копировать элементы из редактора объектов и вставлять в свою карту
все настройки на гуи, думаю разберёшься
Загруженные файлы
28
Демонстрация работ
Shermanator00, блин, у тебя такой заказ простой, но даже тут не хватает банального разнообразия, придумывайте более интересные спеллы, например, в прыжке разбрасывает сюрикены в разные стороны, которые при непродолжительном полёте выбирают цели вокруг для преследования, при достижении цели - поджигают её временно, если целей не было обнаружено - падают в точку прыжка, создавая взрыв и поджигая почву на время

если кто-то захочет импортировать, то скопируйте папку Initialization в свою карту, объекты из ро и в триггере Spell настройте под себя 258-265 строки и поменяйте равкод абилки на 283 строке, ну и равкоды даммиков по коду, остальное требует минимальных знаний джасса
Загруженные файлы
28
Shermanator00, демонстративный вариант, если что, написан на вджассе, а не гуи

Код

AllGlobals
library AllGlobalsLib
globals
    constant hashtable H = InitHashtable( )
    constant real UNIT_MAX_COLLISION = 200.00
    constant location LFZ = Location( 0.00, 0.00 )
    
    real MaxX
    real MinX
    real MaxY
    real MinY
endglobals

native UnitAlive takes unit id returns boolean

function GetLocZ takes real x, real y returns real
    call MoveLocation( LFZ, x, y )
    return GetLocationZ( LFZ )
endfunction

function GetCorY takes real y returns real
    if y > MaxY then
        return MaxY
    elseif y < MinY then
        return MinY
    endif
    
    return y
endfunction

function GetCorX takes real x returns real
    if x > MaxX then
        return MaxX
    elseif x < MinX then
        return MinX
    endif
    
    return x
endfunction

function ParabolaZ2 takes real y0, real y1, real h, real d, real x returns real
    return ((4 * h / d) * (d - x) + y1 - y0) * (x / d) + y0
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 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( )
endglobals

private struct ProjectileS
    timer t
    unit dummy
    unit dummy1
    
    vector array v[4]
    
    real time
    real timeMax
endstruct

private struct SpellS
    timer t
    unit caster
    player p
    vector v
    vector l
    
    real time
    real timeDamage
    
    real radius
    real damage
    real height
    
    real speed
    real distance
    real distanceMax
    
    attacktype attackType
    damagetype damageType
    weapontype weaponType
endstruct

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.03125 / A.timeMax
    
    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
    
    set x[0] = GetCorX( x[0] )
    set y[0] = GetCorX( y[0] )
    
    call SetUnitX( A.dummy, x[0] )
    call SetUnitY( A.dummy, y[0] )
    call SetUnitFlyHeight( A.dummy, z[0] - GetLocZ( x[0], y[0] ), 0.00 )
    
    call SetUnitX( A.dummy1, x[0] )
    call SetUnitY( A.dummy1, y[0] )
    call SetUnitFlyHeight( A.dummy1, z[0] - GetLocZ( x[0], y[0] ), 0.00 )
    
    if A.time >= 1.00 then
        call PauseTimer( A.t )
        call FlushChildHashtable( H, GetHandleId( A.t ) )
        call DestroyTimer( A.t )
        
        call SetUnitAnimation( A.dummy, "death" )
        call UnitApplyTimedLife( A.dummy, 'BTLF', 1.50 )
        
        call SetUnitAnimation( A.dummy1, "death" )
        call UnitApplyTimedLife( A.dummy1, 'BTLF', 1.50 )
        
        set bj_lastCreatedUnit = CreateUnit( GetOwningPlayer( A.dummy ), 'u002', x[0], y[0], GetRandomReal( 0.00, 360.00 ) )
        call SetUnitX( bj_lastCreatedUnit, x[0] )
        call SetUnitY( bj_lastCreatedUnit, y[0] )
        call SetUnitAnimation( bj_lastCreatedUnit, "birth" )
        call QueueUnitAnimation( bj_lastCreatedUnit, "stand" )
        call UnitApplyTimedLife( bj_lastCreatedUnit, 'BTLF', 0.67 )
        call SetUnitScale( bj_lastCreatedUnit, 2.50, 2.50, 2.50 )
        
        call DestroyEffect( AddSpecialEffect( "Abilities\\Weapons\\LavaSpawnMissile\\LavaSpawnBirthMissile.mdl", x[0], y[0] ) )
        
        set i = 0
        
        loop
            call A.v[i].destroy( )
            
            set i = i + 1
            exitwhen i >= 4
        endloop
        
        set A.dummy = null
        set A.dummy1 = null
        call A.destroy( )
    endif
endfunction

private function Move takes nothing returns nothing
    local SpellS A = LoadInteger( H, GetHandleId( GetExpiredTimer( ) ), 0 )
    local ProjectileS B
    local real x
    local real y
    local real z
    local unit u
    local integer i
    
    if A.distance > 0.00 then
        set x = GetCorX( GetUnitX( A.caster ) + A.speed * A.v.x )
        set y = GetCorY( GetUnitY( A.caster ) + A.speed * A.v.y )
        
        if A.speed > A.distance then
            set A.speed = A.distance
        endif
        
        set A.distance = A.distance - A.speed
        
        call SetUnitX( A.caster, x )
        call SetUnitY( A.caster, y )
        call SetUnitFlyHeight( A.caster, ParabolaZ2( A.v.z, A.l.z, A.height, A.distanceMax, A.distance ) - GetLocZ( x, y ), 0.00 )
    endif
    
    if A.time > 0.00 then
        set A.time = A.time - 0.01
        
        if A.time <= 0.00 then
            set x = GetUnitX( A.caster )
            set y = GetUnitY( A.caster )
            set z = GetLocZ( x, y ) + GetUnitFlyHeight( A.caster ) + 85.00
            set i = 10
            
            loop
                set B = ProjectileS.create( )
                
                set B.t = CreateTimer( )
                set B.v[0] = vector.create( x, y, z )
                set B.v[1] = vector.create( x + 200.00 * GetRandomReal( -bj_PI, bj_PI ), y + 200.00 * GetRandomReal( -bj_PI, bj_PI ), GetRandomReal( z + 50.00, z + 200.00 ) )
                set B.v[2] = vector.create( x + 200.00 * GetRandomReal( -bj_PI, bj_PI ), y + 200.00 * GetRandomReal( -bj_PI, bj_PI ), GetRandomReal( z + 50.00, z + 100.00 ) )
                set B.v[3] = vector.create( A.l.x + GetRandomReal( -100.00, 100.00 ), A.l.y + GetRandomReal( -100.00, 100.00 ), A.l.z )
                
                set B.dummy = CreateUnit( A.p, 'u000', B.v[0].x, B.v[0].y, GetRandomReal( 0.00, 360.00 ) )
                call UnitAddAbility( B.dummy, 'Arav' )
                call SetUnitX( B.dummy, B.v[0].x )
                call SetUnitY( B.dummy, B.v[0].y )
                call SetUnitFlyHeight( B.dummy, B.v[0].z - GetLocZ( B.v[0].x, B.v[0].y ), 0.00 )
                call SetUnitAnimation( B.dummy, "birth" )
                call QueueUnitAnimation( B.dummy, "stand" )
                
                set B.dummy1 = CreateUnit( A.p, 'u001', B.v[0].x, B.v[0].y, GetRandomReal( 0.00, 360.00 ) )
                call UnitAddAbility( B.dummy1, 'Arav' )
                call SetUnitX( B.dummy1, B.v[0].x )
                call SetUnitY( B.dummy1, B.v[0].y )
                call SetUnitFlyHeight( B.dummy1, B.v[0].z - GetLocZ( B.v[0].x, B.v[0].y ), 0.00 )
                call SetUnitAnimation( B.dummy1, "birth" )
                call QueueUnitAnimation( B.dummy1, "stand" )
                
                set B.time = 0.00
                set B.timeMax = A.timeDamage
                
                call SaveInteger( H, GetHandleId( B.t ), 0, B )
                call TimerStart( B.t, 0.03125, true, function MoveProjectile )
                
                set i = i - 1
                exitwhen i <= 0
            endloop
        endif
    elseif A.timeDamage > 0.00 then
        set A.timeDamage = A.timeDamage - 0.01
        
        if A.timeDamage <= 0.00 then
            set bj_lastCreatedUnit = CreateUnit( A.p, 'u002', A.l.x, A.l.y, GetRandomReal( 0.00, 360.00 ) )
            call SetUnitX( bj_lastCreatedUnit, A.l.x )
            call SetUnitY( bj_lastCreatedUnit, A.l.y )
            call SetUnitAnimation( bj_lastCreatedUnit, "birth" )
            call QueueUnitAnimation( bj_lastCreatedUnit, "stand" )
            call UnitApplyTimedLife( bj_lastCreatedUnit, 'BTLF', 0.67 )
            call SetUnitScale( bj_lastCreatedUnit, 5.00, 5.00, 5.00 )
            
            set bj_lastCreatedUnit = CreateUnit( A.p, 'u002', A.l.x, A.l.y, GetRandomReal( 0.00, 360.00 ) )
            call SetUnitX( bj_lastCreatedUnit, A.l.x )
            call SetUnitY( bj_lastCreatedUnit, A.l.y )
            call SetUnitAnimation( bj_lastCreatedUnit, "birth" )
            call QueueUnitAnimation( bj_lastCreatedUnit, "stand" )
            call UnitApplyTimedLife( bj_lastCreatedUnit, 'BTLF', 0.67 )
            call SetUnitScale( bj_lastCreatedUnit, 8.00, 8.00, 8.00 )
            
            call DestroyEffect( AddSpecialEffect( "Objects\\Spawnmodels\\Other\\NeutralBuildingExplosion\\NeutralBuildingExplosion.mdl", A.l.x, A.l.y ) )
        
            call GroupEnumUnitsInRange( TempGroup, A.l.x, A.l.y, A.radius + UNIT_MAX_COLLISION, null )
        
            loop
                set u = FirstOfGroup( TempGroup )
                exitwhen u == null
                call GroupRemoveUnit( TempGroup, u )
                
                if IsUnitInRangeXY( u, A.l.x, A.l.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
        endif
    endif
    
    if A.distance <= 0.00 and A.timeDamage <= 0.00 then
        call PauseTimer( A.t )
        call FlushChildHashtable( H, GetHandleId( A.t ) )
        call DestroyTimer( A.t )
        
        set A.caster = null
        call A.l.destroy( )
        call A.v.destroy( )
        call A.destroy( )
    endif
endfunction

private function Spell_Actions takes nothing returns nothing
    local SpellS A = SpellS.create( )
    
    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 ), ( GetUnitFacing( A.caster ) - 180.00 ) * bj_DEGTORAD )
    set A.v = vector.create( Cos( A.l.z ), Sin( A.l.z ), 0.00 )
    set A.l.z = GetLocZ( A.l.x, A.l.y )
    
    set A.damage = 100.00 * GetUnitAbilityLevel( A.caster, GetSpellAbilityId( ) )
    set A.radius = 185.00
    set A.distance = 400.00
    set A.distanceMax = A.distance
    set A.height = A.distance * 0.50
    set A.speed = A.distance * 0.01
    set A.time = 0.20
    set A.timeDamage = 1.20
    
    set A.v.z = GetLocZ( A.l.x + A.distance * A.v.x, A.l.y + A.distance * A.v.y )
    
    set A.attackType = ATTACK_TYPE_MAGIC
    set A.damageType = DAMAGE_TYPE_MAGIC
    set A.weaponType = null
    
    if UnitAddAbility( A.caster, 'Arav' ) then
        call UnitRemoveAbility( A.caster, 'Arav' )
    endif
    
    call SaveInteger( H, GetHandleId( A.t ), 0, A )
    call TimerStart( A.t, 0.01, true, function Move )
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_CAST )
    call TriggerAddCondition( gg_trg_Spell, Condition( function Spell_Conditions ) )
    call TriggerAddAction( gg_trg_Spell, function Spell_Actions )
endfunction
endlibrary

28
Демонстрация работ
Shermanator00, вот тут ещё вариант прыжка, этот спеллпак делать начал где-то пол года назад, но мне не понравилось что он недостаточно интересный, поэтому не могу его выкатить, тут телепорт вверх с последующим приземлением, сразу после телепорта раскидывает сюрикены, которые застревают в земле, на них можно наступить и получить урон, через короткое время сюрикены, что остались в земле - возвращаются, попутно задевая всех противников
карту не скину, т.к. планирую переделать и выкатить, надеюсь это поможет немного интереснее фантазировать
Загруженные файлы
2 комментария удалено
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

Загруженные файлы
Показан только небольшой набор комментариев вокруг указанного. Перейти к актуальным.
Чтобы оставить комментарий, пожалуйста, войдите на сайт.