nazarpunk, мб когда апи с прожектайлами починятся и дополнятся, то сделаю заказы с копированием снарядов, сейчас каждый раз на грабли натыкаюсь и тильтую
globals
constant timer TempTimer = CreateTimer( )
constant group TempGroup = CreateGroup( )
integer max = 0
unit array caster
unit array dummy
player array owningPlayer
group array g
real array x
real array y
real array angleX
real array angleY
real array radius
real array speed
real array distance
endglobals
native UnitAlive takes unit id returns boolean
function Move takes nothing returns nothing
local integer i = 1
local unit u
loop
exitwhen i > max
if speed[i] > distance[i] then
set speed[i] = distance[i]
endif
set x[i] = x[i] + speed[i] * angleX[i]
set y[i] = y[i] + speed[i] * angleY[i]
call SetUnitX( dummy[i], x[i] )
call SetUnitY( dummy[i], y[i] )
call DestroyEffect( AddSpecialEffect( "Objects\\Spawnmodels\\Other\\NeutralBuildingExplosion\\NeutralBuildingExplosion.mdl", x[i], y[i] ) )
call GroupEnumUnitsInRange( TempGroup, x[i], y[i], radius[i] + 200.00, null )
loop
set u = FirstOfGroup( TempGroup )
exitwhen u == null
call GroupRemoveUnit( TempGroup, u )
if IsUnitInRangeXY( u, x[i], y[i], radius[i] ) then
if not IsUnitInGroup( u, g[i] ) then
if UnitAlive( u ) and IsUnitEnemy( u, owningPlayer[i] ) then
call GroupAddUnit( g[i], u )
call UnitDamageTarget( caster[i], u, 100.00, false, false, null, null, null )
endif
endif
endif
endloop
set distance[i] = distance[i] - speed[i]
if distance[i] <= 0.00 then
call KillUnit( dummy[i] )
call DestroyGroup( g[i] )
set caster[i] = caster[max]
set dummy[i] = dummy[max]
set owningPlayer[i] = owningPlayer[max]
set g[i] = g[max]
set x[i] = x[max]
set y[i] = y[max]
set angleX[i] = angleX[max]
set angleY[i] = angleY[max]
set radius[i] = radius[max]
set speed[i] = speed[max]
set distance[i] = distance[max]
set max = max - 1
set i = i - 1
if max <= 0 then
call PauseTimer( TempTimer )
endif
endif
set i = i + 1
endloop
endfunction
function Trig_Untitled_Trigger_001_Actions takes nothing returns nothing
local real a
if max == 0 then
call TimerStart( TempTimer, 0.03125, true, function Move )
endif
set max = max + 1
set caster[max] = GetTriggerUnit( )
set owningPlayer[max] = GetOwningPlayer( caster[max] )
set g[max] = CreateGroup( )
set x[max] = GetUnitX( caster[max] )
set y[max] = GetUnitY( caster[max] )
set a = Atan2( GetSpellTargetY( ) - y[max], GetSpellTargetX( ) - x[max] )
set angleX[max] = Cos( a )
set angleY[max] = Sin( a )
set dummy[max] = CreateUnit( owningPlayer[max], 'h000', x[max], y[max], a * bj_RADTODEG )
set radius[max] = 200.00
set speed[max] = 1000.00 * 0.03125
set distance[max] = 1000.00
endfunction
//===========================================================================
function InitTrig_Untitled_Trigger_001 takes nothing returns nothing
set gg_trg_Untitled_Trigger_001 = CreateTrigger( )
call TriggerRegisterAnyUnitEventBJ( gg_trg_Untitled_Trigger_001, EVENT_PLAYER_UNIT_SPELL_EFFECT )
call TriggerAddAction( gg_trg_Untitled_Trigger_001, function Trig_Untitled_Trigger_001_Actions )
endfunction
можешь в следующий раз по подобным спеллмейкерским вопросам обратиться в мою тему
а, я так понимаю там сама идея была в том, что огненный шар дамажит всё время при движении, а не один раз - достаточно тогда просто удалить всё, что связанно с переменной g
LastUchiha, какой-то ужас
я конечно понимаю что ты хотел на чистом джассе реализовать с глобалками, но хэштаблица со структурами будет удобнее, тем более, ты уже юзаешь вджасс
твои массивы на глобалках нужны разве что в гуишном варианте
я немного не понял нужен ли учёт сферических координат, если корабль только по наземным должен дамажить, поэтому просто пихнул проверку, что юнит не летающий
на видосе 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
скопировать папку Initialization и вставить в свою карту
скопировать даммика и абилку из ро и вставить в свою карту
в триггере Spell:
153 строка - указать равкод абилки
30-32 строки - указать скорость полёта снаряда
60 строка - количество целей для урона/хила после основной
54 строка - хил основной цели
57 строка - урон основной цели
62 строка - радиус с максимальной коллизией у юнита (+200)
71 строка - радиус
103 строка - хил второстепенных целей
105 строка - урон второстепенных целей
заменить 'u000' в коде на своего даммика
Код
Spell
function GetLocZ takes real x, real y returns real
call MoveLocation( udg_LFZ, x, y )
return GetLocationZ( udg_LFZ )
endfunction
function Move takes nothing returns nothing
local timer t = GetExpiredTimer( )
local integer i = GetHandleId( t )
local integer k
local player p
local unit caster
local unit target = LoadUnitHandle( udg_H, i, 1 )
local unit dummy = LoadUnitHandle( udg_H, i, 2 )
local unit u
local real x = GetUnitX( dummy )
local real y = GetUnitY( dummy )
local real z = LoadReal( udg_H, i, 3 )
local real x1 = GetUnitX( target )
local real y1 = GetUnitY( target )
local real z1 = GetLocZ( x1, y1 ) + GetUnitFlyHeight( target ) + 50.00
local real ax = x1 - x
local real ay = y1 - y
local real az = z1 - z
local real d = RMaxBJ( 1.00, SquareRoot( ax * ax + ay * ay + az * az ) )
set ax = ax / d
set ay = ay / d
set az = az / d
set x = x + 20.00 * ax
set y = y + 20.00 * ay
set z = z + 20.00 * az
call SetUnitX( dummy, x )
call SetUnitY( dummy, y )
call SetUnitFlyHeight( dummy, z - GetLocZ( x, y ), 0.00 )
if IsUnitInRange( dummy, target, 0.00 ) and SquareRoot( ( z1 - z ) * ( z1 - z ) ) <= 100.00 then
call SetUnitAnimation( dummy, "death" )
call UnitApplyTimedLife( dummy, 'BTLF', 2.00 )
set caster = LoadUnitHandle( udg_H, i, 0 )
set p = GetOwningPlayer( caster )
set k = LoadInteger( udg_H, i, 4 )
call PauseTimer( t )
call FlushChildHashtable( udg_H, GetHandleId( t ) )
call DestroyTimer( t )
if k == 1 then
if IsUnitAlly( target, p ) then
if not IsUnitType( target, UNIT_TYPE_DEAD ) then
call SetWidgetLife( target, GetWidgetLife( target ) + 600.00 )
endif
else
call UnitDamageTarget( caster, target, 400.00, false, false, null, null, null )
endif
set k = 5
call GroupEnumUnitsInRange( udg_TempGroup, x, y, 700.00, null )
call GroupRemoveUnit( udg_TempGroup, target )
loop
set u = FirstOfGroup( udg_TempGroup )
exitwhen u == null
call GroupRemoveUnit( udg_TempGroup, u )
if IsUnitInRangeXY( u, x, y, 500.00 ) then
if not IsUnitType( u, UNIT_TYPE_DEAD ) then
if ( IsUnitAlly( target, p ) and not IsUnitAlly( u, p ) ) or ( IsUnitAlly( u, p ) and not IsUnitAlly( target, p ) ) then
set t = CreateTimer( )
set i = GetHandleId( t )
set bj_lastCreatedUnit = CreateUnit( GetOwningPlayer( caster ), 'u000', x, y, Atan2( GetUnitY( u ) - y, GetUnitX( u ) - x ) * bj_RADTODEG )
call UnitAddAbility( bj_lastCreatedUnit, 'Arav' )
call SetUnitX( bj_lastCreatedUnit, x )
call SetUnitY( bj_lastCreatedUnit, y )
call SetUnitFlyHeight( bj_lastCreatedUnit, z - GetLocZ( x, y ), 0.00 )
call SetUnitAnimation( bj_lastCreatedUnit, "birth" )
call QueueUnitAnimation( bj_lastCreatedUnit, "stand" )
call SaveUnitHandle( udg_H, i, 0, caster )
call SaveUnitHandle( udg_H, i, 1, u )
call SaveUnitHandle( udg_H, i, 2, bj_lastCreatedUnit )
call SaveReal( udg_H, i, 3, z )
call SaveInteger( udg_H, i, 4, 0 )
call TimerStart( t, 0.01, true, function Move )
set i = i - 1
if i <= 0 then
call GroupClear( udg_TempGroup )
endif
endif
endif
endif
endloop
else
if IsUnitAlly( target, GetOwningPlayer( caster ) ) then
call SetWidgetLife( target, GetWidgetLife( target ) + 300.00 )
else
call UnitDamageTarget( caster, target, 190.00, false, false, null, null, null )
endif
endif
set caster = null
else
call SaveReal( udg_H, i, 3, z )
endif
set t = null
set dummy = null
set target = null
endfunction
function Trig_Spell_Actions takes nothing returns nothing
local timer t = CreateTimer( )
local integer i = GetHandleId( t )
local unit caster = GetTriggerUnit( )
local unit target = GetSpellTargetUnit( )
local real x = GetUnitX( caster )
local real y = GetUnitY( caster )
local real z = GetUnitFlyHeight( caster ) + 50.00
set bj_lastCreatedUnit = CreateUnit( GetOwningPlayer( caster ), 'u000', x, y, Atan2( GetUnitY( target ) - y, GetUnitX( target ) - x ) * bj_RADTODEG )
call UnitAddAbility( bj_lastCreatedUnit, 'Arav' )
call SetUnitX( bj_lastCreatedUnit, x )
call SetUnitY( bj_lastCreatedUnit, y )
call SetUnitFlyHeight( bj_lastCreatedUnit, z, 0.00 )
call SetUnitAnimation( bj_lastCreatedUnit, "birth" )
call QueueUnitAnimation( bj_lastCreatedUnit, "stand" )
set z = z + GetLocZ( x, y )
call SaveUnitHandle( udg_H, i, 0, caster )
call SaveUnitHandle( udg_H, i, 1, target )
call SaveUnitHandle( udg_H, i, 2, bj_lastCreatedUnit )
call SaveReal( udg_H, i, 3, z )
call SaveInteger( udg_H, i, 4, 1 )
call TimerStart( t, 0.01, true, function Move )
set t = null
set caster = null
set target = null
endfunction
//===========================================================================
function Trig_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 Trig_Spell_Conditions ) )
call TriggerAddAction( gg_trg_Spell, function Trig_Spell_Actions )
endfunction
UndeadFisher, странно, только сейчас заметил на видосе, что при втором касте не заспавнились эффекты, но я не первый раз встречаю такую проблему, возможно дело в компе либо в самом варе, он не отображает порой эффекты, я из-за этой проблемы даже к даммикам возвращался когда-то, с ними всегда всё корректно было
удалить триггеры ниже триггера 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
LastUchiha, напиши просто, что через 5 секунд после получения последнего стака - все стаки должны сброситься, так будет понятнее, перенеси строку call TimerStart( t, 5.00, false, function RemoveDebuff ) рядом к строке call SaveInteger( udg_H, i, 1, stack )
должно выйти так
if stack < udg_BDMax then
call SaveInteger( udg_H, i, 1, stack )
call TimerStart( t, 5.00, false, function RemoveDebuff )
else
call IssueTargetOrder( udg_TempUnit, "soulburn", damaged )
endif
время таймера будет обновляться каждый раз, когда юнит получает автоатаку, за исключением наличия последнего стака
LastUchiha, я сначала подумал, что может в цикле накосячил из-за недосыпа, но нет, это сайленс прикалывается. Когда обнулял значения сайленса, поставил периодичность урона на 0.00, в итоге, оно, похоже, каждые 0.00 секунд дамажило с 0 урона, вызывая триггер получения урона, решилось просто - выставил периодичность урона на 99999999999999, ну и приколы..
вот обновлённая карта с исправлением предыдущего косяка
Если эффект абилки триггерный, то в качестве завершения используй end cast. Остальные настройки есть у канала, follow through time на 3 секунды поставь
LastUchiha, ахахаха, блин, извиняюсь, перед сном делал спелл, вытащи из лупа в первом триггере всё, кроме добавления события, поставь чуть ниже/выше пика юнитов, а то там хэштаблица создаётся на каждого выбранного юнита
LastUchiha, если ты захочешь отнимать больше защиты или добавить больше стаков, что превысит 123 единицы (1+2+4+8+16+32+64), то добавь просто новые значения в бд (х2 предыдущего числа, т.е. 128/256/512/1024...), и не забудь указать новое количество индексов для BDMax
скопировать папку Initialization и вставить в свою карту, перекопировать редактор объектов и вставить в свою карту, в триггере Melee Initialization настроить бд в соответствии с редактором объектов
в триггере EventDamage на 81 строке указать даммика, что будет кастовать таргетный сайленс
на 70 строке можно изменить время спадения дебаффа на броню
на 61 строке можешь настроить формулу уменьшения брони
на 54 строке аура торнадо для отображения дебаффа на юните + статус бар (на 24-25 то же самое)
советую сделать прелоад ауры, чтобы при первом получении не происходил пролаг
Код
EventDamage
function SetBonusArmorNegative takes unit u, integer value returns nothing
local integer i = udg_BDMax
loop
exitwhen i <= 0
if udg_BDValue[i] <= value then
call UnitAddAbility( u, udg_BDAbil[i] )
set value = value - udg_BDValue[i]
else
call UnitRemoveAbility( u, udg_BDAbil[i] )
endif
set i = i - 1
endloop
endfunction
function RemoveDebuff takes nothing returns nothing
local timer t = GetExpiredTimer( )
local integer i = GetHandleId( t )
local unit u = LoadUnitHandle( udg_H, i, 0 )
call UnitRemoveAbility( u, 'A009' )
call UnitRemoveAbility( u, 'B000' )
call SetBonusArmorNegative( u, 0 )
call RemoveSavedInteger( udg_H, GetHandleId( u ), 0 )
call FlushChildHashtable( udg_H, i )
call DestroyTimer( t )
set u = null
set t = null
endfunction
function Trig_EventDamage_Actions takes nothing returns nothing
local unit damaged
local timer t
local integer i
local integer stack
if GetUnitAbilityLevel( GetTriggerUnit( ), 'Bspo' ) > 0 then
set damaged = GetTriggerUnit( )
call UnitRemoveAbility( damaged, 'Bspo' )
set t = LoadTimerHandle( udg_H, GetHandleId( damaged ), 0 )
if t == null then
set t = CreateTimer( )
call SaveTimerHandle( udg_H, GetHandleId( damaged ), 0, t )
call UnitAddAbility( damaged, 'A009' )
call SaveUnitHandle( udg_H, GetHandleId( t ), 0, damaged )
endif
set i = GetHandleId( t )
set stack = LoadInteger( udg_H, i, 1 ) + 1
call SetUnitAbilityLevel( damaged, 'A009', stack )
call SetBonusArmorNegative( damaged, IMaxBJ( 1, R2I( GetHeroLevel( GetEventDamageSource( ) ) * 0.10 ) ) * stack )
if stack < udg_BDMax then
call SaveInteger( udg_H, i, 1, stack )
else
call IssueTargetOrder( udg_TempUnit, "soulburn", damaged )
endif
call TimerStart( t, 5.00, false, function RemoveDebuff )
set t = null
set damaged = null
endif
endfunction
//===========================================================================
function InitTrig_EventDamage takes nothing returns nothing
set gg_trg_EventDamage = CreateTrigger( )
call TriggerAddAction( gg_trg_EventDamage, function Trig_EventDamage_Actions )
set udg_TempUnit = CreateUnit( Player( PLAYER_NEUTRAL_PASSIVE ), 'u000', 0.00, 0.00, 0.00 )
endfunction
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
» WarCraft 3 / Как удалять локальные переменные типа location?
» WarCraft 3 / Заклинания на заказ
Ред. rsfghd
» WarCraft 3 / Как сделать MUI через глобалки? - [Jass]
Код
» WarCraft 3 / Как сделать MUI через глобалки? - [Jass]
я конечно понимаю что ты хотел на чистом джассе реализовать с глобалками, но хэштаблица со структурами будет удобнее, тем более, ты уже юзаешь вджасс
» WarCraft 3 / Нормальная ли система применения способностей? - [Jass]
» WarCraft 3 / Нормальная ли система применения способностей? - [Jass]
попробуй лучше это xgm.guru/p/wc3/Preryvanie-vnutri-triggera-kZA/comments/view/5417...
без всяких елсеифов
Ред. rsfghd
» WarCraft 3 / Заклинания на заказ
Заклинание готово!
78 строка - указать абилку и шанс такой атаки (абилку выдать юнитам, что должны проводить эту атаку)
85 строка - начальный оффсет угла от взгляда атакующего
86 строка - скорость вращения лазеров
93 строка - через сколько секунд появляются лазеры после начала проигрывания анимки Spell Slam
21-24 строки - оффсеты для лазеров
30 строка - радиус вокруг атакующего
38 строка - ширина лазера (32.00)
47, 49-52 строки - шаг лазера (чем больше тем менее точно, но более оптимизировано, лучше не ставить больше радиуса лазера)
48 строка - дальность лазера
54-55 - эффекты, использовал по сути как дебаг для ориентации скорости, оффсета и угла лазеров, можно удалить строки
58 - максимальный угол лазеров
71 - периодичность таймера (чем больше, тем оптимизированнее и менее точно, при изменении этой строки на 86 строке (0.05) тоже изменить периодичность)
Код
Ред. rsfghd
» WarCraft 3 / Заклинания на заказ
Заклинание готово!
Божественная призма
скопировать даммика и абилку из ро и вставить в свою карту
в триггере Spell:
153 строка - указать равкод абилки
30-32 строки - указать скорость полёта снаряда
60 строка - количество целей для урона/хила после основной
54 строка - хил основной цели
57 строка - урон основной цели
62 строка - радиус с максимальной коллизией у юнита (+200)
71 строка - радиус
103 строка - хил второстепенных целей
105 строка - урон второстепенных целей
Код
» WarCraft 3 / Заклинания на заказ
» WarCraft 3 / Заклинания на заказ
» WarCraft 3 / Заклинания на заказ
» WarCraft 3 / Заклинания на заказ
» WarCraft 3 / Заклинания на заказ
Заклинание готово!
скопировать папку Initialization и вставить в свою карту
указать равкод абилки на 367 строке триггера Spell
изменить строки 340-344 на свой вкус
всё остальное требует минимальных знаний джасса
сделано на южапи
Код
» WarCraft 3 / Заклинания на заказ
» WarCraft 3 / Анимация юнита при нажатии способности
» WarCraft 3 / Заклинания на заказ
» WarCraft 3 / Заклинания на заказ
» WarCraft 3 / Заклинания на заказ
» WarCraft 3 / Анимация юнита при нажатии способности
Ред. rsfghd
» WarCraft 3 / Заклинания на заказ
» WarCraft 3 / Заклинания на заказ
» WarCraft 3 / Заклинания на заказ
» WarCraft 3 / Заклинания на заказ
Заклинание готово!
Понижение защиты
на 70 строке можно изменить время спадения дебаффа на броню
на 61 строке можешь настроить формулу уменьшения брони
на 54 строке аура торнадо для отображения дебаффа на юните + статус бар (на 24-25 то же самое)
Код
» WarCraft 3 / Заклинания на заказ
» WarCraft 3 / Заклинания на заказ
Заклинание готово!
Код