В дополнение к комменту выше, чтобы каст произошёл спиной, нужно настройку в ро (не помню название на русском, prop window), выставить на 180. Однако кастер всё равно повернётся. Этот параметр отвечает за разницу углов между целью/точкой каста и поворотом кастера. То есть если значение будет 1, юниту полностью нужно повернуться в точку каста, если 180, то кастовать начнет мгновенно со даже со спины. Кроме этого есть ещё 2 параметра, cast point и backswing point, первое отвечает за общее время каста спеллов у юнита, второе дополнительное время для каста во время поворота
Кроме этого в планах сделать кат со всеми выполненными заказами в самом ресурсе, чтобы люди могли искать интересующие спеллы не бегая по страницам комментариев
ShadowNinja, да не выгорел. Пытался заказ назарпанка сделать, а на южапи функции не работали должным образом, анрайз что-то поправил и продолжает исправлять, но я потратил на это выходной. Оставляй заказы, по мере заинтересованности буду делать. Вечером отталкиванием займусь, возьму анимку spell у чародея крови, выпущу двух фениксов по дуге в сторону цели и вместе со свистелками реализую отталкивание. Единственное что мне не очень нравится, это то, что цель может двигаться, из-за этого проблемы логические могут возникнуть. Впрочем, если делать мгновенное отталкивание без украшений, то всё будет оке, но у тебя технические задачи на полёт моей собственной фантазии. Буду делать на южапи
Shermanator00, вот тут ещё вариант прыжка, этот спеллпак делать начал где-то пол года назад, но мне не понравилось что он недостаточно интересный, поэтому не могу его выкатить, тут телепорт вверх с последующим приземлением, сразу после телепорта раскидывает сюрикены, которые застревают в земле, на них можно наступить и получить урон, через короткое время сюрикены, что остались в земле - возвращаются, попутно задевая всех противников
карту не скину, т.к. планирую переделать и выкатить, надеюсь это поможет немного интереснее фантазировать
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
Shermanator00, блин, у тебя такой заказ простой, но даже тут не хватает банального разнообразия, придумывайте более интересные спеллы, например, в прыжке разбрасывает сюрикены в разные стороны, которые при непродолжительном полёте выбирают цели вокруг для преследования, при достижении цели - поджигают её временно, если целей не было обнаружено - падают в точку прыжка, создавая взрыв и поджигая почву на время
если кто-то захочет импортировать, то скопируйте папку Initialization в свою карту, объекты из ро и в триггере Spell настройте под себя 258-265 строки и поменяйте равкод абилки на 283 строке, ну и равкоды даммиков по коду, остальное требует минимальных знаний джасса
скопировать папку Initialization и вставить в свою карту, копировать элементы из редактора объектов и вставлять в свою карту
все настройки на гуи, думаю разберёшься
ME_RiDi, тз с результатом хз. Животным абилку дирижабля дать или это трансформация юнита как с лучница и и гиппогрифами? Или просто периодически героя перемещать в позицию животного? Как затрачивается шкала усталости? Что будет при полном нуле? Нужно ли отображать шкалу? Если да, то каким способом?
Да, там суммарный урон выводится. Если нужно отдельный, то урон от атаки и абилки нужно записать в разные переменные, если нужно, могу объяснить, там буквально 2 строки написать в разных местах
SebastianCarrey, посмотрел, к сожалению южапи немного скривил, либо реф с новым патчем изменил аргументы и выглядит следующим образом BlzGetAbilityCooldown takes integer abilId, integer level returns real
Первым аргументом принимает равкод, а вторым уровень абилки, так что замени все эти строки на BlzGetAbilityCooldown( 'A000', GetUnitAbilityLevel( A.caster, 'A000' ) )
Где А000 - равкод основной абилки
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
удалить из папки 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
ShadowNinja, а я о чём говорю, когда предлагаю через пкм сделать луч. Кликнул во время каста и юнит повернулся в точку, куда кликнул, если кликнул на юнита, то кастер будет всё время поворачиваться на него, пока в другое место не кликнешь. Единственная проблема это невозможность отменить каст спелла движением. Но можно отменить, например, нажав на S
Panda_95, если вы не понимаете что это значит, то после 100к кастов допустим (а может и раньше, если в карте и в другом коде присутствуют утечки), начнутся лаги, а потом и вовсе краш игры из-за нехватки памяти. Ну а поллед вейт может не соответствовать анимации удара по земле с разницей около 0.10 сек
» WarCraft 3 / Как узнать есть ли цель способности за кастующим юнитом
» WarCraft 3 / Заклинания на заказ
Ред. rsfghd
» WarCraft 3 / Заклинания на заказ
» WarCraft 3 / Заклинания на заказ
» WarCraft 3 / Заклинания на заказ
Код
» WarCraft 3 / Заклинания на заказ
» WarCraft 3 / Заклинания на заказ
Заклинание готово!
Dodge (третий вариант )
все настройки на гуи, думаю разберёшься
» WarCraft 3 / Заклинания на заказ
» WarCraft 3 / Эффект снижения лечения
» WarCraft 3 / Заклинания на заказ
» WarCraft 3 / Заклинания на заказ
» WarCraft 3 / Спавн как в Direct Strike
» WarCraft 3 / Заклинания на заказ
» WarCraft 3 / Заклинания на заказ
BlzGetAbilityCooldown takes integer abilId, integer level returns real
Первым аргументом принимает равкод, а вторым уровень абилки, так что замени все эти строки на
BlzGetAbilityCooldown( 'A000', GetUnitAbilityLevel( A.caster, 'A000' ) )
Где А000 - равкод основной абилки
Ред. rsfghd
» WarCraft 3 / Заклинания на заказ
Ред. rsfghd
» WarCraft 3 / Заклинания на заказ
Заклинание готово!
Молот древних (Rolling Slam)
» WarCraft 3 / Способности и алгоритмы на заказ
» WarCraft 3 / Способности и алгоритмы на заказ
» WarCraft 3 / Заклинания на заказ
» WarCraft 3 / Заклинания на заказ
» WarCraft 3 / Заклинания на заказ
» WarCraft 3 / Способности и алгоритмы на заказ
» WarCraft 3 / Способности и алгоритмы на заказ
» WarCraft 3 / Эффект снижения лечения