Files
2021-10-24 15:36:18 -04:00

326 lines
12 KiB
Lua
Executable File

aghanim_shard_attack = class( {} )
LinkLuaModifier( "modifier_aghanim_shard_attack", "modifiers/creatures/modifier_aghanim_shard_attack", LUA_MODIFIER_MOTION_NONE )
_G.PATTERN_SPIRAL = 0
_G.PATTERN_REBOUND = 1
_G.PATTERN_JITTER = 2
_G.CAST_ESCLATION_PCT = 17
_G.FAST_COLOR = Vector( 0, 0, 255 )
_G.SLOW_COLOR = Vector( 350, 0, 0 ) -- looks weird, but it's because it can't go to 0 speed
_G.HEAL_COLOR = Vector( 0, 255, 0 )
----------------------------------------------------------------------------------------
function aghanim_shard_attack:Precache( context )
PrecacheResource( "particle", "particles/creatures/aghanim/aghanim_shard_channel.vpcf", context )
PrecacheResource( "particle", "particles/creatures/aghanim/aghanim_shard_proj.vpcf", context )
PrecacheResource( "particle", "particles/units/heroes/hero_lich/lich_frost_nova.vpcf", context )
PrecacheResource( "soundfile", "soundevents/game_sounds_heroes/game_sounds_dark_willow.vsndevts", context )
PrecacheResource( "soundfile", "soundevents/game_sounds_heroes/game_sounds_silencer.vsndevts", context )
self.nPattern = PATTERN_SPIRAL
self.nCastCount = 0
self.Projectiles = {}
end
----------------------------------------------------------------------------------------
function aghanim_shard_attack:ProcsMagicStick()
return false
end
--------------------------------------------------------------------------------
function aghanim_shard_attack:OnAbilityPhaseStart()
if IsServer() then
StartSoundEventFromPositionReliable( "Aghanim.ShardAttack.Channel", self:GetCaster():GetAbsOrigin() )
self.nChannelFX = ParticleManager:CreateParticle( "particles/creatures/aghanim/aghanim_shard_channel.vpcf", PATTACH_ABSORIGIN_FOLLOW, self:GetCaster() )
end
return true
end
-------------------------------------------------------------------------------
function aghanim_shard_attack:OnChannelThink( flInterval )
if IsServer() then
if self.nPattern == PATTERN_SPIRAL then
self:ThinkSpirals( flInterval )
end
end
end
-------------------------------------------------------------------------------
function aghanim_shard_attack:OnChannelFinish( bInterrupted )
if IsServer() then
StopSoundOn( "Aghanim.ShardAttack.Loop", self:GetCaster() )
ParticleManager:DestroyParticle( self.nChannelFX, false )
self.nCastCount = self.nCastCount + 1
end
end
-------------------------------------------------------------------------------
function aghanim_shard_attack:OnSpellStart()
if IsServer() then
EmitSoundOn( "Aghanim.ShardAttack.Loop", self:GetCaster() )
if self.nPattern == PATTERN_SPIRAL then
self:BeginSpirals()
end
if self.nPattern == PATTERN_REBOUND then
self:BeginRebound()
end
if self.nPattern == PATTERN_JITTER then
self:BeginJitter()
end
end
end
-------------------------------------------------------------------------------
function aghanim_shard_attack:BeginSpirals()
self.Projectiles = {}
self.spiral_projectiles = self:GetSpecialValueFor( "spiral_projectiles" )
self.spiral_projectile_waves = self:GetSpecialValueFor( "spiral_projectile_waves" )
self.spiral_projectile_speed = self:GetSpecialValueFor( "spiral_projectile_speed" )
self.spiral_projectiles = math.min( self.spiral_projectiles * 2, math.floor( self.spiral_projectiles + ( self.spiral_projectiles * CAST_ESCLATION_PCT * self.nCastCount / 100 ) ) )
self.spiral_projectile_waves = math.min( self.spiral_projectile_waves * 2, math.floor( self.spiral_projectile_waves + ( self.spiral_projectile_waves * CAST_ESCLATION_PCT * self.nCastCount / 100 ) ) )
self.spiral_projectile_speed = math.min( self.spiral_projectile_speed * 2, math.floor( self.spiral_projectile_speed + ( self.spiral_projectile_speed * CAST_ESCLATION_PCT * self.nCastCount / 100 ) ) )
self.spiral_projectile_rotation_speed = self:GetSpecialValueFor( "spiral_projectile_rotation_speed" )
self.spiral_projectile_width = self:GetSpecialValueFor( "spiral_projectile_width" )
self.spiral_projectile_damage = self:GetSpecialValueFor( "spiral_projectile_damage" )
self.spiral_projectile_speed_change_interval = self:GetSpecialValueFor( "spiral_projectile_speed_change_interval" )
self.flSpiralYaw = RandomInt( 0, 360 )
self.flSpiralWaveInterval = self:GetChannelTime() / self.spiral_projectile_waves
self.flSpiralNextWaveTime = GameRules:GetGameTime()
self.flSpiralYawStep = 360 / self.spiral_projectiles
self.bReverse = false
if RandomInt( 0, 1 ) == 1 then
self.bReverse = true
end
self.flSpiralSpeedToggleTime = GameRules:GetGameTime() + self.spiral_projectile_speed_change_interval
self.bSpiralSpeedingUp = true
self.flCurSpeed = self.spiral_projectile_speed
self.nToggleCount = 0
end
-------------------------------------------------------------------------------
function aghanim_shard_attack:ThinkSpirals( flInterval )
local flNow = GameRules:GetGameTime()
if flNow > self.flSpiralSpeedToggleTime then
self.flSpiralSpeedToggleTime = flNow + self.spiral_projectile_speed_change_interval
self.bSpiralSpeedingUp = not self.bSpiralSpeedingUp
self.nToggleCount = self.nToggleCount + 1
if self.nToggleCount == 2 then
self.bReverse = not self.bReverse
self.nToggleCount = 0
end
end
local flRate = ( self.spiral_projectile_speed / self.spiral_projectile_speed_change_interval ) * flInterval
if self.bSpiralSpeedingUp then
self.flCurSpeed = math.min( self.spiral_projectile_speed, self.flCurSpeed + flRate )
else
self.flCurSpeed = math.max( 100, self.flCurSpeed - flRate )
end
if self.flSpiralNextWaveTime > flNow then
return
end
self.flSpiralNextWaveTime = flNow + self.flSpiralWaveInterval
EmitSoundOn( "Aghanim.ShardAttack.Wave", self:GetCaster() )
for i=1,self.spiral_projectiles do
local Angle = QAngle( 0, self.flSpiralYaw, 0 )
local vVelocity = ( RotatePosition( Vector( 0, 0, 0 ), Angle, Vector( 1, 0, 0 ) ) ) * self.flCurSpeed
local nProjectileHandle = self:LaunchCrystals( vVelocity, 5000, self.spiral_projectile_width )
local ProjectileInfo = {}
ProjectileInfo.nHandle = nProjectileHandle
ProjectileInfo.flYaw = self.flSpiralYaw
ProjectileInfo.nFXIndex = ParticleManager:CreateParticle( "particles/creatures/aghanim/aghanim_shard_proj.vpcf", PATTACH_CUSTOMORIGIN, nil )
local vLoc = self:GetCaster():GetAbsOrigin()
vLoc.z = GetGroundHeight( vLoc, self:GetCaster() ) + 50
ProjectileInfo.attachEnt = CreateUnitByName( "npc_dota_wisp_spirit", vLoc, false, self:GetCaster(), self:GetCaster(), DOTA_TEAM_GOODGUYS )
if ProjectileInfo.attachEnt ~= nil then
ProjectileInfo.attachEnt:AddNewModifier( self:GetCaster(), self, "modifier_wisp_spirit_invulnerable", {} )
end
ParticleManager:SetParticleControlEnt( ProjectileInfo.nFXIndex, 0, ProjectileInfo.attachEnt, PATTACH_ABSORIGIN_FOLLOW, nil, vLoc, false )
ParticleManager:SetParticleControl( ProjectileInfo.nFXIndex, 1, Vector( self.spiral_projectile_width, self.spiral_projectile_width, self.spiral_projectile_width ) )
ParticleManager:SetParticleControl( ProjectileInfo.nFXIndex, 2, Vector( 6, 6, 6 ) )
--local flSpeedColorFactor = self.flCurSpeed / self.spiral_projectile_speed
--local vColor = LerpVectors( SLOW_COLOR, FAST_COLOR, flSpeedColorFactor )
--ParticleManager:SetParticleControl( ProjectileInfo.nFXIndex, 15, vColor )
table.insert( self.Projectiles, ProjectileInfo )
if self.bReverse then
self.flSpiralYaw = self.flSpiralYaw - self.flSpiralYawStep
else
self.flSpiralYaw = self.flSpiralYaw + self.flSpiralYawStep
end
end
self.flSpiralYaw = self.flSpiralYaw + self.flSpiralYawStep * 0.5
end
-------------------------------------------------------------------------------
function aghanim_shard_attack:ThinkSpiralProjectile( info )
if self:IsChanneling() then
local flNewYaw = 0
if self.bReverse then
flNewYaw = info.flYaw - self.spiral_projectile_rotation_speed
else
flNewYaw = info.flYaw + self.spiral_projectile_rotation_speed
end
info.flYaw = flNewYaw
local Angle = QAngle( 0, flNewYaw, 0 )
local vNewVelocity = ( RotatePosition( Vector( 0, 0, 0 ), Angle, Vector( 1, 0, 0 ) ) ) * self.flCurSpeed
ProjectileManager:UpdateLinearProjectileDirection( info.nHandle, vNewVelocity, 5000 )
end
local vLoc = ProjectileManager:GetLinearProjectileLocation( info.nHandle )
vLoc.z = GetGroundHeight( vLoc, self:GetCaster() ) + 50
info.attachEnt:SetAbsOrigin( vLoc )
--ParticleManager:SetParticleControl( info.nFXIndex, 0, vLoc )
--local flSpeedColorFactor = self.flCurSpeed / self.spiral_projectile_speed
--local vColor = LerpVectors( SLOW_COLOR, FAST_COLOR, flSpeedColorFactor )
--ParticleManager:SetParticleControl( info.nFXIndex, 15, vColor )
--rint( "setting new velocity on spiral projectile" )
end
-------------------------------------------------------------------------------
function aghanim_shard_attack:BeginRebound()
end
-------------------------------------------------------------------------------
function aghanim_shard_attack:ThinkRebound( flInterval )
end
-------------------------------------------------------------------------------
function aghanim_shard_attack:ThinkReboundProjectile( info )
end
-------------------------------------------------------------------------------
function aghanim_shard_attack:BeginJitter()
end
-------------------------------------------------------------------------------
function aghanim_shard_attack:ThinkJitter( flInterval )
end
-------------------------------------------------------------------------------
function aghanim_shard_attack:ThinkJitterProjectile( info )
end
--------------------------------------------------------------------------------
function aghanim_shard_attack:LaunchCrystals( vVel, flDist, flRadius )
local info =
{
Ability = self,
vSpawnOrigin = self:GetCaster():GetAbsOrigin(),
fStartRadius = flRadius,
fEndRadius = flRadius,
vVelocity = vVel,
fDistance = flDist,
Source = self:GetCaster(),
iUnitTargetTeam = DOTA_UNIT_TARGET_TEAM_ENEMY,
iUnitTargetType = DOTA_UNIT_TARGET_HERO + DOTA_UNIT_TARGET_BASIC,
fExpireTime = GameRules:GetGameTime() + 10.0,
}
return ProjectileManager:CreateLinearProjectile( info )
end
-------------------------------------------------------------------------------
function aghanim_shard_attack:OnProjectileThinkHandle( iProjectileHandle )
if IsServer() then
local info = nil
for _,v in pairs ( self.Projectiles ) do
if v.nHandle == iProjectileHandle then
info = v
break
end
end
if info == nil then
return
end
if self.nPattern == PATTERN_SPIRAL then
self:ThinkSpiralProjectile( info )
end
end
end
-------------------------------------------------------------------------------
function aghanim_shard_attack:OnProjectileHitHandle( hTarget, vLocation, iProjectileHandle )
if IsServer() then
local info = nil
for _,v in pairs ( self.Projectiles ) do
if v.nHandle == iProjectileHandle then
info = v
break
end
end
if info == nil then
return false
end
if self.nPattern == PATTERN_SPIRAL then
ParticleManager:DestroyParticle( info.nFXIndex, false )
UTIL_Remove( info.attachEnt )
info.attachEnt = nil
end
if hTarget and not hTarget:IsMagicImmune() and not hTarget:IsInvulnerable() then
local damage =
{
victim = hTarget,
attacker = self:GetCaster(),
damage = self.spiral_projectile_damage,
damage_type = DAMAGE_TYPE_PURE,
ability = self,
}
ApplyDamage( damage )
EmitSoundOn( "Hero_Silencer.LastWord.Damage", hTarget )
local nFXIndex = ParticleManager:CreateParticle( "particles/units/heroes/hero_lich/lich_frost_nova.vpcf", PATTACH_WORLDORIGIN, nil )
ParticleManager:SetParticleControl( nFXIndex, 0, hTarget:GetAbsOrigin() )
ParticleManager:SetParticleControl( nFXIndex, 1, Vector( self.spiral_projectile_width, self.spiral_projectile_width, self.spiral_projectile_width ) )
ParticleManager:ReleaseParticleIndex( nFXIndex )
end
end
return true
end