modifier_TaisonCharge = class({})
function modifier_TaisonCharge:IsHidden()
return false
end
function modifier_TaisonCharge:IsDebuff()
return false
end
function modifier_TaisonCharge:IsPurgable()
return false
end
function modifier_TaisonCharge:OnCreated( kv )
if not IsServer() then return end
self.caster = self:GetCaster()
self.parent = self:GetParent()
self.bonus_ms = self:GetAbility():GetSpecialValueFor( "movement_speed" )
self.radius = self:GetAbility():GetSpecialValueFor( "bash_radius" )
self.duration = self:GetAbility():GetSpecialValueFor( "stun_duration" )
self.target = EntIndexToHScript( kv.target )
self.direction = self.caster:GetForwardVector()
self.targets = {}
self.search_radius = 4000
self.tree_radius = 150
self.min_dist = 150
self.offset = 20
self.interrupted = false
self.mod = self.parent:FindModifierByName( "modifier_none")
if self.mod and self.mod:GetAbility():GetLevel()<1 then
self.mod = nil
end
if not self:ApplyHorizontalMotionController() then
self.interrupted = true
self
estroy()
end
self:SetTarget( self.target )
self:GetAbility():SetActivated( false )
local sound_cast = "Hero_Spirit_Breaker.ChargeOfDarkness"
EmitSoundOn( sound_cast, self.parent )
end
function modifier_TaisonCharge:OnRefresh( kv )
end
function modifier_TaisonCharge:OnRemoved()
end
function modifier_TaisonCharge:OnDestroy()
if not IsServer() then return end
GridNav
estroyTreesAroundPoint( self:GetParent():GetOrigin(), self.tree_radius, true )
self:GetParent():RemoveHorizontalMotionController( self )
if self.debuff and (not self.debuff:IsNull()) then
self.debuff
estroy()
end
self:GetAbility():SetActivated( true )
self:GetAbility():UseResources( false, false, true)
if self.interrupted then return end
self.target:AddNewModifier(
self.parent,
self:GetAbility(),
"modifier_memes_stunned",
{ duration = self.duration }
)
if self.target:IsAlive() then
local order = {
UnitIndex = self.parent:entindex(),
OrderType = DOTA_UNIT_ORDER_ATTACK_TARGET,
TargetIndex = self.target:entindex(),
}
ExecuteOrderFromTable( order )
self.parent:SetAttacking( self.target )
end
local sound_cast = "Hero_Spirit_Breaker.Charge.Impact"
EmitSoundOn( sound_cast, self.target )
end
function modifier_TaisonCharge
eclareFunctions()
local funcs = {
MODIFIER_EVENT_ON_ORDER,
MODIFIER_PROPERTY_MOVESPEED_BONUS_CONSTANT,
MODIFIER_PROPERTY_IGNORE_MOVESPEED_LIMIT,
}
return funcs
end
function modifier_TaisonCharge:OnOrder( params )
if params.unit~=self.parent then return end
if
params.order_type==DOTA_UNIT_ORDER_MOVE_TO_POSITION or
params.order_type==DOTA_UNIT_ORDER_MOVE_TO_TARGET or
params.order_type==DOTA_UNIT_ORDER_ATTACK_TARGET or
params.order_type==DOTA_UNIT_ORDER_STOP or
params.order_type==DOTA_UNIT_ORDER_HOLD_POSITION or
params.order_type==DOTA_UNIT_ORDER_CAST_POSITION or
params.order_type==DOTA_UNIT_ORDER_CAST_TARGET or
params.order_type==DOTA_UNIT_ORDER_CAST_TARGET_TREE or
params.order_type==DOTA_UNIT_ORDER_CAST_RUNE or
params.order_type==DOTA_UNIT_ORDER_VECTOR_TARGET_POSITION
then
self.interrupted = true
self
estroy()
end
end
function modifier_TaisonCharge:GetModifierMoveSpeedBonus_Constant()
return self.bonus_ms
end
function modifier_TaisonCharge:GetModifierIgnoreMovespeedLimit()
return 1
end
function modifier_TaisonCharge:UpdateHorizontalMotion( me, dt )
self:CancelLogic()
local direction = self.target:GetOrigin()-me:GetOrigin()
local dist = direction:Length2D()
direction.z = 0
direction = direction:Normalized()
if dist<self.min_dist then
self
estroy()
return
end
local pos = me:GetOrigin() + direction * me:GetIdealSpeed() * dt
pos = GetGroundPosition( pos,me )
me:SetOrigin( pos )
self.direction = direction
self.parent:FaceTowards( self.target:GetOrigin() )
end
function modifier_TaisonCharge:OnHorizontalMotionInterrupted()
self.interrupted = true
self
estroy()
end
function modifier_TaisonCharge:BashLogic()
if (not self.mod) or self.mod:IsNull() then return end
local loc = self.parent:GetOrigin() + self.direction * self.offset
local enemies = FindUnitsInRadius(
self.parent:GetTeamNumber(),
loc,
nil,
self.radius,
DOTA_UNIT_TARGET_TEAM_ENEMY,
DOTA_UNIT_TARGET_HERO,
DOTA_UNIT_TARGET_FLAG_MAGIC_IMMUNE_ENEMIES,
0,
false
)
for _,enemy in pairs(enemies) do
if not self.targets[enemy] then
self.targets[enemy] = true
self.mod:Bash( enemy, 0, false )
end
end
end
function modifier_TaisonCharge:CancelLogic()
local check = self.parent:IsHexed() or self.parent:IsStunned() or self.parent:IsRooted()
if check then
self.interrupted = true
self
estroy()
end
if not self.target:IsAlive() then
local enemies = FindUnitsInRadius(
self.parent:GetTeamNumber(),
self.target:GetOrigin(),
nil,
self.search_radius,
DOTA_UNIT_TARGET_TEAM_ENEMY,
DOTA_UNIT_TARGET_HERO,
DOTA_UNIT_TARGET_FLAG_MAGIC_IMMUNE_ENEMIES + DOTA_UNIT_TARGET_FLAG_FOW_VISIBLE + DOTA_UNIT_TARGET_FLAG_NO_INVIS,
FIND_CLOSEST,
false
)
if #enemies<1 then
self.interrupted = true
self
estroy()
return
else
self:SetTarget( enemies[1] )
end
end
end
function modifier_TaisonCharge:SetTarget( target )
if self.debuff and (not self.debuff:IsNull()) then
self.debuff
estroy()
end
self.debuff = target:AddNewModifier(
self.parent,
self:GetAbility(),
"modifier_TaisonCharge_debuff",
{}
)
self.target = target
self.targets[target] = true
end
function modifier_TaisonCharge:GetEffectName()
return "particles/units/heroes/hero_spirit_breaker/spirit_breaker_charge.vpcf"
end
function modifier_TaisonCharge:GetEffectAttachType()
return PATTACH_ABSORIGIN_FOLLOW
end