initial commit
This commit is contained in:
@@ -0,0 +1,39 @@
|
||||
|
||||
modifier_aghanim_announcer_passive = class({})
|
||||
|
||||
----------------------------------------
|
||||
|
||||
function modifier_aghanim_announcer_passive:OnCreated( kv )
|
||||
print( "modifier_aghanim_announcer_passive" )
|
||||
end
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
function modifier_aghanim_announcer_passive:IsHidden()
|
||||
return true
|
||||
end
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
function modifier_aghanim_announcer_passive:IsPurgable()
|
||||
return false
|
||||
end
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
function modifier_aghanim_announcer_passive:CheckState()
|
||||
local state = {}
|
||||
if IsServer() then
|
||||
state[ MODIFIER_STATE_INVULNERABLE ] = true
|
||||
state[ MODIFIER_STATE_MAGIC_IMMUNE ] = true
|
||||
state[ MODIFIER_STATE_UNSELECTABLE ] = true
|
||||
state[ MODIFIER_STATE_NOT_ON_MINIMAP ] = true
|
||||
state[ MODIFIER_STATE_NO_UNIT_COLLISION ] = true
|
||||
state[ MODIFIER_STATE_NO_HEALTH_BAR ] = true
|
||||
state[ MODIFIER_STATE_DISARMED ] = true
|
||||
state[ MODIFIER_STATE_ROOTED ] = true
|
||||
state[ MODIFIER_STATE_ATTACK_IMMUNE ] = true
|
||||
end
|
||||
|
||||
return state
|
||||
end
|
||||
@@ -0,0 +1,63 @@
|
||||
modifier_aghanim_crystal_attack_active = class({})
|
||||
|
||||
---------------------------------------------------------------------------
|
||||
|
||||
function modifier_aghanim_crystal_attack_active:GetEffectName()
|
||||
return "particles/creatures/aghanim/aghanim_pulse_ambient.vpcf";
|
||||
end
|
||||
|
||||
---------------------------------------------------------------------------
|
||||
|
||||
function modifier_aghanim_crystal_attack_active:IsPurgable()
|
||||
return false
|
||||
end
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
function modifier_aghanim_crystal_attack_active:OnCreated( kv )
|
||||
self.pulse_radius = self:GetAbility():GetSpecialValueFor( "pulse_radius" )
|
||||
self.pulse_damage = self:GetAbility():GetSpecialValueFor( "pulse_damage" )
|
||||
self.debuff_duration = self:GetAbility():GetSpecialValueFor( "debuff_duration" )
|
||||
self.pulse_damage_pct = self:GetAbility():GetSpecialValueFor( "pulse_damage_pct" )
|
||||
end
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
function modifier_aghanim_crystal_attack_active:Pulse()
|
||||
if IsServer() then
|
||||
|
||||
local nFXIndex = ParticleManager:CreateParticle( "particles/creatures/aghanim/aghanim_self_dmg.vpcf", PATTACH_CUSTOMORIGIN, self:GetParent() )
|
||||
ParticleManager:SetParticleControlEnt( nFXIndex, 0, self:GetParent(), PATTACH_POINT_FOLLOW, "attach_hitloc", self:GetParent():GetAbsOrigin(), true )
|
||||
ParticleManager:SetParticleControlEnt( nFXIndex, 1, self:GetParent(), PATTACH_ABSORIGIN_FOLLOW, nil, self:GetParent():GetAbsOrigin(), true )
|
||||
ParticleManager:SetParticleControl( nFXIndex, 2, Vector( self.pulse_radius, self.pulse_radius, self.pulse_radius ) )
|
||||
|
||||
EmitSoundOn( "Hero_Lich.IceAge.Tick", self:GetParent() )
|
||||
|
||||
local enemies = FindUnitsInRadius( self:GetCaster():GetTeamNumber(), self:GetParent():GetAbsOrigin(), nil, self.pulse_radius, DOTA_UNIT_TARGET_TEAM_ENEMY, DOTA_UNIT_TARGET_HERO + DOTA_UNIT_TARGET_BASIC + DOTA_UNIT_TARGET_BUILDING, DOTA_UNIT_TARGET_FLAG_MAGIC_IMMUNE_ENEMIES, FIND_CLOSEST, false )
|
||||
for _,enemy in pairs( enemies ) do
|
||||
if enemy ~= nil and enemy:IsInvulnerable() == false and enemy:IsAttackImmune() == false then
|
||||
|
||||
enemy:AddNewModifier( self:GetCaster(), self:GetAbility(), "modifier_aghanim_crystal_attack_debuff", { duration = self.debuff_duration } )
|
||||
|
||||
local flDamage = enemy:GetMaxHealth() * self.pulse_damage_pct / 100
|
||||
|
||||
local damage =
|
||||
{
|
||||
victim = enemy,
|
||||
attacker = self:GetCaster(),
|
||||
damage = flDamage,
|
||||
damage_type = DAMAGE_TYPE_PHYSICAL,
|
||||
ability = self:GetAbility(),
|
||||
}
|
||||
|
||||
ApplyDamage( damage )
|
||||
|
||||
|
||||
local nFXIndex2 = ParticleManager:CreateParticle( "particles/creatures/aghanim/aghanim_pulse_nova.vpcf", PATTACH_ABSORIGIN_FOLLOW, enemy )
|
||||
ParticleManager:ReleaseParticleIndex( nFXIndex2 )
|
||||
|
||||
EmitSoundOn( "Hero_Leshrac.Pulse_Nova_Strike", enemy )
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -0,0 +1,81 @@
|
||||
modifier_aghanim_crystal_attack_debuff = class({})
|
||||
|
||||
|
||||
function modifier_aghanim_crystal_attack_debuff:GetAttributes()
|
||||
return MODIFIER_ATTRIBUTE_MULTIPLE
|
||||
end
|
||||
|
||||
|
||||
---------------------------------------------------------------------------
|
||||
|
||||
function modifier_aghanim_crystal_attack_debuff:IsPurgable()
|
||||
return false
|
||||
end
|
||||
|
||||
|
||||
---------------------------------------------------------------------------
|
||||
|
||||
function modifier_aghanim_crystal_attack_debuff:GetEffectName()
|
||||
return "particles/units/heroes/hero_ancient_apparition/ancient_apparition_ice_blast_debuff.vpcf";
|
||||
end
|
||||
|
||||
---------------------------------------------------------------------------
|
||||
|
||||
function modifier_aghanim_crystal_attack_debuff:GetStatusEffectName()
|
||||
return "particles/status_fx/status_effect_iceblast.vpcf";
|
||||
end
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
function modifier_aghanim_crystal_attack_debuff:OnCreated( kv )
|
||||
self.heal_suppression_pct = self:GetAbility():GetSpecialValueFor( "heal_suppression_pct" )
|
||||
self.nArmorReductionPerStack = math.max( math.floor( self:GetAbility():GetSpecialValueFor( "armor_reduction_pct" ) * self:GetParent():GetPhysicalArmorValue( false ) / 100 ), 1 )
|
||||
end
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
function modifier_aghanim_crystal_attack_debuff:DeclareFunctions()
|
||||
local funcs =
|
||||
{
|
||||
MODIFIER_PROPERTY_LIFESTEAL_AMPLIFY_PERCENTAGE,
|
||||
MODIFIER_PROPERTY_SPELL_LIFESTEAL_AMPLIFY_PERCENTAGE,
|
||||
MODIFIER_PROPERTY_HP_REGEN_AMPLIFY_PERCENTAGE,
|
||||
MODIFIER_PROPERTY_HEAL_AMPLIFY_PERCENTAGE_TARGET,
|
||||
MODIFIER_PROPERTY_PHYSICAL_ARMOR_BONUS,
|
||||
|
||||
}
|
||||
return funcs
|
||||
end
|
||||
-----------------------------------------------------------------------------------------
|
||||
|
||||
function modifier_aghanim_crystal_attack_debuff:GetModifierPhysicalArmorBonus()
|
||||
if self.nArmorReductionPerStack == nil then
|
||||
return 0
|
||||
end
|
||||
|
||||
return self.nArmorReductionPerStack * -1
|
||||
end
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
function modifier_aghanim_crystal_attack_debuff:GetModifierHealAmplify_PercentageTarget( params )
|
||||
return -self.heal_suppression_pct
|
||||
end
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
function modifier_aghanim_crystal_attack_debuff:GetModifierHPRegenAmplify_Percentage( params )
|
||||
return -self.heal_suppression_pct
|
||||
end
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
function modifier_aghanim_crystal_attack_debuff:GetModifierLifestealRegenAmplify_Percentage( params )
|
||||
return -self.heal_suppression_pct
|
||||
end
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
function modifier_aghanim_crystal_attack_debuff:GetModifierSpellLifestealRegenAmplify_Percentage( params )
|
||||
return -self.heal_suppression_pct
|
||||
end
|
||||
@@ -0,0 +1,230 @@
|
||||
|
||||
modifier_aghanim_passive = class({})
|
||||
|
||||
-----------------------------------------------------------------------------------------
|
||||
|
||||
function modifier_aghanim_passive:IsHidden()
|
||||
return true
|
||||
end
|
||||
|
||||
-----------------------------------------------------------------------------------------
|
||||
|
||||
function modifier_aghanim_passive:IsPurgable()
|
||||
return false
|
||||
end
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
function modifier_aghanim_passive:GetPriority()
|
||||
return MODIFIER_PRIORITY_ULTRA + 10000
|
||||
end
|
||||
|
||||
-----------------------------------------------------------------------------------------
|
||||
|
||||
function modifier_aghanim_passive:CheckState()
|
||||
local state =
|
||||
{
|
||||
[MODIFIER_STATE_HEXED] = false,
|
||||
[MODIFIER_STATE_ROOTED] = false,
|
||||
[MODIFIER_STATE_SILENCED] = false,
|
||||
[MODIFIER_STATE_STUNNED] = false,
|
||||
[MODIFIER_STATE_FROZEN] = false,
|
||||
[MODIFIER_STATE_FEARED] = false,
|
||||
[MODIFIER_STATE_CANNOT_BE_MOTION_CONTROLLED] = true,
|
||||
[MODIFIER_STATE_NO_HEALTH_BAR] = true,
|
||||
}
|
||||
|
||||
if IsServer() then
|
||||
if self:GetParent() and self:GetParent().AI and self:GetParent().AI.bDefeated == true then
|
||||
state[MODIFIER_STATE_INVULNERABLE] = true
|
||||
end
|
||||
end
|
||||
|
||||
return state
|
||||
end
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
function modifier_aghanim_passive:OnCreated( kv )
|
||||
self.status_resist = self:GetAbility():GetSpecialValueFor( "status_resist" )
|
||||
if IsServer() then
|
||||
self:GetParent().bAbsoluteNoCC = true
|
||||
self:GetParent().bNoNullifier = true
|
||||
end
|
||||
end
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
function modifier_aghanim_passive:OnRefresh( kv )
|
||||
self.status_resist = self:GetAbility():GetSpecialValueFor( "status_resist" )
|
||||
end
|
||||
|
||||
-----------------------------------------------------------------------------------------
|
||||
|
||||
function modifier_aghanim_passive:DeclareFunctions()
|
||||
local funcs =
|
||||
{
|
||||
MODIFIER_PROPERTY_MIN_HEALTH,
|
||||
MODIFIER_EVENT_ON_DEATH_PREVENTED,
|
||||
MODIFIER_PROPERTY_STATUS_RESISTANCE_STACKING,
|
||||
}
|
||||
return funcs
|
||||
end
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
function modifier_aghanim_passive:GetModifierStatusResistanceStacking( params )
|
||||
return self.status_resist
|
||||
end
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
function modifier_aghanim_passive:GetMinHealth( params )
|
||||
if IsServer() then
|
||||
if GameRules.Aghanim:GetAscensionLevel() < 3 then
|
||||
return math.floor( self:GetParent():GetMaxHealth() * 0.1 )
|
||||
end
|
||||
end
|
||||
return 1
|
||||
end
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
function modifier_aghanim_passive:OnDeathPrevented( params )
|
||||
if IsServer() then
|
||||
if self:GetParent() == params.unit and self:GetParent().AI and self:GetParent().AI.Encounter and self:GetParent().AI.bDefeated == false then
|
||||
print( "Game Over - Players win! Play Aghanim Victory Sequence" )
|
||||
for nPlayerID = 0,AGHANIM_PLAYERS-1 do
|
||||
local hPlayerHero = PlayerResource:GetSelectedHeroEntity( nPlayerID )
|
||||
if hPlayerHero then
|
||||
hPlayerHero:AddNewModifier( self:GetCaster(), self:GetAbility(), "modifier_invulnerable", { duration = -1 } )
|
||||
end
|
||||
end
|
||||
|
||||
local Angles = self:GetParent():GetAnglesAsVector()
|
||||
CustomGameEventManager:Send_ServerToAllClients( "begin_aghanim_victory", { ent_index = self:GetParent():entindex(), yaw = Angles.y } )
|
||||
|
||||
self:GetParent().AI.bDefeated = true
|
||||
self:GetParent():Interrupt()
|
||||
self:GetParent():InterruptChannel()
|
||||
self:GetParent():Purge( false, true, false, true, true )
|
||||
--self:GetParent():SetAbsAngles( 0, 270, 0 )
|
||||
self:GetParent().AI.Encounter:BeginVictorySequence()
|
||||
|
||||
EmitSoundOn( "Aghanim.ShardAttack.Channel", self:GetCaster() )
|
||||
if GameRules.Aghanim:GetAscensionLevel() < 3 then
|
||||
self:GetParent():StartGestureFadeWithSequenceSettings( ACT_DOTA_CAST_ABILITY_3 )
|
||||
else
|
||||
self:GetParent():StartGestureFadeWithSequenceSettings( ACT_DOTA_SPAWN )
|
||||
end
|
||||
self.nOutroPhase = 1
|
||||
self:StartIntervalThink( 2.0 )
|
||||
end
|
||||
end
|
||||
return 0
|
||||
end
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
function modifier_aghanim_passive:OnIntervalThink()
|
||||
if IsServer() then
|
||||
|
||||
if self.nOutroPhase == 1 then
|
||||
if GameRules.Aghanim:GetAscensionLevel() < 3 then
|
||||
EmitSoundOn( "Aghanim.ShardAttack.Wave", self:GetCaster() )
|
||||
local nFXIndex = ParticleManager:CreateParticle( "particles/creatures/aghanim/aghanim_self_dmg.vpcf", PATTACH_CUSTOMORIGIN, self:GetParent() )
|
||||
ParticleManager:SetParticleControlEnt( nFXIndex, 0, self:GetParent(), PATTACH_POINT_FOLLOW, "attach_hitloc", self:GetParent():GetAbsOrigin(), true )
|
||||
ParticleManager:SetParticleControlEnt( nFXIndex, 1, self:GetParent(), PATTACH_ABSORIGIN_FOLLOW, nil, self:GetParent():GetAbsOrigin(), true )
|
||||
ParticleManager:SetParticleControl( nFXIndex, 2, Vector( 2500, 2500, 2500 ) )
|
||||
|
||||
for nPlayerID = 0,AGHANIM_PLAYERS-1 do
|
||||
local hPlayerHero = PlayerResource:GetSelectedHeroEntity( nPlayerID )
|
||||
if hPlayerHero then
|
||||
hPlayerHero:RemoveModifierByName( "modifier_invulnerable" )
|
||||
hPlayerHero:AddNewModifier( self:GetCaster(), self:GetAbility(), "modifier_aghanim_crystal_attack_debuff", { duration = -1 } )
|
||||
hPlayerHero:AddNewModifier( self:GetCaster(), self:GetAbility(), "modifier_stunned", { duration = -1 } )
|
||||
hPlayerHero:AddNewModifier( self:GetCaster(), self:GetAbility(), "modifier_invulnerable", { duration = -1 } )
|
||||
|
||||
local nFXIndex2 = ParticleManager:CreateParticle( "particles/creatures/aghanim/aghanim_pulse_nova.vpcf", PATTACH_ABSORIGIN_FOLLOW, hPlayerHero )
|
||||
ParticleManager:ReleaseParticleIndex( nFXIndex2 )
|
||||
EmitSoundOn( "Hero_Leshrac.Pulse_Nova_Strike", hPlayerHero )
|
||||
end
|
||||
end
|
||||
self:GetParent():FadeGesture( ACT_DOTA_CAST_ABILITY_3 )
|
||||
else
|
||||
for nPlayerID = 0,AGHANIM_PLAYERS-1 do
|
||||
local hPlayerHero = PlayerResource:GetSelectedHeroEntity( nPlayerID )
|
||||
if hPlayerHero then
|
||||
hPlayerHero:AddNewModifier( self:GetCaster(), self:GetAbility(), "modifier_boss_intro", { duration = -1 } )
|
||||
end
|
||||
end
|
||||
|
||||
self:GetParent():FadeGesture( ACT_DOTA_SPAWN )
|
||||
end
|
||||
|
||||
local AlliedUnits = FindUnitsInRadius( self:GetParent():GetTeamNumber(), self:GetParent():GetAbsOrigin(), nil, FIND_UNITS_EVERYWHERE, DOTA_UNIT_TARGET_TEAM_FRIENDLY, DOTA_UNIT_TARGET_HERO + DOTA_UNIT_TARGET_BASIC + DOTA_UNIT_TARGET_BUILDING, DOTA_UNIT_TARGET_FLAG_MAGIC_IMMUNE_ENEMIES, FIND_CLOSEST, false )
|
||||
for _,Ally in pairs( AlliedUnits ) do
|
||||
if Ally:GetUnitName() == "npc_dota_boss_aghanim_crystal" or Ally:GetUnitName() == "npc_dota_boss_aghanim_minion" or Ally:GetUnitName() == "npc_dota_thinker" or Ally:GetUnitName() == "npc_dota_boss_aghanim_spear" then
|
||||
Ally:ForceKill( false )
|
||||
end
|
||||
end
|
||||
|
||||
self.nOutroPhase = self.nOutroPhase + 1
|
||||
self:StartIntervalThink( 2.0 )
|
||||
self:GetParent():FadeGesture( ACT_DOTA_CAST_ABILITY_3 )
|
||||
self:GetParent():StartGestureFadeWithSequenceSettings( ACT_DOTA_VICTORY )
|
||||
return
|
||||
end
|
||||
|
||||
if self.nOutroPhase == 2 then
|
||||
self.nPortalFX = ParticleManager:CreateParticle( "particles/creatures/aghanim/portal_summon.vpcf", PATTACH_CUSTOMORIGIN, nil )
|
||||
ParticleManager:SetParticleControl( self.nPortalFX, 0, self:GetParent():GetAbsOrigin() )
|
||||
ParticleManager:SetParticleControlForward( self.nPortalFX, 0, self:GetParent():GetForwardVector() )
|
||||
|
||||
self.nOutroPhase = self.nOutroPhase + 1
|
||||
self:StartIntervalThink( 0.1 )
|
||||
return
|
||||
end
|
||||
|
||||
if self.nOutroPhase == 3 then
|
||||
if self:GetParent().Encounter and self:GetParent().Encounter.nVictoryState ~= self:GetParent().Encounter.AGH_VICTORY_BOWING then
|
||||
return
|
||||
end
|
||||
|
||||
EmitSoundOn( "SeasonalConsumable.TI10.Portal.Open", self:GetParent() )
|
||||
EmitSoundOn( "SeasonalConsumable.TI10.Portal.Loop", self:GetParent() )
|
||||
|
||||
local nFXIndex = ParticleManager:CreateParticle( "particles/creatures/aghanim/aghanim_outro_linger.vpcf", PATTACH_CUSTOMORIGIN, nil )
|
||||
ParticleManager:SetParticleControl( nFXIndex, 0, self:GetParent():GetAbsOrigin() )
|
||||
ParticleManager:SetParticleControlForward( nFXIndex, 0, self:GetParent():GetForwardVector() )
|
||||
|
||||
self:GetParent():FadeGesture( ACT_DOTA_VICTORY )
|
||||
self:GetParent():StartGestureFadeWithSequenceSettings( ACT_DOTA_DIE )
|
||||
self.nOutroPhase = self.nOutroPhase + 1
|
||||
self:StartIntervalThink( 5.67 )
|
||||
return
|
||||
end
|
||||
|
||||
if self.nOutroPhase == 4 then
|
||||
self:GetParent().bOutroComplete = true
|
||||
ParticleManager:DestroyParticle( self.nPortalFX, false )
|
||||
|
||||
StopSoundOn( "SeasonalConsumable.TI10.Portal.Open", self:GetParent() )
|
||||
StopSoundOn( "SeasonalConsumable.TI10.Portal.Loop", self:GetParent() )
|
||||
|
||||
self:StartIntervalThink( -1 )
|
||||
self:GetParent():AddEffects( EF_NODRAW )
|
||||
|
||||
for nPlayerID = 0,AGHANIM_PLAYERS-1 do
|
||||
local hPlayerHero = PlayerResource:GetSelectedHeroEntity( nPlayerID )
|
||||
if hPlayerHero then
|
||||
hPlayerHero:RemoveModifierByName( "modifier_stunned" )
|
||||
hPlayerHero:RemoveModifierByName( "modifier_aghanim_crystal_attack_debuff" )
|
||||
hPlayerHero:StartGestureFadeWithSequenceSettings( ACT_DOTA_VICTORY )
|
||||
end
|
||||
end
|
||||
return
|
||||
end
|
||||
|
||||
end
|
||||
end
|
||||
@@ -0,0 +1,79 @@
|
||||
modifier_aghanim_portal_spawn_effect = class({})
|
||||
|
||||
---------------------------------------------------------------------------
|
||||
|
||||
function modifier_aghanim_portal_spawn_effect:IsHidden()
|
||||
return true
|
||||
end
|
||||
|
||||
---------------------------------------------------------------------------
|
||||
|
||||
function modifier_aghanim_portal_spawn_effect:IsPurgable()
|
||||
return false
|
||||
end
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
function modifier_aghanim_portal_spawn_effect:OnCreated( kv )
|
||||
if IsServer() then
|
||||
self:StartIntervalThink( 1.0 )
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
function modifier_aghanim_portal_spawn_effect:OnIntervalThink()
|
||||
if IsServer() then
|
||||
self:GetParent():RemoveEffects( EF_NODRAW )
|
||||
self:StartIntervalThink( -1 )
|
||||
end
|
||||
end
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
function modifier_aghanim_portal_spawn_effect:GetPriority()
|
||||
return MODIFIER_PRIORITY_ULTRA + 20000
|
||||
end
|
||||
|
||||
---------------------------------------------------------------------------
|
||||
|
||||
function modifier_aghanim_portal_spawn_effect:GetEffectName()
|
||||
return "particles/units/heroes/hero_pugna/pugna_decrepify.vpcf"
|
||||
end
|
||||
|
||||
---------------------------------------------------------------------------
|
||||
|
||||
function modifier_aghanim_portal_spawn_effect:GetStatusEffectName()
|
||||
return "particles/status_fx/status_effect_ghost.vpcf"
|
||||
end
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
function modifier_aghanim_portal_spawn_effect:DeclareFunctions()
|
||||
local funcs =
|
||||
{
|
||||
MODIFIER_PROPERTY_MODEL_SCALE,
|
||||
}
|
||||
return funcs
|
||||
end
|
||||
|
||||
---------------------------------------------------------------------------
|
||||
|
||||
function modifier_aghanim_portal_spawn_effect:GetModifierModelScale( params )
|
||||
return ( self:GetElapsedTime() / self:GetDuration() - 1.0 ) * 100
|
||||
end
|
||||
|
||||
---------------------------------------------------------------------------
|
||||
|
||||
function modifier_aghanim_portal_spawn_effect:CheckState()
|
||||
local state =
|
||||
{
|
||||
[MODIFIER_STATE_INVULNERABLE] = true,
|
||||
[MODIFIER_STATE_NO_HEALTH_BAR] = true,
|
||||
[MODIFIER_STATE_UNSELECTABLE] = true,
|
||||
[MODIFIER_STATE_STUNNED] = true,
|
||||
[MODIFIER_STATE_NO_UNIT_COLLISION] = true,
|
||||
}
|
||||
return state
|
||||
end
|
||||
@@ -0,0 +1,166 @@
|
||||
modifier_aghanim_spell_swap = class({})
|
||||
|
||||
---------------------------------------------------------------------------
|
||||
|
||||
function modifier_aghanim_spell_swap:IsHidden()
|
||||
return false
|
||||
end
|
||||
|
||||
---------------------------------------------------------------------------
|
||||
|
||||
function modifier_aghanim_spell_swap:IsPurgable()
|
||||
return false
|
||||
end
|
||||
|
||||
-----------------------------------------------------------------------------------------
|
||||
|
||||
function modifier_aghanim_spell_swap:GetAttributes()
|
||||
return MODIFIER_ATTRIBUTE_MULTIPLE
|
||||
end
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
function modifier_aghanim_spell_swap:OnCreated( kv )
|
||||
if IsServer() then
|
||||
self:DisableSpell()
|
||||
end
|
||||
end
|
||||
|
||||
----------------------------------------------------------------------------------
|
||||
|
||||
function modifier_aghanim_spell_swap:DeclareFunctions()
|
||||
local funcs =
|
||||
{
|
||||
MODIFIER_EVENT_ON_DEATH,
|
||||
}
|
||||
|
||||
return funcs
|
||||
end
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
|
||||
function modifier_aghanim_spell_swap:OnDeath( params )
|
||||
if IsServer() then
|
||||
if params.unit == self.hCrystal then
|
||||
self:Destroy()
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
function modifier_aghanim_spell_swap:DisableSpell()
|
||||
if IsServer() then
|
||||
local NormalAbilities = {}
|
||||
for i=0,DOTA_MAX_ABILITIES-1 do
|
||||
local hAbility = self:GetParent():GetAbilityByIndex( i )
|
||||
if hAbility and not hAbility:IsCosmetic( nil ) and not hAbility:IsAttributeBonus() and hAbility:GetAssociatedPrimaryAbilities() == nil and not hAbility:IsHidden() and not hAbility.bAghDisabled == true and not hAbility.bAghDummy == true and hAbility:IsActivated() then
|
||||
print( "considering ability for disable: " .. hAbility:GetAbilityName() )
|
||||
table.insert( NormalAbilities, hAbility )
|
||||
end
|
||||
end
|
||||
|
||||
local nNextAghDummy = nil
|
||||
for j=1,4 do
|
||||
local szName = tostring( "aghanim_empty_spell" .. j )
|
||||
local hDummyAbility = self:GetParent():FindAbilityByName( szName )
|
||||
nNextAghDummy = j
|
||||
if not hDummyAbility then
|
||||
break
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
local nIndexToDisable = math.random( 1, #NormalAbilities )
|
||||
local hAbilityToDisable = NormalAbilities[ nIndexToDisable ]
|
||||
|
||||
if nNextAghDummy == nil or hAbilityToDisable == nil then
|
||||
self:Destroy()
|
||||
print( "Cannot disable spell:" )
|
||||
print( "Next agh dummy: " .. nNextAghDummy )
|
||||
if hAbilityToDisable ~= nil then
|
||||
print( "hAbilityToDisable " .. hAbilityToDisable:GetAbilityName() )
|
||||
end
|
||||
return
|
||||
end
|
||||
|
||||
local hNewDummyAbility = self:GetParent():AddAbility( tostring( "aghanim_empty_spell" .. nNextAghDummy ) )
|
||||
if hNewDummyAbility then
|
||||
print( "adding dummy ability for disable: " .. hNewDummyAbility:GetAbilityName() )
|
||||
hNewDummyAbility:UpgradeAbility( true )
|
||||
hNewDummyAbility:SetActivated( true )
|
||||
hNewDummyAbility.bAghDummy = true
|
||||
hNewDummyAbility.nOriginalIndex = hNewDummyAbility:GetAbilityIndex()
|
||||
end
|
||||
|
||||
|
||||
hAbilityToDisable.bAghDisabled = true
|
||||
print( "disabling " .. hAbilityToDisable:GetAbilityName() )
|
||||
if hAbilityToDisable:GetToggleState() then
|
||||
--print( "toggling ability off" )
|
||||
hAbilityToDisable:OnToggle()
|
||||
end
|
||||
|
||||
hAbilityToDisable:SetActivated( false )
|
||||
hAbilityToDisable.nOriginalIndex = hAbilityToDisable:GetAbilityIndex()
|
||||
|
||||
self.hDisabledAbility = hAbilityToDisable
|
||||
self.hDummyAbility = hNewDummyAbility
|
||||
|
||||
self:GetParent():SwapAbilities( self.hDisabledAbility:GetAbilityName(), self.hDummyAbility:GetAbilityName(), false, true )
|
||||
self.hDummyAbility:SetActivated( false )
|
||||
|
||||
--self.hDisabledAbility:SetAbilityIndex( self.hDummyAbility.nOriginalIndex )
|
||||
--self.hDisabledAbility:SetHidden( true )
|
||||
--self.hDummyAbility:SetAbilityIndex( self.hDisabledAbility.nOriginalIndex )
|
||||
--self.hDummyAbility:SetHidden( false )
|
||||
|
||||
self.hCrystal = CreateUnitByName( "npc_dota_boss_aghanim_crystal", self:GetCaster():GetAbsOrigin(), true, self:GetCaster(), self:GetCaster():GetOwner(), self:GetCaster():GetTeamNumber() )
|
||||
if self.hCrystal then
|
||||
self.hCrystal:SetControllableByPlayer( self:GetCaster():GetPlayerOwnerID(), false )
|
||||
self.hCrystal:SetOwner( self:GetCaster() )
|
||||
self.hCrystal:AddNewModifier( self:GetCaster(), self:GetAbility(), "modifier_aghanim_spell_swap_crystal", {} )
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
function modifier_aghanim_spell_swap:RestoreSpell()
|
||||
if IsServer() then
|
||||
if self.hDisabledAbility and self.hDummyAbility then
|
||||
self.hDisabledAbility:SetActivated( true )
|
||||
self.hDisabledAbility.bAghDisabled = false
|
||||
self.hDisabledAbility:SetHidden( false )
|
||||
self:GetParent():RemoveAbilityFromIndexByName( self.hDisabledAbility:GetAbilityName() )
|
||||
self:GetParent():SetAbilityByIndex( self.hDisabledAbility, self.hDisabledAbility.nOriginalIndex ) -- this destroys the dummy spell
|
||||
|
||||
if self.hCrystal then
|
||||
self.hCrystal:AddEffects( EF_NODRAW )
|
||||
if self.hCrystal:IsAlive() then
|
||||
self.hCrystal:ForceKill( false )
|
||||
end
|
||||
|
||||
local nFXIndex = ParticleManager:CreateParticle( "particles/creatures/aghanim/aghanim_crystal_destroy.vpcf", PATTACH_CUSTOMORIGIN, nil )
|
||||
ParticleManager:SetParticleControl( nFXIndex, 0, self.hCrystal:GetAbsOrigin() )
|
||||
ParticleManager:ReleaseParticleIndex( nFXIndex )
|
||||
|
||||
EmitSoundOn( "Hero_Wisp.Spirits.Destroy", self.hCrystal )
|
||||
|
||||
local nFXIndex2 = ParticleManager:CreateParticle( "particles/creatures/aghanim/aghanim_crystal_spellswap_replenish.vpcf", PATTACH_CUSTOMORIGIN, nil )
|
||||
ParticleManager:SetParticleControlEnt( nFXIndex2, 0, self.hCrystal, PATTACH_POINT_FOLLOW, "attach_attack1", self.hCrystal:GetAbsOrigin(), true )
|
||||
ParticleManager:SetParticleControlEnt( nFXIndex2, 1, self:GetParent(), PATTACH_POINT_FOLLOW, "attach_hitloc", self:GetParent():GetAbsOrigin(), true )
|
||||
ParticleManager:ReleaseParticleIndex( nFXIndex2 )
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
function modifier_aghanim_spell_swap:OnDestroy()
|
||||
if IsServer() then
|
||||
self:RestoreSpell()
|
||||
end
|
||||
end
|
||||
@@ -0,0 +1,181 @@
|
||||
modifier_aghanim_spell_swap_crystal = class({})
|
||||
|
||||
---------------------------------------------------------------------------
|
||||
|
||||
function modifier_aghanim_spell_swap_crystal:IsHidden()
|
||||
return true
|
||||
end
|
||||
|
||||
---------------------------------------------------------------------------
|
||||
|
||||
function modifier_aghanim_spell_swap_crystal:IsPurgable()
|
||||
return false
|
||||
end
|
||||
|
||||
---------------------------------------------------------------------------
|
||||
|
||||
function modifier_aghanim_spell_swap_crystal:GetEffectName()
|
||||
return "particles/creatures/aghanim/aghanim_crystal_spellswap_ambient.vpcf"
|
||||
end
|
||||
|
||||
----------------------------------------------------------------------------------
|
||||
|
||||
function modifier_aghanim_spell_swap_crystal:DeclareFunctions()
|
||||
local funcs =
|
||||
{
|
||||
MODIFIER_PROPERTY_ABSOLUTE_NO_DAMAGE_PHYSICAL,
|
||||
MODIFIER_PROPERTY_ABSOLUTE_NO_DAMAGE_MAGICAL,
|
||||
MODIFIER_PROPERTY_ABSOLUTE_NO_DAMAGE_PURE,
|
||||
MODIFIER_EVENT_ON_ATTACKED,
|
||||
}
|
||||
|
||||
return funcs
|
||||
end
|
||||
|
||||
----------------------------------------------------------------------------------
|
||||
|
||||
function modifier_aghanim_spell_swap_crystal:CheckState()
|
||||
local state =
|
||||
{
|
||||
[MODIFIER_STATE_MAGIC_IMMUNE] = true,
|
||||
[MODIFIER_STATE_FLYING] = true,
|
||||
}
|
||||
return state
|
||||
end
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
function modifier_aghanim_spell_swap_crystal:OnCreated( kv )
|
||||
if IsServer() then
|
||||
self.num_crystal_hits = self:GetAbility():GetSpecialValueFor( "num_crystal_hits" )
|
||||
|
||||
self:GetParent():SetBaseMaxHealth( self.num_crystal_hits * 2 )
|
||||
self:GetParent():SetMaxHealth( self.num_crystal_hits * 2 )
|
||||
self:GetParent():SetHealth( self.num_crystal_hits * 2 )
|
||||
|
||||
self.flRotationTime = 12.0
|
||||
self.flRotationDist = 300.0
|
||||
self.flHeight = RandomFloat( 120.0, 180.0 )
|
||||
self.flRotation = RandomFloat( 0, 360 )
|
||||
self.flRecoverTime = -1
|
||||
|
||||
self:StartIntervalThink( 0.25 )
|
||||
|
||||
if self:ApplyHorizontalMotionController() == false or self:ApplyVerticalMotionController() == false then
|
||||
self:Destroy()
|
||||
return
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
function modifier_aghanim_spell_swap_crystal:OnIntervalThink()
|
||||
if IsServer() then
|
||||
if GameRules:GetGameTime() > self.flRecoverTime then
|
||||
self.flRotationTime = 12.0
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
function modifier_aghanim_spell_swap_crystal:OnDestroy()
|
||||
if IsServer() then
|
||||
self:GetParent():RemoveHorizontalMotionController( self )
|
||||
self:GetParent():RemoveVerticalMotionController( self )
|
||||
end
|
||||
end
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
function modifier_aghanim_spell_swap_crystal:UpdateHorizontalMotion( me, dt )
|
||||
if IsServer() then
|
||||
self.flRotation = self.flRotation + ( 2.0 * dt * math.pi / self.flRotationTime )
|
||||
local flX = self.flRotationDist * math.sin( self.flRotation )
|
||||
local flY = self.flRotationDist * math.cos( self.flRotation )
|
||||
if self:GetCaster() and self:GetParent() then
|
||||
local vNewLocation = self:GetCaster():GetAbsOrigin() + Vector( flX, flY, self:GetParent():GetAbsOrigin().z )
|
||||
me:SetOrigin( vNewLocation )
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
function modifier_aghanim_spell_swap_crystal:OnHorizontalMotionInterrupted()
|
||||
if IsServer() then
|
||||
self:Destroy()
|
||||
end
|
||||
end
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
function modifier_aghanim_spell_swap_crystal:UpdateVerticalMotion( me, dt )
|
||||
if IsServer() then
|
||||
local flHeight = GetGroundHeight( self:GetParent():GetAbsOrigin(), self:GetParent() ) + self.flHeight
|
||||
local vNewLocation = self:GetParent():GetAbsOrigin()
|
||||
vNewLocation.z = flHeight
|
||||
me:SetOrigin( vNewLocation )
|
||||
end
|
||||
end
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
function modifier_aghanim_spell_swap_crystal:OnVerticalMotionInterrupted()
|
||||
if IsServer() then
|
||||
self:Destroy()
|
||||
end
|
||||
end
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
function modifier_aghanim_spell_swap_crystal:GetAbsoluteNoDamagePhysical( params )
|
||||
return 1
|
||||
end
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
function modifier_aghanim_spell_swap_crystal:GetAbsoluteNoDamageMagical( params )
|
||||
return 1
|
||||
end
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
function modifier_aghanim_spell_swap_crystal:GetAbsoluteNoDamagePure( params )
|
||||
return 1
|
||||
end
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
function modifier_aghanim_spell_swap_crystal:OnAttacked( params )
|
||||
if IsServer() then
|
||||
if self:GetParent() == params.target then
|
||||
local nDamage = 0
|
||||
if params.attacker then
|
||||
local bDeathWard = params.attacker:FindModifierByName( "modifier_aghsfort_witch_doctor_death_ward" ) ~= nil
|
||||
local bValidAttacker = params.attacker:IsRealHero() or bDeathWard
|
||||
if not bValidAttacker then
|
||||
return 0
|
||||
end
|
||||
|
||||
nDamage = 2
|
||||
if params.attacker:FindModifierByName( "modifier_aghsfort_snapfire_lil_shredder_buff" ) or bDeathWard then
|
||||
nDamage = 1
|
||||
end
|
||||
|
||||
self.flRotationTime = 36.0
|
||||
self.flRecoverTime = GameRules:GetGameTime() + 1.0
|
||||
self:GetParent():ModifyHealth( self:GetParent():GetHealth() - nDamage, nil, true, 0 )
|
||||
|
||||
EmitSoundOn( "Hero_Wisp.Spirits.Target", self:GetParent() )
|
||||
|
||||
local nFXIndex = ParticleManager:CreateParticle( "particles/creatures/aghanim/aghanim_crystal_impact.vpcf", PATTACH_CUSTOMORIGIN, self:GetParent() )
|
||||
ParticleManager:SetParticleControlEnt( nFXIndex, 0, self:GetParent(), PATTACH_POINT_FOLLOW, "attach_hitloc", self:GetParent():GetAbsOrigin(), false )
|
||||
ParticleManager:ReleaseParticleIndex( nFXIndex )
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
return 0
|
||||
end
|
||||
@@ -0,0 +1,55 @@
|
||||
|
||||
modifier_aghanim_staff_beams_debuff = class({})
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
function modifier_aghanim_staff_beams_debuff:IsHidden()
|
||||
return true
|
||||
end
|
||||
|
||||
|
||||
-----------------------------------------------------------------------------
|
||||
|
||||
function modifier_aghanim_staff_beams_debuff:OnCreated( kv )
|
||||
if IsServer() then
|
||||
self.beam_dps = self:GetAbility():GetSpecialValueFor( "beam_dps" )
|
||||
self.beam_dps_pct = self:GetAbility():GetSpecialValueFor( "beam_dps_pct" )
|
||||
self.damage_interval = self:GetAbility():GetSpecialValueFor( "damage_interval" )
|
||||
self:OnIntervalThink()
|
||||
self:StartIntervalThink( self.damage_interval )
|
||||
|
||||
EmitSoundOn( "Hero_Huskar.Burning_Spear", self:GetParent() )
|
||||
end
|
||||
end
|
||||
|
||||
-----------------------------------------------------------------------------
|
||||
|
||||
function modifier_aghanim_staff_beams_debuff:OnDestroy()
|
||||
if IsServer() then
|
||||
StopSoundOn( "Hero_Huskar.Burning_Spear", self:GetParent() )
|
||||
end
|
||||
end
|
||||
|
||||
-----------------------------------------------------------------------------
|
||||
|
||||
function modifier_aghanim_staff_beams_debuff:OnIntervalThink()
|
||||
if IsServer() then
|
||||
local flHealthPctDamage = self.beam_dps_pct * self:GetParent():GetMaxHealth() / 100
|
||||
local flDamage = self.beam_dps + flHealthPctDamage
|
||||
local damageInfo =
|
||||
{
|
||||
victim = self:GetParent(),
|
||||
attacker = self:GetCaster(),
|
||||
damage = flDamage * self.damage_interval,
|
||||
damage_type = DAMAGE_TYPE_MAGICAL,
|
||||
ability = self:GetAbility(),
|
||||
}
|
||||
ApplyDamage( damageInfo )
|
||||
|
||||
local nFXIndex = ParticleManager:CreateParticle( "particles/creatures/aghanim/aghanim_beam_burn.vpcf", PATTACH_ABSORIGIN_FOLLOW, self:GetParent() )
|
||||
ParticleManager:SetParticleControlEnt( nFXIndex, 1, self:GetParent(), PATTACH_POINT_FOLLOW, "attach_hitloc", self:GetParent():GetAbsOrigin(), true )
|
||||
ParticleManager:ReleaseParticleIndex( nFXIndex )
|
||||
end
|
||||
end
|
||||
|
||||
-----------------------------------------------------------------------------
|
||||
@@ -0,0 +1,68 @@
|
||||
|
||||
modifier_aghanim_staff_beams_linger_thinker = class({})
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
function modifier_aghanim_staff_beams_linger_thinker:IsHidden()
|
||||
return true
|
||||
end
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
function modifier_aghanim_staff_beams_linger_thinker:IsAura()
|
||||
return true
|
||||
end
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
function modifier_aghanim_staff_beams_linger_thinker:GetModifierAura()
|
||||
return "modifier_aghanim_staff_beams_debuff"
|
||||
end
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
function modifier_aghanim_staff_beams_linger_thinker:GetAuraSearchTeam()
|
||||
return DOTA_UNIT_TARGET_TEAM_ENEMY
|
||||
end
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
function modifier_aghanim_staff_beams_linger_thinker:GetAuraSearchType()
|
||||
return DOTA_UNIT_TARGET_HERO + DOTA_UNIT_TARGET_CREEP
|
||||
end
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
function modifier_aghanim_staff_beams_linger_thinker:GetAuraRadius()
|
||||
return self.beam_radius
|
||||
end
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
function modifier_aghanim_staff_beams_linger_thinker:OnCreated( kv )
|
||||
self.beam_radius = self:GetAbility():GetSpecialValueFor( "beam_radius" )
|
||||
if IsServer() then
|
||||
EmitSoundOn( "n_black_dragon.Fireball.Target", self:GetParent() )
|
||||
self.nFXIndex = ParticleManager:CreateParticle( "particles/creatures/aghanim/staff_beam_linger.vpcf", PATTACH_CUSTOMORIGIN, nil )
|
||||
ParticleManager:SetParticleControl( self.nFXIndex, 0, self:GetParent():GetAbsOrigin() )
|
||||
ParticleManager:SetParticleControl( self.nFXIndex, 1, Vector( self.beam_radius, 1, 1 ) )
|
||||
end
|
||||
end
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
function modifier_aghanim_staff_beams_linger_thinker:OnDestroy()
|
||||
if IsServer() then
|
||||
StopSoundOn( "n_black_dragon.Fireball.Target", self:GetParent() )
|
||||
ParticleManager:DestroyParticle( self.nFXIndex, false )
|
||||
UTIL_Remove( self:GetParent() )
|
||||
end
|
||||
end
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
function modifier_aghanim_staff_beams_linger_thinker:OnRefresh( kv )
|
||||
self.beam_radius = self:GetAbility():GetSpecialValueFor( "beam_radius" )
|
||||
end
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
@@ -0,0 +1,22 @@
|
||||
|
||||
modifier_aghanim_staff_beams_thinker = class({})
|
||||
|
||||
-----------------------------------------------------------------------------
|
||||
|
||||
function modifier_aghanim_staff_beams_thinker:OnCreated( kv )
|
||||
if IsServer() then
|
||||
self.linger_time = self:GetAbility():GetSpecialValueFor( "linger_time" )
|
||||
self.linger_create_interval = self:GetAbility():GetSpecialValueFor( "linger_create_interval" )
|
||||
self:StartIntervalThink( self.linger_create_interval )
|
||||
end
|
||||
end
|
||||
|
||||
-----------------------------------------------------------------------------
|
||||
|
||||
function modifier_aghanim_staff_beams_thinker:OnIntervalThink()
|
||||
if IsServer() then
|
||||
CreateModifierThinker( self:GetCaster(), self:GetAbility(), "modifier_aghanim_staff_beams_linger_thinker", { duration = self.linger_time }, self:GetParent():GetAbsOrigin(), self:GetCaster():GetTeamNumber(), false )
|
||||
end
|
||||
end
|
||||
|
||||
-----------------------------------------------------------------------------
|
||||
@@ -0,0 +1,220 @@
|
||||
|
||||
modifier_aghanim_summon_portals_thinker = class({})
|
||||
|
||||
-----------------------------------------------------------------------------
|
||||
|
||||
function modifier_aghanim_summon_portals_thinker:OnCreated( kv )
|
||||
if IsServer() then
|
||||
self.nMode = kv.mode
|
||||
self.hTarget = EntIndexToHScript( kv.target_entindex )
|
||||
self.nDepth = kv.depth
|
||||
|
||||
local vFwd = nil
|
||||
if self.hTarget == nil then
|
||||
vFwd = self:GetCaster():GetAbsOrigin() - self:GetParent():GetAbsOrigin()
|
||||
vFwd = vFwd:Normalized()
|
||||
else
|
||||
vFwd = self.hTarget:GetAbsOrigin() - self:GetParent():GetAbsOrigin()
|
||||
vFwd = vFwd:Normalized()
|
||||
end
|
||||
|
||||
local szEffect = nil
|
||||
if self.nMode == self:GetAbility().PORTAL_MODE_ALL_SPEARS and self.hTarget then
|
||||
self:CreateSpear()
|
||||
szEffect = "particles/creatures/aghanim/portal_summon.vpcf"
|
||||
self:StartIntervalThink( 0.1 )
|
||||
else
|
||||
self:CreateEnemies()
|
||||
szEffect = "particles/creatures/aghanim/portal_summon.vpcf"
|
||||
end
|
||||
|
||||
EmitSoundOn( "SeasonalConsumable.TI10.Portal.Open", self:GetParent() )
|
||||
EmitSoundOn( "SeasonalConsumable.TI10.Portal.Loop", self:GetParent() )
|
||||
|
||||
self.nPortalFX = ParticleManager:CreateParticle( szEffect, PATTACH_CUSTOMORIGIN, nil )
|
||||
ParticleManager:SetParticleControl( self.nPortalFX, 0, self:GetParent():GetAbsOrigin() )
|
||||
ParticleManager:SetParticleControlForward( self.nPortalFX, 0, vFwd )
|
||||
|
||||
AddFOWViewer( DOTA_TEAM_GOODGUYS, self:GetParent():GetAbsOrigin(), 300.0, self:GetDuration(), false )
|
||||
GridNav:DestroyTreesAroundPoint( self:GetParent():GetAbsOrigin(), 300, false )
|
||||
end
|
||||
end
|
||||
|
||||
-----------------------------------------------------------------------------
|
||||
|
||||
function modifier_aghanim_summon_portals_thinker:CreateSpear()
|
||||
if IsServer() then
|
||||
self.hSpear = CreateUnitByName( "npc_dota_boss_aghanim_spear", self:GetParent():GetAbsOrigin(), true, self:GetCaster(), self:GetCaster():GetOwner(), self:GetCaster():GetTeamNumber() )
|
||||
if self.hSpear then
|
||||
self.hSpear:SetControllableByPlayer( self:GetCaster():GetPlayerOwnerID(), false )
|
||||
self.hSpear:SetOwner( self:GetCaster() )
|
||||
self.hSpear:AddEffects( EF_NODRAW )
|
||||
self.hSpear:AddNewModifier( self:GetCaster(), self:GetAbility(), "modifier_rooted", {} )
|
||||
self.hSpear:AddNewModifier( self:GetCaster(), self:GetAbility(), "modifier_hero_statue_pedestal", {} )
|
||||
|
||||
--self.hSpear:AddNewModifier( self:GetCaster(), self:GetAbility(), "modifier_aghanim_portal_spawn_effect", {} )
|
||||
self.hSpear:FaceTowards( self.hTarget:GetAbsOrigin() )
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
function modifier_aghanim_summon_portals_thinker:DeclareFunctions()
|
||||
local funcs =
|
||||
{
|
||||
MODIFIER_PROPERTY_IGNORE_CAST_ANGLE,
|
||||
}
|
||||
return funcs
|
||||
end
|
||||
|
||||
-----------------------------------------------------------------------------
|
||||
|
||||
function modifier_aghanim_summon_portals_thinker:GetModifierIgnoreCastAngle( params )
|
||||
return 1
|
||||
end
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
function modifier_aghanim_summon_portals_thinker:OnIntervalThink()
|
||||
if IsServer() then
|
||||
if self.hSpear then
|
||||
self.hSpear:RemoveEffects( EF_NODRAW )
|
||||
self.hSpear:FaceTowards( self.hTarget:GetAbsOrigin() )
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
-----------------------------------------------------------------------------
|
||||
|
||||
function modifier_aghanim_summon_portals_thinker:CreateEnemies()
|
||||
if IsServer() then
|
||||
self.Summons = {}
|
||||
if 1 then
|
||||
nCount = 2
|
||||
for n=1,nCount do
|
||||
local vSpawnPos = self:GetParent():GetAbsOrigin() + RandomVector( 25 * nCount )
|
||||
local hSummon = CreateUnitByName( "npc_dota_creature_aghanim_minion", vSpawnPos, true, self:GetCaster(), self:GetCaster(), self:GetCaster():GetTeamNumber() )
|
||||
if hSummon ~= nil then
|
||||
table.insert( self.Summons, hSummon )
|
||||
hSummon.nDisableResistance = hSummon:GetDisableResistance( )
|
||||
hSummon.nUltimateDisableResistance = hSummon:GetUltimateDisableResistance( )
|
||||
hSummon:SetDisableResistance( 0 )
|
||||
hSummon:SetUltimateDisableResistance( 0 )
|
||||
hSummon:SetOwner( self:GetCaster() )
|
||||
hSummon:SetDeathXP( 0 )
|
||||
hSummon:SetMinimumGoldBounty( 0 )
|
||||
hSummon:SetMaximumGoldBounty( 0 )
|
||||
hSummon:AddEffects( EF_NODRAW )
|
||||
hSummon:SetAbsAngles( 0, RandomFloat( 0, 360 ), 0 )
|
||||
hSummon:SetMaterialGroup( "1" )
|
||||
hSummon:AddNewModifier( self:GetCaster(), self:GetAbility(), "modifier_aghanim_portal_spawn_effect", { duration = self:GetRemainingTime() } )
|
||||
|
||||
end
|
||||
end
|
||||
else
|
||||
local PossibleSummons = GameRules.Aghanim:GetSummonsForAghanim()
|
||||
local Summon = nil
|
||||
|
||||
while Summon == nil and self.nDepth > 1 do
|
||||
for _,CurSummon in pairs( PossibleSummons ) do
|
||||
if CurSummon[ "depth" ] == self.nDepth then
|
||||
Summon = CurSummon
|
||||
break
|
||||
end
|
||||
end
|
||||
|
||||
if Summon == nil then
|
||||
self.nDepth = self.nDepth - 1
|
||||
end
|
||||
end
|
||||
|
||||
if Summon then
|
||||
local nCount = math.max( 1, 5 - math.floor( self.nDepth / 2 ) )
|
||||
for n=1,nCount do
|
||||
local vSpawnPos = self:GetParent():GetAbsOrigin() + RandomVector( 25 * nCount )
|
||||
local hSummon = CreateUnitByName( Summon[ "unit_name" ], vSpawnPos, true, self:GetCaster(), self:GetCaster(), self:GetCaster():GetTeamNumber() )
|
||||
if hSummon ~= nil then
|
||||
table.insert( self.Summons, hSummon )
|
||||
hSummon.nDisableResistance = hSummon:GetDisableResistance( )
|
||||
hSummon.nUltimateDisableResistance = hSummon:GetUltimateDisableResistance( )
|
||||
hSummon:SetDisableResistance( 0 )
|
||||
hSummon:SetUltimateDisableResistance( 0 )
|
||||
hSummon:SetOwner( self:GetCaster() )
|
||||
hSummon:SetDeathXP( 0 )
|
||||
hSummon:SetMinimumGoldBounty( 0 )
|
||||
hSummon:SetMaximumGoldBounty( 0 )
|
||||
hSummon:AddEffects( EF_NODRAW )
|
||||
hSummon:SetAbsAngles( 0, RandomFloat( 0, 360 ), 0 )
|
||||
hSummon:AddNewModifier( self:GetCaster(), self:GetAbility(), "modifier_aghanim_portal_spawn_effect", { duration = self:GetRemainingTime() } )
|
||||
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
-----------------------------------------------------------------------------
|
||||
|
||||
function modifier_aghanim_summon_portals_thinker:OnDestroy()
|
||||
if IsServer() then
|
||||
if self.nMode == self:GetAbility().PORTAL_MODE_ALL_SPEARS then
|
||||
self:LaunchSpear()
|
||||
else
|
||||
self:ReleaseEnemies()
|
||||
end
|
||||
StopSoundOn( "SeasonalConsumable.TI10.Portal.Open", self:GetParent() )
|
||||
StopSoundOn( "SeasonalConsumable.TI10.Portal.Loop", self:GetParent() )
|
||||
|
||||
ParticleManager:DestroyParticle( self.nPortalFX, false )
|
||||
UTIL_Remove( self:GetParent() )
|
||||
end
|
||||
end
|
||||
|
||||
-----------------------------------------------------------------------------
|
||||
|
||||
function modifier_aghanim_summon_portals_thinker:LaunchSpear()
|
||||
if IsServer() then
|
||||
if self.hSpear ~= nil then
|
||||
self.hSpear:AddEffects( EF_NODRAW )
|
||||
self.hSpear:ForceKill( false )
|
||||
end
|
||||
|
||||
local hSpear = self:GetCaster():FindAbilityByName( "aghanim_spear" )
|
||||
if hSpear and self.hTarget then
|
||||
hSpear:EndCooldown()
|
||||
|
||||
EmitSoundOn( "SeasonalConsumable.TI10.Portal.Emit", self:GetParent() )
|
||||
local nFXIndex = ParticleManager:CreateParticle( "particles/creatures/aghanim/aghanim_portal_emit.vpcf", PATTACH_CUSTOMORIGIN, nil )
|
||||
ParticleManager:SetParticleControl( nFXIndex, 0, self:GetParent():GetAbsOrigin() )
|
||||
ParticleManager:ReleaseParticleIndex( nFXIndex )
|
||||
|
||||
hSpear:LaunchSpear( self.hTarget:GetAbsOrigin(), self:GetParent():GetAbsOrigin() )
|
||||
else
|
||||
print( "No spear, or no target?" )
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
-----------------------------------------------------------------------------
|
||||
|
||||
function modifier_aghanim_summon_portals_thinker:ReleaseEnemies()
|
||||
if IsServer() then
|
||||
for _, Summon in pairs ( self.Summons ) do
|
||||
EmitSoundOn( "SeasonalConsumable.TI10.Portal.Emit", Summon )
|
||||
local nFXIndex = ParticleManager:CreateParticle( "particles/creatures/aghanim/aghanim_portal_emit.vpcf", PATTACH_CUSTOMORIGIN, nil )
|
||||
ParticleManager:SetParticleControl( nFXIndex, 0, Summon:GetAbsOrigin() )
|
||||
ParticleManager:ReleaseParticleIndex( nFXIndex )
|
||||
|
||||
Summon:RemoveModifierByName( "modifier_aghanim_portal_spawn_effect" )
|
||||
Summon:SetAcquisitionRange( 5000 )
|
||||
Summon:SetDayTimeVisionRange( 5000 )
|
||||
Summon:SetNightTimeVisionRange( 5000 )
|
||||
Summon:SetDisableResistance( Summon.nDisableResistance )
|
||||
Summon:SetUltimateDisableResistance( Summon.nUltimateDisableResistance )
|
||||
Summon.bBossMinion = true
|
||||
FindClearSpaceForUnit( Summon, Summon:GetAbsOrigin(), false )
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -0,0 +1,40 @@
|
||||
modifier_aghsfort_waveblaster_summon_ghost_thinker = class({})
|
||||
|
||||
|
||||
function modifier_aghsfort_waveblaster_summon_ghost_thinker:OnCreated( kv )
|
||||
if IsServer() then
|
||||
self.nFXIndex = ParticleManager:CreateParticle( "particles/econ/items/ancient_apparition/ancient_apparation_ti8/ancient_ice_vortex_ti8.vpcf", PATTACH_ABSORIGIN, self:GetParent() )
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
|
||||
------------------------------------------------------------------
|
||||
|
||||
function modifier_aghsfort_waveblaster_summon_ghost_thinker:OnDestroy()
|
||||
if IsServer() then
|
||||
local hCreep = CreateUnitByName( "npc_aghsfort_creature_wave_blaster_ghost", self:GetParent():GetOrigin(), true, self:GetCaster(), self:GetCaster(), self:GetCaster():GetTeamNumber() )
|
||||
if hCreep ~= nil then
|
||||
hCreep:SetOwner( self:GetCaster() )
|
||||
hCreep:SetControllableByPlayer( self:GetCaster():GetPlayerOwnerID(), false )
|
||||
hCreep:SetInitialGoalEntity( self:GetCaster():GetInitialGoalEntity() )
|
||||
hCreep:SetDeathXP( 0 )
|
||||
hCreep:SetMinimumGoldBounty( 0 )
|
||||
hCreep:SetMaximumGoldBounty( 0 )
|
||||
end
|
||||
|
||||
local nExplosionFX = ParticleManager:CreateParticle( "particles/units/heroes/hero_ancient_apparition/ancient_apparition_ice_blast_explode.vpcf", PATTACH_CUSTOMORIGIN, NULL )
|
||||
ParticleManager:SetParticleControl( nExplosionFX, 0, self:GetParent():GetOrigin() )
|
||||
ParticleManager:SetParticleControl( nExplosionFX, 3, self:GetParent():GetOrigin() )
|
||||
ParticleManager:ReleaseParticleIndex( nExplosionFX )
|
||||
EmitSoundOn( "Aghsfort_Abilty_Specials.Tusk.Snowball_Damage_End", hCreep )
|
||||
|
||||
|
||||
ParticleManager:DestroyParticle( self.nFXIndex, true )
|
||||
UTIL_Remove( self:GetParent() )
|
||||
end
|
||||
end
|
||||
|
||||
------------------------------------------------------------------
|
||||
|
||||
|
||||
@@ -0,0 +1,46 @@
|
||||
|
||||
modifier_aghsfort_wisp_autoattack = class({})
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
function modifier_aghsfort_wisp_autoattack:OnCreated( kv )
|
||||
self.attack_range = self:GetParent():Script_GetAttackRange()
|
||||
self.attack_interval = self:GetAbility():GetSpecialValueFor( "attack_interval" )
|
||||
|
||||
self:StartIntervalThink( self.attack_interval )
|
||||
end
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
function modifier_aghsfort_wisp_autoattack:IsHidden()
|
||||
return true
|
||||
end
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
function modifier_aghsfort_wisp_autoattack:OnRefresh( kv )
|
||||
self.radius =self:GetParent():Script_GetAttackRange()
|
||||
self.attack_interval = self:GetAbility():GetSpecialValueFor( "attack_interval" )
|
||||
end
|
||||
|
||||
|
||||
function modifier_aghsfort_wisp_autoattack:OnIntervalThink()
|
||||
if IsServer() then
|
||||
|
||||
if not self:GetParent():IsAlive() then
|
||||
return -1
|
||||
end
|
||||
|
||||
if not self:GetParent():FindModifierByName("modifier_aghsfort_wisp_tether") then
|
||||
local hEnemies = FindUnitsInRadius( self:GetParent():GetTeamNumber(), self:GetParent():GetOrigin(), nil, self.attack_range, DOTA_UNIT_TARGET_TEAM_ENEMY, DOTA_UNIT_TARGET_HERO + DOTA_UNIT_TARGET_BASIC, DOTA_UNIT_TARGET_FLAG_MAGIC_IMMUNE_ENEMIES + DOTA_UNIT_TARGET_FLAG_FOW_VISIBLE, FIND_CLOSEST, false )
|
||||
if #hEnemies > 0 then
|
||||
for _, hEnemy in pairs( hEnemies ) do
|
||||
if hEnemy ~= nil and hEnemy:IsAlive() == true then
|
||||
self:GetParent():PerformAttack( hEnemy, true, true, true, true, true, false, true )
|
||||
break
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -0,0 +1,81 @@
|
||||
|
||||
modifier_baby_broodmother_passive = class({})
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
function modifier_baby_broodmother_passive:IsPurgable()
|
||||
return false
|
||||
end
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
function modifier_baby_broodmother_passive:IsHidden()
|
||||
return true
|
||||
end
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
function modifier_baby_broodmother_passive:OnCreated( kv )
|
||||
if IsServer() then
|
||||
self.radius = self:GetAbility():GetSpecialValueFor( "radius" )
|
||||
self.landing_damage = self:GetAbility():GetSpecialValueFor( "landing_damage" )
|
||||
self.launch_duration = self:GetAbility():GetSpecialValueFor( "launch_duration" )
|
||||
self.knockback_duration = self:GetAbility():GetSpecialValueFor( "knockback_duration" )
|
||||
self.knockback_distance = self:GetAbility():GetSpecialValueFor( "knockback_distance" )
|
||||
self.knockback_height = self:GetAbility():GetSpecialValueFor( "knockback_height" )
|
||||
|
||||
self:StartIntervalThink( self.launch_duration ) -- this is hacky: launch duration (0.75) matches the enchant totem leap duration; ideally we'd create the thinker using OnModifierAdded or similar
|
||||
end
|
||||
end
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
function modifier_baby_broodmother_passive:OnIntervalThink()
|
||||
if IsServer() then
|
||||
self:DamageEnemiesOnLanding()
|
||||
|
||||
self:StartIntervalThink( -1 )
|
||||
|
||||
self:Destroy()
|
||||
end
|
||||
end
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
function modifier_baby_broodmother_passive:DamageEnemiesOnLanding()
|
||||
if IsServer() then
|
||||
local hEnemies = FindUnitsInRadius( self:GetParent():GetTeamNumber(), self:GetParent():GetOrigin(), self:GetParent(), self.radius, DOTA_UNIT_TARGET_TEAM_ENEMY, DOTA_UNIT_TARGET_HERO + DOTA_UNIT_TARGET_BASIC, DOTA_UNIT_TARGET_FLAG_NONE, 0, false )
|
||||
if #hEnemies > 0 then
|
||||
for _, hEnemy in pairs( hEnemies ) do
|
||||
if hEnemy ~= nil and ( not hEnemy:IsMagicImmune() ) and ( not hEnemy:IsInvulnerable() ) then
|
||||
local DamageInfo =
|
||||
{
|
||||
victim = hEnemy,
|
||||
attacker = self:GetCaster(),
|
||||
ability = self:GetAbility(),
|
||||
damage = self.landing_damage,
|
||||
damage_type = self:GetAbility():GetAbilityDamageType(),
|
||||
}
|
||||
ApplyDamage( DamageInfo )
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
function modifier_baby_broodmother_passive:CheckState()
|
||||
local state =
|
||||
{
|
||||
[ MODIFIER_STATE_UNSELECTABLE ] = true,
|
||||
[ MODIFIER_STATE_OUT_OF_GAME ] = true,
|
||||
[ MODIFIER_STATE_INVULNERABLE ] = true,
|
||||
[ MODIFIER_STATE_MAGIC_IMMUNE ] = true,
|
||||
[ MODIFIER_STATE_DISARMED ] = true,
|
||||
}
|
||||
|
||||
return state
|
||||
end
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
@@ -0,0 +1,104 @@
|
||||
|
||||
modifier_baby_broodmother_venom_pool = class({})
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
function modifier_baby_broodmother_venom_pool:IsHidden()
|
||||
return true
|
||||
end
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
function modifier_baby_broodmother_venom_pool:IsPurgable()
|
||||
return false
|
||||
end
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
function modifier_baby_broodmother_venom_pool:IsAura()
|
||||
return true
|
||||
end
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
function modifier_baby_broodmother_venom_pool:GetModifierAura()
|
||||
return "modifier_viper_nethertoxin"
|
||||
end
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
function modifier_baby_broodmother_venom_pool:GetAuraSearchTeam()
|
||||
return DOTA_UNIT_TARGET_TEAM_ENEMY
|
||||
end
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
function modifier_baby_broodmother_venom_pool:GetAuraSearchType()
|
||||
return DOTA_UNIT_TARGET_HERO + DOTA_UNIT_TARGET_CREEP
|
||||
end
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
function modifier_baby_broodmother_venom_pool:GetAuraRadius()
|
||||
return self.radius
|
||||
end
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
function modifier_baby_broodmother_venom_pool:OnCreated( kv )
|
||||
if IsServer() then
|
||||
self.radius = self:GetAbility():GetSpecialValueFor( "radius" )
|
||||
self.damage = self:GetAbility():GetSpecialValueFor( "damage" )
|
||||
|
||||
self.nFXIndex = ParticleManager:CreateParticle( "particles/baby_brood_venom_pool.vpcf", PATTACH_CUSTOMORIGIN, self:GetCaster() )
|
||||
ParticleManager:SetParticleControl( self.nFXIndex, 0, self:GetCaster():GetAbsOrigin() )
|
||||
ParticleManager:SetParticleControl( self.nFXIndex, 1, Vector( self.radius, 1, 1 ) )
|
||||
|
||||
EmitSoundOn( "Hero_Viper.Nethertoxin", self:GetCaster() )
|
||||
|
||||
self:StartIntervalThink( 1 )
|
||||
end
|
||||
end
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
function modifier_baby_broodmother_venom_pool:OnIntervalThink()
|
||||
if IsServer() then
|
||||
if not self:GetCaster() then
|
||||
self:Destroy()
|
||||
return
|
||||
end
|
||||
|
||||
local hEnemies = FindUnitsInRadius( self:GetParent():GetTeamNumber(), self:GetParent():GetOrigin(), self:GetParent(), self.radius, DOTA_UNIT_TARGET_TEAM_ENEMY, DOTA_UNIT_TARGET_HERO + DOTA_UNIT_TARGET_BASIC, DOTA_UNIT_TARGET_FLAG_MAGIC_IMMUNE_ENEMIES, 0, false )
|
||||
if #hEnemies > 0 then
|
||||
for _, hEnemy in pairs( hEnemies ) do
|
||||
if hEnemy and hEnemy:IsInvulnerable() == false and hEnemy:IsMagicImmune() == false then
|
||||
local damage = {
|
||||
victim = hEnemy,
|
||||
attacker = self:GetCaster(),
|
||||
damage = self.damage,
|
||||
damage_type = self:GetAbility():GetAbilityDamageType(),
|
||||
ability = self:GetAbility()
|
||||
}
|
||||
|
||||
ApplyDamage( damage )
|
||||
|
||||
EmitSoundOn( "Hero_Viper.NetherToxin.Damage", hEnemy )
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
function modifier_baby_broodmother_venom_pool:OnDestroy()
|
||||
if IsServer() then
|
||||
ParticleManager:DestroyParticle( self.nFXIndex, false )
|
||||
self:GetParent():StopSound( "Hero_Viper.Nethertoxin" )
|
||||
UTIL_Remove( self:GetParent() )
|
||||
end
|
||||
end
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
@@ -0,0 +1,33 @@
|
||||
|
||||
modifier_bandit_archer_arrow_debuff = class({})
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
function modifier_bandit_archer_arrow_debuff:OnCreated( kv )
|
||||
if IsServer() then
|
||||
self.nBreakFX = ParticleManager:CreateParticle( "particles/generic_gameplay/generic_break.vpcf", PATTACH_OVERHEAD_FOLLOW, self:GetParent() )
|
||||
end
|
||||
end
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
function modifier_bandit_archer_arrow_debuff:OnDestroy()
|
||||
if IsServer() then
|
||||
if self.nBreakFX ~= nil then
|
||||
ParticleManager:DestroyParticle( self.nBreakFX, false )
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
function modifier_bandit_archer_arrow_debuff:CheckState()
|
||||
local state =
|
||||
{
|
||||
[ MODIFIER_STATE_PASSIVES_DISABLED ] = true,
|
||||
}
|
||||
|
||||
return state
|
||||
end
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
@@ -0,0 +1,99 @@
|
||||
modifier_bomb_squad_landmine_detonate = class({})
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
function modifier_bomb_squad_landmine_detonate:OnCreated( kv )
|
||||
if IsServer() then
|
||||
self.radius = self:GetAbility():GetSpecialValueFor( "detonate_radius" )
|
||||
self.damage = self:GetAbility():GetSpecialValueFor( "detonate_damage" )
|
||||
self.duration = self:GetRemainingTime()
|
||||
self.flExplodeTime = GameRules:GetGameTime() + self.duration - 0.2
|
||||
|
||||
self:StartIntervalThink( 0 )
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
--------------------------------------------------------------
|
||||
|
||||
function modifier_bomb_squad_landmine_detonate:DeclareFunctions()
|
||||
local funcs =
|
||||
{
|
||||
MODIFIER_EVENT_ON_DEATH,
|
||||
}
|
||||
|
||||
return funcs
|
||||
end
|
||||
--------
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
function modifier_bomb_squad_landmine_detonate:OnIntervalThink()
|
||||
if IsServer() then
|
||||
|
||||
local nFXIndex = ParticleManager:CreateParticle( "particles/econ/events/darkmoon_2017/darkmoon_calldown_marker_ring.vpcf", PATTACH_CUSTOMORIGIN, nil )
|
||||
ParticleManager:SetParticleControl( nFXIndex, 0, self:GetParent():GetOrigin() )
|
||||
ParticleManager:SetParticleControl( nFXIndex, 1, Vector( self.radius, self.radius, self.radius ) )
|
||||
ParticleManager:SetParticleControl( nFXIndex, 2, Vector( self:GetRemainingTime() / 6, self:GetRemainingTime() / 6, self:GetRemainingTime() / 6 ) )
|
||||
ParticleManager:ReleaseParticleIndex( nFXIndex )
|
||||
|
||||
EmitSoundOn( "Creature_Bomb_Squad.LandMine.Priming", self:GetParent() )
|
||||
|
||||
if GameRules:GetGameTime() > self.flExplodeTime then
|
||||
self:Detonate()
|
||||
end
|
||||
|
||||
self:StartIntervalThink( self:GetRemainingTime() / 3 )
|
||||
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
function modifier_bomb_squad_landmine_detonate:OnDestroy()
|
||||
if IsServer() then
|
||||
self:GetParent():ForceKill( false )
|
||||
end
|
||||
end
|
||||
|
||||
function modifier_bomb_squad_landmine_detonate:Detonate()
|
||||
if IsServer() then
|
||||
local enemies = FindUnitsInRadius( self:GetCaster():GetTeamNumber(), self:GetParent():GetOrigin(), self:GetCaster(), self.radius, DOTA_UNIT_TARGET_TEAM_ENEMY, DOTA_UNIT_TARGET_HERO + DOTA_UNIT_TARGET_BASIC, DOTA_UNIT_TARGET_FLAG_NOT_ANCIENTS, 0, false )
|
||||
if #enemies > 0 then
|
||||
for _,enemy in pairs(enemies) do
|
||||
if enemy ~= nil and ( not enemy:IsMagicImmune() ) and ( not enemy:IsInvulnerable() ) then
|
||||
local DamageInfo =
|
||||
{
|
||||
victim = enemy,
|
||||
attacker = self:GetCaster(),
|
||||
ability = self,
|
||||
damage = self.damage,
|
||||
damage_type = DAMAGE_TYPE_MAGICAL,
|
||||
}
|
||||
ApplyDamage( DamageInfo )
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
local nFXIndex = ParticleManager:CreateParticle( "particles/units/heroes/hero_techies/techies_land_mine_explode.vpcf", PATTACH_CUSTOMORIGIN, nil )
|
||||
ParticleManager:SetParticleControl( nFXIndex, 0, self:GetParent():GetOrigin() )
|
||||
ParticleManager:SetParticleControl( nFXIndex, 1, Vector( 1.0, 1.0, self.radius ) )
|
||||
ParticleManager:SetParticleControl( nFXIndex, 2, Vector( 1.0, 1.0, self.radius ) )
|
||||
ParticleManager:ReleaseParticleIndex( nFXIndex )
|
||||
|
||||
EmitSoundOn( "Creature_Bomb_Squad.LandMine.Detonate", self:GetParent() )
|
||||
self:GetParent():ForceKill( false )
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
|
||||
function modifier_bomb_squad_landmine_detonate:OnDeath( params )
|
||||
if IsServer() then
|
||||
if params.unit == self:GetParent() then
|
||||
params.unit:AddEffects( EF_NODRAW )
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -0,0 +1,112 @@
|
||||
modifier_bomb_squad_landmine_intrinsic = class({})
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
function modifier_bomb_squad_landmine_intrinsic:CheckState()
|
||||
local state =
|
||||
{
|
||||
[MODIFIER_STATE_NO_UNIT_COLLISION] = true,
|
||||
[MODIFIER_STATE_ROOTED] = true,
|
||||
[MODIFIER_STATE_MAGIC_IMMUNE] = true,
|
||||
}
|
||||
|
||||
return state
|
||||
end
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
function modifier_bomb_squad_landmine_intrinsic:DeclareFunctions()
|
||||
local funcs = {
|
||||
MODIFIER_PROPERTY_INCOMING_DAMAGE_PERCENTAGE,
|
||||
MODIFIER_EVENT_ON_ATTACKED,
|
||||
MODIFIER_EVENT_ON_DEATH,
|
||||
}
|
||||
|
||||
return funcs
|
||||
|
||||
end
|
||||
|
||||
----------------------------------------------------------------------------------
|
||||
|
||||
function modifier_bomb_squad_landmine_intrinsic:IsHidden()
|
||||
return true
|
||||
end
|
||||
|
||||
----------------------------------------------------------------------------------
|
||||
|
||||
function modifier_bomb_squad_landmine_intrinsic:IsPurgable()
|
||||
return false
|
||||
end
|
||||
|
||||
----------------------------------------------------------------------------------
|
||||
|
||||
function modifier_bomb_squad_landmine_intrinsic:CanParentBeAutoAttacked()
|
||||
return true
|
||||
end
|
||||
|
||||
------------------------------------------------------------
|
||||
|
||||
function modifier_bomb_squad_landmine_intrinsic:GetAbsoluteNoDamageMagical( params )
|
||||
return 1
|
||||
end
|
||||
|
||||
------------------------------------------------------------
|
||||
|
||||
function modifier_bomb_squad_landmine_intrinsic:GetAbsoluteNoDamagePure( params )
|
||||
return 1
|
||||
end
|
||||
|
||||
------------------------------------------------------------
|
||||
|
||||
function modifier_bomb_squad_landmine_intrinsic:GetAbsoluteNoDamagePhysical( params )
|
||||
return 1
|
||||
end
|
||||
|
||||
------------------------------------------------------------
|
||||
|
||||
function modifier_bomb_squad_landmine_intrinsic:GetModifierIncomingDamage_Percentage( params )
|
||||
return -100
|
||||
end
|
||||
|
||||
|
||||
------------------------------------------------------------
|
||||
|
||||
function modifier_bomb_squad_landmine_intrinsic:OnAttacked( params )
|
||||
if IsServer() then
|
||||
|
||||
if params.target == self:GetParent() then
|
||||
|
||||
self:GetParent():ForceKill( false )
|
||||
end
|
||||
end
|
||||
|
||||
return 1
|
||||
end
|
||||
|
||||
------------------------------------------------------------
|
||||
|
||||
function modifier_bomb_squad_landmine_intrinsic:OnDeath( params )
|
||||
if IsServer() then
|
||||
if params.unit == self:GetParent() then
|
||||
local iChainReactionRadius = self:GetAbility():GetSpecialValueFor( "chain_radius" )
|
||||
local hFriendlyMines = FindUnitsInRadius( self:GetParent():GetTeamNumber(), self:GetParent():GetOrigin(), nil, iChainReactionRadius, DOTA_UNIT_TARGET_TEAM_FRIENDLY, DOTA_UNIT_TARGET_HERO + DOTA_UNIT_TARGET_BASIC, DOTA_UNIT_TARGET_FLAG_MAGIC_IMMUNE_ENEMIES + DOTA_UNIT_TARGET_FLAG_FOW_VISIBLE, FIND_CLOSEST, false )
|
||||
if #hFriendlyMines > 0 then
|
||||
for _,entity in pairs (hFriendlyMines) do
|
||||
if entity ~= nil and entity:IsNull() == false and entity ~= self:GetParent() and entity:IsAlive() and entity:GetUnitName() == self:GetParent():GetUnitName() and not entity:FindModifierByName("modifier_bomb_squad_landmine_detonate") then
|
||||
local hAbility = entity:FindAbilityByName("bomb_squad_landmine_detonate")
|
||||
if hAbility ~= nil then
|
||||
entity:AddNewModifier( entity, hAbility, "modifier_bomb_squad_landmine_detonate", { duration = hAbility:GetSpecialValueFor( "chain_duration" ) } )
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
self:GetParent():AddEffects( EF_NODRAW )
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
return 0
|
||||
end
|
||||
|
||||
|
||||
@@ -0,0 +1,152 @@
|
||||
|
||||
modifier_bomb_squad_mine_charge = class({})
|
||||
|
||||
-------------------------------------------------------
|
||||
|
||||
function modifier_bomb_squad_mine_charge:IsPurgable()
|
||||
return false
|
||||
end
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
function modifier_bomb_squad_mine_charge:OnCreated( kv )
|
||||
if IsServer() then
|
||||
self.vTarget = Vector( kv["vLocX"], kv["vLocY"], kv["vLocZ"] )
|
||||
self.vDir = self.vTarget - self:GetParent():GetOrigin()
|
||||
self.vDir = self.vDir:Normalized()
|
||||
self.szMineUnit = "npc_aghsfort_creature_bomb_squad_landmine"
|
||||
self.speed = self:GetAbility():GetSpecialValueFor( "speed" )
|
||||
|
||||
self.mine_spawn_interval = self:GetAbility():GetSpecialValueFor( "mine_spawn_interval" )
|
||||
self.max_launch_distance = self:GetAbility():GetSpecialValueFor( "max_launch_distance" )
|
||||
self.flLastMineTime = GameRules:GetGameTime()
|
||||
self:GetParent():StartGesture( ACT_DOTA_RUN )
|
||||
|
||||
|
||||
self:OnIntervalThink()
|
||||
self:StartIntervalThink( 0.33 )
|
||||
if self:ApplyHorizontalMotionController() == false then
|
||||
self:Destroy()
|
||||
return
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
function modifier_bomb_squad_mine_charge:OnIntervalThink()
|
||||
if IsServer() then
|
||||
if GameRules:GetGameTime() - self.flLastMineTime > self.mine_spawn_interval then
|
||||
self:SpawnMine()
|
||||
end
|
||||
if self:GetParent():IsStunned() == true then
|
||||
self:Destroy()
|
||||
end
|
||||
|
||||
end
|
||||
end
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
function modifier_bomb_squad_mine_charge:UpdateHorizontalMotion( me, dt )
|
||||
if IsServer() then
|
||||
local vNewLocation = self:GetParent():GetOrigin() + self.vDir * self.speed * dt
|
||||
me:SetOrigin( vNewLocation )
|
||||
end
|
||||
end
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
function modifier_bomb_squad_mine_charge:SpawnMine()
|
||||
if IsServer() then
|
||||
local hUnit = self:GetParent()
|
||||
if hUnit == nil then
|
||||
return
|
||||
end
|
||||
if not hUnit:IsAlive() then
|
||||
return
|
||||
end
|
||||
|
||||
local hMine = CreateUnitByName( self.szMineUnit, self:GetParent():GetAbsOrigin(), true, self:GetParent(), self:GetParent(), self:GetParent():GetTeamNumber() )
|
||||
local nMaxDistance = self.max_launch_distance
|
||||
-- spawn the mine a little bit bit behind us
|
||||
local vLoc = self:GetParent():GetOrigin() - self.vDir * nMaxDistance
|
||||
|
||||
hMine:SetDeathXP( 0 )
|
||||
hMine:SetMinimumGoldBounty( 0 )
|
||||
hMine:SetMaximumGoldBounty( 0 )
|
||||
|
||||
local kv =
|
||||
{
|
||||
vLocX = vLoc.x,
|
||||
vLocY = vLoc.y,
|
||||
vLocZ = vLoc.z,
|
||||
}
|
||||
hMine:SetAbsAngles( 0 , vLoc.y, 0 )
|
||||
|
||||
hMine:AddNewModifier( self:GetParent(), self:GetAbility(), "modifier_frostivus2018_broodbaby_launch", kv )
|
||||
self.flLastMineTime = GameRules:GetGameTime()
|
||||
EmitSoundOn( "Creature_Bomb_Squad.LandMine.Plant", hMine )
|
||||
end
|
||||
|
||||
return
|
||||
end
|
||||
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
function modifier_bomb_squad_mine_charge:OnHorizontalMotionInterrupted()
|
||||
if IsServer() then
|
||||
self:Destroy()
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
function modifier_bomb_squad_mine_charge:OnDestroy()
|
||||
if IsServer() then
|
||||
self:GetParent():RemoveGesture( ACT_DOTA_RUN )
|
||||
self:GetParent():RemoveHorizontalMotionController( self )
|
||||
end
|
||||
end
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
function modifier_bomb_squad_mine_charge:DeclareFunctions()
|
||||
local funcs =
|
||||
{
|
||||
MODIFIER_PROPERTY_DISABLE_TURNING,
|
||||
}
|
||||
|
||||
return funcs
|
||||
end
|
||||
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
function modifier_bomb_squad_mine_charge:GetModifierDisableTurning(params)
|
||||
return 1
|
||||
end
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
function modifier_bomb_squad_mine_charge:GetPriority()
|
||||
return MODIFIER_PRIORITY_SUPER_ULTRA + 100
|
||||
end
|
||||
|
||||
-----------------------------------------------------------------------------------------
|
||||
|
||||
function modifier_bomb_squad_mine_charge:CheckState()
|
||||
local state =
|
||||
{
|
||||
[MODIFIER_STATE_HEXED] = false,
|
||||
[MODIFIER_STATE_ROOTED] = false,
|
||||
[MODIFIER_STATE_SILENCED] = false,
|
||||
[MODIFIER_STATE_STUNNED] = false,
|
||||
[MODIFIER_STATE_FROZEN] = false,
|
||||
[MODIFIER_STATE_FEARED] = false,
|
||||
}
|
||||
return state
|
||||
end
|
||||
@@ -0,0 +1,154 @@
|
||||
modifier_bomb_squad_self_cast = class({})
|
||||
|
||||
require( "utility_functions" ) -- require utility_functions early (other required files may use its functions)
|
||||
require( "aghanim_utility_functions" ) -- require utility_functions early (other required files may use its functions)
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
function modifier_bomb_squad_self_cast:IsPurgable()
|
||||
return false;
|
||||
end
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
function modifier_bomb_squad_self_cast:IsHidden()
|
||||
return true;
|
||||
end
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
function modifier_bomb_squad_self_cast:OnCreated( kv )
|
||||
if IsServer() then
|
||||
self.hMines = { }
|
||||
self.max_active_mines = self:GetAbility():GetSpecialValueFor( "max_active_mines" )
|
||||
self.mine_spawn_interval = self:GetAbility():GetSpecialValueFor( "mine_spawn_interval" )
|
||||
self.max_launch_distance = self:GetAbility():GetSpecialValueFor( "max_launch_distance" )
|
||||
self.flLastMineTime = GameRules:GetGameTime()
|
||||
self.flLastOrderTime = GameRules:GetGameTime() - 5
|
||||
self.bActivated = false;
|
||||
self.szMineUnit = "npc_aghsfort_creature_bomb_squad_landmine"
|
||||
|
||||
self:OnIntervalThink()
|
||||
end
|
||||
end
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
function modifier_bomb_squad_self_cast:DeclareFunctions()
|
||||
local funcs = {
|
||||
MODIFIER_EVENT_ON_DEATH,
|
||||
MODIFIER_PROPERTY_MOVESPEED_ABSOLUTE,
|
||||
}
|
||||
|
||||
return funcs
|
||||
end
|
||||
|
||||
function modifier_bomb_squad_self_cast:OnIntervalThink()
|
||||
if IsServer() then
|
||||
|
||||
if GameRules:GetGameTime() - self.flLastOrderTime > 5 then
|
||||
self:DoMove()
|
||||
|
||||
end
|
||||
|
||||
if GameRules:GetGameTime() - self.flLastMineTime > self.mine_spawn_interval then
|
||||
self:SpawnMine()
|
||||
end
|
||||
|
||||
if self.bActivated == false then
|
||||
self.bActivated = true
|
||||
self:StartIntervalThink( 1 )
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
function modifier_bomb_squad_self_cast:SpawnMine()
|
||||
if IsServer() then
|
||||
local hUnit = self:GetParent()
|
||||
if hUnit == nil then
|
||||
return
|
||||
end
|
||||
if not hUnit:IsAlive() then
|
||||
return
|
||||
end
|
||||
|
||||
if #self.hMines > self.max_active_mines then
|
||||
return
|
||||
end
|
||||
|
||||
local hMine = CreateUnitByName( self.szMineUnit, self:GetParent():GetAbsOrigin(), true, self:GetParent(), self:GetParent(), self:GetParent():GetTeamNumber() )
|
||||
local nMaxDistance = self.max_launch_distance
|
||||
local vLoc = FindPathablePositionNearby(self:GetParent():GetAbsOrigin(), 150, nMaxDistance )
|
||||
table.insert( self.hMines, hMine )
|
||||
|
||||
local heroes = FindRealLivingEnemyHeroesInRadius( self:GetParent():GetTeamNumber(), self:GetParent():GetAbsOrigin(), FIND_UNITS_EVERYWHERE )
|
||||
local hero = heroes[RandomInt(1, #heroes)]
|
||||
if hero ~= nil then
|
||||
hMine:SetInitialGoalEntity( hero )
|
||||
else
|
||||
hMine:SetInitialGoalEntity( self:GetParent().hInitialGoalEntity )
|
||||
end
|
||||
|
||||
hMine:SetDeathXP( 0 )
|
||||
hMine:SetMinimumGoldBounty( 0 )
|
||||
hMine:SetMaximumGoldBounty( 0 )
|
||||
|
||||
local kv =
|
||||
{
|
||||
vLocX = vLoc.x,
|
||||
vLocY = vLoc.y,
|
||||
vLocZ = vLoc.z,
|
||||
}
|
||||
hMine:SetAbsAngles( 0 , vLoc.y, 0 )
|
||||
|
||||
hMine:AddNewModifier( self:GetParent(), self:GetAbility(), "modifier_frostivus2018_broodbaby_launch", kv )
|
||||
self.flLastMineTime = GameRules:GetGameTime()
|
||||
EmitSoundOn( "Creature_Bomb_Squad.LandMine.Plant", hMine )
|
||||
end
|
||||
|
||||
return
|
||||
end
|
||||
|
||||
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
|
||||
function modifier_bomb_squad_self_cast:DoMove()
|
||||
if IsServer() then
|
||||
|
||||
for i=1,4 do
|
||||
local vLoc = FindPathablePositionNearby(self:GetParent():GetAbsOrigin(), 800, 2000 )
|
||||
|
||||
if GameRules.Aghanim:GetCurrentRoom():IsInRoomBounds( vLoc ) then
|
||||
|
||||
ExecuteOrderFromTable({
|
||||
UnitIndex = self:GetParent():entindex(),
|
||||
OrderType = DOTA_UNIT_ORDER_MOVE_TO_POSITION,
|
||||
Position = vLoc,
|
||||
Queue = false,
|
||||
})
|
||||
self.flLastOrderTime = GameRules:GetGameTime()
|
||||
|
||||
break
|
||||
end
|
||||
end
|
||||
end
|
||||
return
|
||||
end
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
|
||||
function modifier_bomb_squad_self_cast:OnDeath( params )
|
||||
if IsServer() then
|
||||
if TableContainsValue (self.hMines, params.unit) then
|
||||
local k = TableFindKey(self.hMines, params.unit)
|
||||
params.unit:AddEffects( EF_NODRAW )
|
||||
table.remove(self.hMines, k)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
@@ -0,0 +1,91 @@
|
||||
modifier_bomb_squad_stasis_trap = class({})
|
||||
--------------------------------------------------------------------------------
|
||||
function modifier_bomb_squad_stasis_trap:IsHidden()
|
||||
return true
|
||||
end
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
function modifier_bomb_squad_stasis_trap:OnCreated()
|
||||
self.radius = self:GetAbility():GetSpecialValueFor( "detonate_radius" )
|
||||
self.activation_delay = self:GetAbility():GetSpecialValueFor( "activation_delay" )
|
||||
self.stun_duration = self:GetAbility():GetSpecialValueFor( "stun_duration" )
|
||||
self.damage = self:GetAbility():GetSpecialValueFor( "damage" )
|
||||
self.bActivated = false
|
||||
self.bTriggered = false
|
||||
self:StartIntervalThink( self.activation_delay )
|
||||
end
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
function modifier_bomb_squad_stasis_trap:OnIntervalThink()
|
||||
if IsServer() then
|
||||
if self.bActivated == false then
|
||||
self.bActivated = true
|
||||
|
||||
EmitSoundOn("Hero_Techies.StasisTrap.Plant", self:GetParent())
|
||||
local nFXIndex = ParticleManager:CreateParticle( "particles/units/heroes/hero_techies/techies_stasis_trap_plant.vpcf", PATTACH_ABSORIGIN_FOLLOW, self:GetParent() )
|
||||
ParticleManager:SetParticleControlEnt( nFXIndex, 0, self:GetParent(), PATTACH_ABSORIGIN_FOLLOW, nil, self:GetParent():GetOrigin(), true )
|
||||
ParticleManager:SetParticleControl( nFXIndex, 1, self:GetParent():GetOrigin() )
|
||||
ParticleManager:SetParticleControlOrientation( nFXIndex, 1, self:GetParent():GetForwardVector(), self:GetParent():GetRightVector(), self:GetParent():GetUpVector() )
|
||||
ParticleManager:SetParticleControlEnt( nFXIndex, 0, self:GetParent(), PATTACH_ABSORIGIN_FOLLOW, nil, self:GetParent():GetOrigin(), true )
|
||||
ParticleManager:ReleaseParticleIndex( nFXIndex )
|
||||
|
||||
self:StartIntervalThink( 0.1 )
|
||||
end
|
||||
|
||||
local enemies = FindUnitsInRadius( self:GetParent():GetTeamNumber(), self:GetParent():GetOrigin(), self:GetParent(), self.radius, DOTA_UNIT_TARGET_TEAM_ENEMY, DOTA_UNIT_TARGET_HERO + DOTA_UNIT_TARGET_BASIC, DOTA_UNIT_TARGET_FLAG_NOT_ANCIENTS, 0, false )
|
||||
if #enemies > 0 then
|
||||
self:Detonate()
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function modifier_bomb_squad_stasis_trap:Detonate()
|
||||
if IsServer() then
|
||||
local nFXIndex = ParticleManager:CreateParticle("particles/units/heroes/hero_techies/techies_stasis_trap_explode.vpcf", PATTACH_WORLDORIGIN, self:GetParent())
|
||||
ParticleManager:SetParticleControl(nFXIndex, 0, self:GetParent():GetAbsOrigin())
|
||||
ParticleManager:SetParticleControl(nFXIndex, 1, Vector(self.radius , 1, 1))
|
||||
ParticleManager:SetParticleControl(nFXIndex, 3, self:GetParent():GetAbsOrigin())
|
||||
ParticleManager:ReleaseParticleIndex(nFXIndex)
|
||||
|
||||
local enemies = FindUnitsInRadius( self:GetParent():GetTeamNumber(), self:GetParent():GetOrigin(), self:GetParent(), self.radius, DOTA_UNIT_TARGET_TEAM_ENEMY, DOTA_UNIT_TARGET_HERO + DOTA_UNIT_TARGET_BASIC, DOTA_UNIT_TARGET_FLAG_NOT_ANCIENTS, 0, false )
|
||||
if #enemies > 0 then
|
||||
EmitSoundOn("Hero_Techies.StasisTrap.Stun", self:GetParent())
|
||||
for _,enemy in pairs(enemies) do
|
||||
--apply stun modifier
|
||||
if enemy ~= nil and ( not enemy:IsMagicImmune() ) and ( not enemy:IsInvulnerable() ) then
|
||||
local DamageInfo =
|
||||
{
|
||||
victim = enemy,
|
||||
attacker = self:GetParent(),
|
||||
ability = self:GetAbility(),
|
||||
damage = self.damage,
|
||||
damage_type = DAMAGE_TYPE_MAGICAL,
|
||||
}
|
||||
ApplyDamage( DamageInfo )
|
||||
enemy:AddNewModifier(self:GetParent(), self:GetAbility(), "modifier_techies_stasis_trap_stunned", {duration = self.stun_duration})
|
||||
end
|
||||
end
|
||||
end
|
||||
self:Destroy()
|
||||
end
|
||||
end
|
||||
|
||||
function modifier_bomb_squad_stasis_trap:OnDeath( params )
|
||||
if IsServer() then
|
||||
if params.unit == self:GetParent() then
|
||||
params.unit:AddEffects( EF_NODRAW )
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
function modifier_bomb_squad_stasis_trap:OnDestroy()
|
||||
if IsServer() then
|
||||
if self:GetParent() ~= nil and self:GetParent():IsAlive() then
|
||||
self:GetParent():ForceKill(false)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
@@ -0,0 +1,158 @@
|
||||
|
||||
modifier_bomber_death_explosion = class({})
|
||||
|
||||
--------------------------------------------------------------
|
||||
|
||||
function modifier_bomber_death_explosion:IsHidden()
|
||||
return true
|
||||
end
|
||||
|
||||
--------------------------------------------------------------
|
||||
|
||||
function modifier_bomber_death_explosion:IsPurgable()
|
||||
return false
|
||||
end
|
||||
|
||||
--------------------------------------------------------------
|
||||
|
||||
function modifier_bomber_death_explosion:OnCreated()
|
||||
local min_delay = self:GetAbility():GetSpecialValueFor( "min_delay_time" )
|
||||
local max_delay = self:GetAbility():GetSpecialValueFor( "max_delay_time" )
|
||||
--printf( 'min = %f, max = %f\n', min_delay, max_delay )
|
||||
|
||||
EmitSoundOn( "Ability.Bomber.Priming", self:GetParent() )
|
||||
|
||||
self.is_ascension_ability = self:GetAbility():GetSpecialValueFor( "is_ascension_ability" )
|
||||
|
||||
local delay = RandomFloat( min_delay, max_delay )
|
||||
self:StartIntervalThink( delay )
|
||||
|
||||
if IsServer() then
|
||||
|
||||
if self.is_ascension_ability == 0 then
|
||||
self:GetParent():StartGesture( ACT_DOTA_VICTORY )
|
||||
else
|
||||
local nOverheadFX = ParticleManager:CreateParticle( "particles/units/heroes/hero_gyrocopter/gyro_guided_missile_target.vpcf", PATTACH_OVERHEAD_FOLLOW, self:GetParent() )
|
||||
self:AddParticle( nOverheadFX, false, false, -1, false, false )
|
||||
end
|
||||
|
||||
local radius = self:GetAbility():GetSpecialValueFor( "radius" )
|
||||
|
||||
local nFXIndex = ParticleManager:CreateParticle( "particles/dark_moon/darkmoon_calldown_marker_ring.vpcf", PATTACH_CUSTOMORIGIN, nil )
|
||||
ParticleManager:SetParticleControlEnt( nFXIndex, 0, self:GetParent(), PATTACH_ABSORIGIN_FOLLOW, nil, self:GetParent():GetAbsOrigin(), true )
|
||||
ParticleManager:SetParticleControl( nFXIndex, 1, Vector( radius, radius, radius ) )
|
||||
ParticleManager:SetParticleControl( nFXIndex, 2, Vector( delay, delay, delay ) )
|
||||
ParticleManager:ReleaseParticleIndex( nFXIndex )
|
||||
end
|
||||
end
|
||||
|
||||
---------------------------------------------------------
|
||||
|
||||
function modifier_bomber_death_explosion:CheckState()
|
||||
if self.is_ascension_ability == 1 then
|
||||
return {}
|
||||
end
|
||||
|
||||
local state =
|
||||
{
|
||||
[MODIFIER_STATE_INVULNERABLE] = true,
|
||||
[MODIFIER_STATE_ROOTED] = true,
|
||||
[MODIFIER_STATE_DISARMED] = true,
|
||||
[MODIFIER_STATE_NO_HEALTH_BAR] = true,
|
||||
[MODIFIER_STATE_UNSELECTABLE] = true,
|
||||
}
|
||||
|
||||
return state
|
||||
end
|
||||
|
||||
--------------------------------------------------------------
|
||||
|
||||
function modifier_bomber_death_explosion:DeclareFunctions()
|
||||
local funcs =
|
||||
{
|
||||
MODIFIER_PROPERTY_MIN_HEALTH,
|
||||
MODIFIER_PROPERTY_MODEL_SCALE
|
||||
}
|
||||
|
||||
return funcs
|
||||
end
|
||||
-------------------------------------------------------------------
|
||||
|
||||
function modifier_bomber_death_explosion:OnIntervalThink()
|
||||
if not IsServer() then
|
||||
return
|
||||
end
|
||||
|
||||
if self:GetAbility() == nil then
|
||||
return
|
||||
end
|
||||
|
||||
local damage = self:GetAbility():GetSpecialValueFor( "damage" )
|
||||
local radius = self:GetAbility():GetSpecialValueFor( "radius" )
|
||||
|
||||
EmitSoundOn( "Ability.Bomber.Detonate", self:GetParent() )
|
||||
|
||||
local nFXIndex2 = ParticleManager:CreateParticle( "particles/units/heroes/hero_techies/techies_remote_mines_detonate.vpcf", PATTACH_CUSTOMORIGIN, nil )
|
||||
ParticleManager:SetParticleControl( nFXIndex2, 0, self:GetParent():GetOrigin() )
|
||||
ParticleManager:SetParticleControl( nFXIndex2, 1, Vector( radius, radius, radius ) )
|
||||
ParticleManager:ReleaseParticleIndex( nFXIndex2 )
|
||||
|
||||
local nTeam = DOTA_UNIT_TARGET_TEAM_ENEMY
|
||||
if self.is_ascension_ability == 1 then
|
||||
nTeam = DOTA_UNIT_TARGET_TEAM_FRIENDLY
|
||||
end
|
||||
|
||||
local entities = FindUnitsInRadius( self:GetParent():GetTeamNumber(), self:GetParent():GetOrigin(), nil, radius, nTeam,
|
||||
DOTA_UNIT_TARGET_HERO + DOTA_UNIT_TARGET_BASIC, DOTA_UNIT_TARGET_FLAG_MAGIC_IMMUNE_ENEMIES, FIND_CLOSEST, false )
|
||||
|
||||
if #entities > 0 then
|
||||
for _,entity in pairs(entities) do
|
||||
if entity ~= nil and entity:IsNull() == false and entity ~= self:GetParent() and ( not entity:IsMagicImmune() ) and ( not entity:IsInvulnerable() ) then
|
||||
local DamageInfo =
|
||||
{
|
||||
victim = entity,
|
||||
attacker = self:GetCaster(),
|
||||
ability = self,
|
||||
damage = damage,
|
||||
damage_type = DAMAGE_TYPE_MAGICAL,
|
||||
}
|
||||
if self.is_ascension_ability == 1 then
|
||||
DamageInfo.damage = DamageInfo.damage * entity:GetMaxHealth() / 100.0
|
||||
DamageInfo.damage_type = DAMAGE_TYPE_PURE
|
||||
end
|
||||
ApplyDamage( DamageInfo )
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
if self.is_ascension_ability == 0 then
|
||||
self:GetParent():AddEffects( EF_NODRAW )
|
||||
self:GetParent():ForceKill( false )
|
||||
else
|
||||
self:Destroy()
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
function modifier_bomber_death_explosion:GetMinHealth( params )
|
||||
if IsServer() and self.is_ascension_ability == 0 then
|
||||
return 1
|
||||
end
|
||||
return 0
|
||||
end
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
function modifier_bomber_death_explosion:GetModifierModelScale( params )
|
||||
if self:GetCaster() == nil then
|
||||
return 0
|
||||
end
|
||||
|
||||
if self:GetCaster():PassivesDisabled() or self.is_ascension_ability == 1 then
|
||||
return 0
|
||||
end
|
||||
|
||||
return 70
|
||||
end
|
||||
@@ -0,0 +1,45 @@
|
||||
|
||||
modifier_bomber_death_explosion_trigger = class({})
|
||||
|
||||
--------------------------------------------------------------
|
||||
|
||||
function modifier_bomber_death_explosion_trigger:IsHidden()
|
||||
return true
|
||||
end
|
||||
|
||||
--------------------------------------------------------------
|
||||
|
||||
function modifier_bomber_death_explosion_trigger:IsPurgable()
|
||||
return false
|
||||
end
|
||||
|
||||
--------------------------------------------------------------
|
||||
|
||||
function modifier_bomber_death_explosion_trigger:DeclareFunctions()
|
||||
local funcs =
|
||||
{
|
||||
MODIFIER_EVENT_ON_TAKEDAMAGE_KILLCREDIT,
|
||||
}
|
||||
|
||||
return funcs
|
||||
end
|
||||
-------------------------------------------------------------------
|
||||
|
||||
function modifier_bomber_death_explosion_trigger:OnTakeDamageKillCredit( params )
|
||||
if IsServer() then
|
||||
local flDamage = params.damage
|
||||
|
||||
--printf( 'Take Damage Kill Credit, damage = %f', flDamage )
|
||||
|
||||
if params.target == self:GetParent() then
|
||||
local health = self:GetParent():GetHealth()
|
||||
--printf( 'health = %d, damage = %f\n', health, flDamage )
|
||||
if flDamage >= health then
|
||||
self:GetParent():AddNewModifier( self:GetCaster(), self:GetAbility(), "modifier_bomber_death_explosion", { delay = 2 } )
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
return 0
|
||||
end
|
||||
@@ -0,0 +1,59 @@
|
||||
|
||||
modifier_bomber_suicide_on_attack = class({})
|
||||
|
||||
--------------------------------------------------------------
|
||||
|
||||
function modifier_bomber_suicide_on_attack:IsHidden()
|
||||
return true
|
||||
end
|
||||
|
||||
--------------------------------------------------------------
|
||||
|
||||
function modifier_bomber_suicide_on_attack:IsPurgable()
|
||||
return false
|
||||
end
|
||||
|
||||
--------------------------------------------------------------
|
||||
|
||||
function modifier_bomber_suicide_on_attack:OnCreated( kv )
|
||||
self.suicide_chance = 0
|
||||
local hAbility = self:GetAbility()
|
||||
if hAbility ~= nil then
|
||||
self.suicide_chance = hAbility:GetSpecialValueFor( "suicide_chance" )
|
||||
else
|
||||
print( 'modifier_bomber_suicide_on_attack:OnCreated() - hAbility is nil????' )
|
||||
end
|
||||
end
|
||||
|
||||
--------------------------------------------------------------
|
||||
|
||||
function modifier_bomber_suicide_on_attack:DeclareFunctions()
|
||||
local funcs =
|
||||
{
|
||||
MODIFIER_EVENT_ON_ATTACK_LANDED
|
||||
}
|
||||
|
||||
return funcs
|
||||
end
|
||||
|
||||
--------------------------------------------------------------
|
||||
|
||||
function modifier_bomber_suicide_on_attack:OnAttackLanded( params )
|
||||
if IsServer() then
|
||||
if params.attacker == self:GetParent() and RollPercentage( self.suicide_chance ) then
|
||||
local damage = self:GetParent():GetHealth() + 1
|
||||
local DamageInfo =
|
||||
{
|
||||
victim = self:GetParent(),
|
||||
attacker = self:GetParent(),
|
||||
ability = self:GetAbility(),
|
||||
damage = damage,
|
||||
damage_type = DAMAGE_TYPE_PURE,
|
||||
}
|
||||
ApplyDamage( DamageInfo )
|
||||
end
|
||||
end
|
||||
|
||||
return 0
|
||||
end
|
||||
|
||||
@@ -0,0 +1,272 @@
|
||||
modifier_boss_timbersaw_chakram_dance = class({})
|
||||
|
||||
-----------------------------------------------------------------------------
|
||||
|
||||
function modifier_boss_timbersaw_chakram_dance:IsHidden()
|
||||
return true
|
||||
end
|
||||
|
||||
-----------------------------------------------------------------------------
|
||||
|
||||
function modifier_boss_timbersaw_chakram_dance:IsPurgable()
|
||||
return false
|
||||
end
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
function modifier_boss_timbersaw_chakram_dance:GetPriority()
|
||||
return MODIFIER_PRIORITY_SUPER_ULTRA
|
||||
end
|
||||
|
||||
-----------------------------------------------------------------------------------------
|
||||
|
||||
function modifier_boss_timbersaw_chakram_dance:CheckState()
|
||||
local state =
|
||||
{
|
||||
[MODIFIER_STATE_HEXED] = false,
|
||||
[MODIFIER_STATE_ROOTED] = false,
|
||||
[MODIFIER_STATE_SILENCED] = false,
|
||||
[MODIFIER_STATE_STUNNED] = false,
|
||||
}
|
||||
return state
|
||||
end
|
||||
|
||||
-----------------------------------------------------------------------------
|
||||
|
||||
function modifier_boss_timbersaw_chakram_dance:OnCreated( kv )
|
||||
if IsServer() then
|
||||
|
||||
self.is_ascension_ability = kv[ "is_ascension_ability" ]
|
||||
self.num_chakrams = self:GetAbility():GetSpecialValueFor( "num_chakrams" )
|
||||
self.interval = self:GetAbility():GetSpecialValueFor( "interval" )
|
||||
self.short_range = self:GetAbility():GetSpecialValueFor( "short_range" )
|
||||
self.long_range = self:GetAbility():GetSpecialValueFor( "long_range" )
|
||||
|
||||
local flInterval = self.interval
|
||||
if self.is_ascension_ability == 1 then
|
||||
flInterval = self:GetAbility():GetSpecialValueFor( "spawn_interval" )
|
||||
self.spawn_count = self:GetAbility():GetSpecialValueFor( "spawn_count" )
|
||||
end
|
||||
|
||||
self.radius = kv[ "radius" ]
|
||||
self.nAngleStepPerChakram = 360 / self.num_chakrams
|
||||
self.nAngleStepPerInterval = self.nAngleStepPerChakram / 2
|
||||
self.bLongRange = true
|
||||
self.Angle = QAngle( 0, 0, 0 )
|
||||
self.Chakrams = {}
|
||||
|
||||
self:StartIntervalThink( flInterval )
|
||||
self:OnIntervalThink()
|
||||
end
|
||||
end
|
||||
|
||||
-----------------------------------------------------------------------------
|
||||
|
||||
function modifier_boss_timbersaw_chakram_dance:OnDestroy()
|
||||
if IsServer() then
|
||||
for _,Chakram in pairs ( self.Chakrams ) do
|
||||
if Chakram.bReturning == false then
|
||||
local vLocation = ProjectileManager:GetLinearProjectileLocation( Chakram.nProjectileHandle )
|
||||
self:ReturnChakram( Chakram, vLocation )
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
-----------------------------------------------------------------------------
|
||||
|
||||
function modifier_boss_timbersaw_chakram_dance:OnIntervalThink()
|
||||
if IsServer() then
|
||||
|
||||
local Angle = QAngle( self.Angle.x, self.Angle.y, self.Angle.z )
|
||||
|
||||
for i=1,self.num_chakrams do
|
||||
local flDist = self.short_range
|
||||
if self.bLongRange == true then
|
||||
flDist = self.long_range
|
||||
end
|
||||
|
||||
local flSpeed = ( flDist / self.interval ) * 2 -- need enough time to go out and back
|
||||
local vVelocity = ( RotatePosition( Vector( 0, 0, 0 ), Angle, Vector( 1, 0, 0 ) ) ) * flSpeed
|
||||
|
||||
self:LaunchOutgoingChakram( vVelocity, flDist )
|
||||
|
||||
self.bLongRange = not self.bLongRange
|
||||
Angle.y = Angle.y + self.nAngleStepPerChakram
|
||||
end
|
||||
EmitSoundOn( "Boss_Timbersaw.Chakram.Cast", self:GetParent() )
|
||||
self.Angle.y = self.Angle.y + self.nAngleStepPerInterval
|
||||
|
||||
if self.is_ascension_ability == 1 then
|
||||
self.spawn_count = self.spawn_count - 1
|
||||
if self.spawn_count <= 0 then
|
||||
self:StartIntervalThink( -1 )
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
function modifier_boss_timbersaw_chakram_dance:ChooseRandomPointsOnEdges()
|
||||
|
||||
local hRoom = self:GetCaster().Encounter:GetRoom()
|
||||
local vMins = hRoom:GetMins()
|
||||
local vMaxs = hRoom:GetMaxs()
|
||||
local vDelta = ( vMaxs - vMins ) * 0.15
|
||||
local vClampedMins = Vector( vMins.x + vDelta.x, vMins.y + vDelta.y, vMins.z )
|
||||
local vClampedMaxs = Vector( vMaxs.x - vDelta.x, vMaxs.y - vDelta.y, vMaxs.z )
|
||||
local retVal =
|
||||
{
|
||||
vSpawnOrigin = Vector( vClampedMins.x, vClampedMins.y, vMins.z ),
|
||||
vDestination = Vector( vClampedMaxs.x, vClampedMaxs.y, vMaxs.z ),
|
||||
}
|
||||
|
||||
local nSide = math.random( 1,4 )
|
||||
if nSide <= 2 then
|
||||
if nSide == 1 then
|
||||
retVal.vSpawnOrigin.x = vMins.x
|
||||
retVal.vDestination.x = vMaxs.x
|
||||
else
|
||||
retVal.vSpawnOrigin.x = vMaxs.x
|
||||
retVal.vDestination.x = vMins.x
|
||||
end
|
||||
retVal.vSpawnOrigin.y = RandomFloat( vClampedMins.y, vClampedMaxs.y )
|
||||
retVal.vDestination.y = RandomFloat( vClampedMins.y, vClampedMaxs.y )
|
||||
else
|
||||
if nSide == 3 then
|
||||
retVal.vSpawnOrigin.y = vMins.y
|
||||
retVal.vDestination.y = vMaxs.y
|
||||
else
|
||||
retVal.vSpawnOrigin.y = vMaxs.y
|
||||
retVal.vDestination.y = vMins.y
|
||||
end
|
||||
retVal.vSpawnOrigin.x = RandomFloat( vClampedMins.x, vClampedMaxs.x )
|
||||
retVal.vDestination.x = RandomFloat( vClampedMins.x, vClampedMaxs.x )
|
||||
end
|
||||
|
||||
retVal.vDestination.z = retVal.vSpawnOrigin.z
|
||||
|
||||
return retVal
|
||||
|
||||
end
|
||||
|
||||
-----------------------------------------------------------------------------
|
||||
|
||||
function modifier_boss_timbersaw_chakram_dance:LaunchOutgoingChakram( vVel, flDist )
|
||||
if IsServer() then
|
||||
|
||||
local projectileInfo =
|
||||
{
|
||||
Ability = self:GetAbility(),
|
||||
vSpawnOrigin = self:GetCaster():GetAbsOrigin(),
|
||||
fStartRadius = self.radius,
|
||||
fEndRadius = self.radius,
|
||||
vVelocity = vVel,
|
||||
fDistance = flDist,
|
||||
Source = self:GetParent(),
|
||||
iUnitTargetTeam = DOTA_UNIT_TARGET_TEAM_ENEMY,
|
||||
iUnitTargetType = DOTA_UNIT_TARGET_HERO + DOTA_UNIT_TARGET_BASIC,
|
||||
}
|
||||
|
||||
local Chakram = {}
|
||||
|
||||
local flSpeed = vVel:Length2D()
|
||||
if self.is_ascension_ability == 1 then
|
||||
local pts = self:ChooseRandomPointsOnEdges()
|
||||
projectileInfo.vSpawnOrigin = pts.vSpawnOrigin
|
||||
projectileInfo.vVelocity = ( pts.vDestination - pts.vSpawnOrigin ):Normalized() * flSpeed
|
||||
Chakram.vReturnLocation = projectileInfo.vSpawnOrigin
|
||||
end
|
||||
|
||||
if flDist == self.long_range then
|
||||
projectileInfo[ "EffectName" ] = "particles/units/heroes/hero_shredder/shredder_chakram.vpcf"
|
||||
Chakram.bBlue = false
|
||||
else
|
||||
projectileInfo[ "EffectName" ] = "particles/units/heroes/hero_shredder/shredder_chakram_aghs.vpcf"
|
||||
Chakram.bBlue = true
|
||||
end
|
||||
Chakram.flDist = flDist
|
||||
Chakram.flSpeed = flSpeed
|
||||
Chakram.bReturning = false
|
||||
Chakram.nProjectileHandle = ProjectileManager:CreateLinearProjectile( projectileInfo )
|
||||
table.insert( self.Chakrams, Chakram.nProjectileHandle, Chakram )
|
||||
end
|
||||
end
|
||||
|
||||
-----------------------------------------------------------------------------
|
||||
|
||||
function modifier_boss_timbersaw_chakram_dance:LaunchIncomingChakram( vSpawnOrigin, vReturnLocation, flSpeed, flDist )
|
||||
if IsServer() then
|
||||
|
||||
if vReturnLocation == nil then
|
||||
vReturnLocation = self:GetParent():GetAbsOrigin()
|
||||
flSpeed = flDist -- Seems like a bug in the original boss encounter, but preserving the behavior
|
||||
end
|
||||
|
||||
local vDir = vReturnLocation - vSpawnOrigin
|
||||
vDir.z = 0.0
|
||||
vDir = vDir:Normalized()
|
||||
|
||||
local projectileInfo =
|
||||
{
|
||||
Ability = self:GetAbility(),
|
||||
vSpawnOrigin = vSpawnOrigin,
|
||||
fStartRadius = self.radius,
|
||||
fEndRadius = self.radius,
|
||||
vVelocity = vDir * flSpeed,
|
||||
fDistance = flDist,
|
||||
Source = self:GetCaster(),
|
||||
iUnitTargetTeam = DOTA_UNIT_TARGET_TEAM_ENEMY,
|
||||
iUnitTargetType = DOTA_UNIT_TARGET_HERO + DOTA_UNIT_TARGET_BASIC,
|
||||
}
|
||||
|
||||
local Chakram = {}
|
||||
if flDist == self.long_range then
|
||||
projectileInfo[ "EffectName" ] = "particles/units/heroes/hero_shredder/shredder_chakram.vpcf"
|
||||
Chakram.bBlue = false
|
||||
else
|
||||
projectileInfo[ "EffectName" ] = "particles/units/heroes/hero_shredder/shredder_chakram_aghs.vpcf"
|
||||
Chakram.bBlue = true
|
||||
end
|
||||
|
||||
Chakram.bReturning = true
|
||||
Chakram.nProjectileHandle = ProjectileManager:CreateLinearProjectile( projectileInfo )
|
||||
table.insert( self.Chakrams, Chakram.nProjectileHandle, Chakram )
|
||||
ProjectileManager:CreateLinearProjectile( projectileInfo )
|
||||
end
|
||||
end
|
||||
|
||||
-----------------------------------------------------------------------------
|
||||
|
||||
function modifier_boss_timbersaw_chakram_dance:ReturnChakram( Chakram, vLocation )
|
||||
if IsServer() then
|
||||
for k,v in pairs ( self.Chakrams ) do
|
||||
if v == Chakram and v.bReturning == false then
|
||||
Chakram.bReturning = true
|
||||
EmitSoundOnLocationWithCaster( vLocation, "Boss_Timbersaw.Chakram.Return", self:GetParent() )
|
||||
self:LaunchIncomingChakram( vLocation, Chakram.vReturnLocation, Chakram.flSpeed, Chakram.flDist )
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
-----------------------------------------------------------------------------
|
||||
|
||||
function modifier_boss_timbersaw_chakram_dance:DestroyChakram( Chakram )
|
||||
if IsServer() then
|
||||
for k,v in pairs ( self.Chakrams ) do
|
||||
if v == Chakram then
|
||||
table.remove( self.Chakrams, k )
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
-----------------------------------------------------------------------------
|
||||
|
||||
function modifier_boss_timbersaw_chakram_dance:GetChakram( nProjectileHandle )
|
||||
return self.Chakrams[ nProjectileHandle ]
|
||||
end
|
||||
|
||||
-----------------------------------------------------------------------------
|
||||
@@ -0,0 +1,265 @@
|
||||
modifier_boss_timbersaw_reactive_armor = class({})
|
||||
|
||||
-----------------------------------------------------------------------------------------
|
||||
|
||||
function modifier_boss_timbersaw_reactive_armor:constructor()
|
||||
self.max_stacks = 0
|
||||
self.armor_per_stack = 0
|
||||
self.magic_resist_per_stack = 0
|
||||
self.regen_per_stack = 0
|
||||
self.bEnraged = false
|
||||
end
|
||||
|
||||
-----------------------------------------------------------------------------------------
|
||||
|
||||
function modifier_boss_timbersaw_reactive_armor:IsHidden()
|
||||
return false
|
||||
end
|
||||
|
||||
-----------------------------------------------------------------------------------------
|
||||
|
||||
function modifier_boss_timbersaw_reactive_armor:IsPurgable()
|
||||
return false
|
||||
end
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
function modifier_boss_timbersaw_reactive_armor:GetPriority()
|
||||
return MODIFIER_PRIORITY_ULTRA
|
||||
end
|
||||
|
||||
-----------------------------------------------------------------------------------------
|
||||
|
||||
function modifier_boss_timbersaw_reactive_armor:OnCreated( kv )
|
||||
self.max_stacks = self:GetAbility():GetSpecialValueFor( "max_stacks" )
|
||||
self.armor_per_stack = self:GetAbility():GetSpecialValueFor( "armor_per_stack" )
|
||||
self.magic_resist_per_stack = self:GetAbility():GetSpecialValueFor( "magic_resist_per_stack" )
|
||||
self.regen_per_stack = self:GetAbility():GetSpecialValueFor( "regen_per_stack" )
|
||||
self.status_resist =self:GetAbility():GetSpecialValueFor( "status_resist" )
|
||||
self.nPhysicalMode = 0
|
||||
self.bEnraged = false
|
||||
self.nModeFX = -1
|
||||
self.ParticleIndices = {}
|
||||
|
||||
if IsServer() then
|
||||
CustomNetTables:SetTableValue( "boss_net_table", "boss_timbersaw", { physical = self.nPhysicalMode } )
|
||||
|
||||
|
||||
|
||||
self:SwitchMode()
|
||||
else
|
||||
|
||||
|
||||
for i=1,4 do
|
||||
local szParticlename = string.format( "particles/creatures/boss_timbersaw/shredder_armor_lyr%d.vpcf", i )
|
||||
local nFXIndex = ParticleManager:CreateParticle( szParticlename, PATTACH_CUSTOMORIGIN, self:GetParent() )
|
||||
ParticleManager:SetParticleControlEnt( nFXIndex, 0, self:GetParent(), PATTACH_POINT_FOLLOW, "attach_armor", self:GetParent():GetAbsOrigin(), true )
|
||||
ParticleManager:SetParticleControlEnt( nFXIndex, 1, self:GetParent(), PATTACH_ABSORIGIN_FOLLOW, nil, self:GetParent():GetAbsOrigin(), true )
|
||||
ParticleManager:SetParticleControl( nFXIndex, 2, Vector( 0, 0, 0 ) )
|
||||
ParticleManager:SetParticleControl( nFXIndex, 3, Vector( 0, 0, 0 ) )
|
||||
ParticleManager:SetParticleControlEnt( nFXIndex, 4, self:GetParent(), PATTACH_POINT_FOLLOW, "attach_chimmney", self:GetParent():GetAbsOrigin(), true )
|
||||
ParticleManager:SetParticleControl( nFXIndex, 5, Vector( 2.0, 0, 0 ) )
|
||||
self:AddParticle( nFXIndex, false, false, -1, false, false )
|
||||
|
||||
table.insert( self.ParticleIndices, nFXIndex )
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
-----------------------------------------------------------------------------------------
|
||||
|
||||
function modifier_boss_timbersaw_reactive_armor:OnRefresh( kv )
|
||||
if IsServer() then
|
||||
local netTable = {}
|
||||
netTable[ "physical" ] = self.nPhysicalMode
|
||||
if self:GetParent().AI and self:GetParent().AI.bEnraged then
|
||||
netTable[ "enraged" ] = 1
|
||||
else
|
||||
netTable[ "enraged" ] = 0
|
||||
end
|
||||
CustomNetTables:SetTableValue( "boss_net_table", "boss_timbersaw", netTable )
|
||||
else
|
||||
local netTable = CustomNetTables:GetTableValue( "boss_net_table", "boss_timbersaw" )
|
||||
self.nPhysicalMode = netTable[ "physical" ]
|
||||
self.bEnraged = true
|
||||
end
|
||||
end
|
||||
|
||||
-----------------------------------------------------------------------------------------
|
||||
|
||||
function modifier_boss_timbersaw_reactive_armor:CheckState()
|
||||
local state =
|
||||
{
|
||||
--[MODIFIER_STATE_HEXED] = false,
|
||||
--[MODIFIER_STATE_ROOTED] = false,
|
||||
--[MODIFIER_STATE_SILENCED] = false,
|
||||
[MODIFIER_STATE_NO_HEALTH_BAR] = true,
|
||||
}
|
||||
return state
|
||||
end
|
||||
|
||||
-----------------------------------------------------------------------------------------
|
||||
|
||||
function modifier_boss_timbersaw_reactive_armor:DeclareFunctions()
|
||||
local funcs =
|
||||
{
|
||||
MODIFIER_EVENT_ON_TAKEDAMAGE,
|
||||
MODIFIER_PROPERTY_HEALTH_REGEN_CONSTANT,
|
||||
MODIFIER_PROPERTY_PHYSICAL_ARMOR_BONUS,
|
||||
MODIFIER_PROPERTY_MAGICAL_RESISTANCE_BONUS,
|
||||
MODIFIER_PROPERTY_STATUS_RESISTANCE_STACKING,
|
||||
MODIFIER_PROPERTY_MOVESPEED_BONUS_PERCENTAGE,
|
||||
}
|
||||
return funcs
|
||||
end
|
||||
|
||||
-----------------------------------------------------------------------------------------
|
||||
|
||||
function modifier_boss_timbersaw_reactive_armor:OnTakeDamage( params )
|
||||
if IsServer() then
|
||||
local hAttacker = params.attacker
|
||||
local hVictim = params.unit
|
||||
if hAttacker ~= nil and hVictim ~= nil and hVictim == self:GetParent() then
|
||||
if hVictim:FindModifierByName( "modifier_provide_vision" ) == nil then
|
||||
--printf( "Provide Vision" )
|
||||
hVictim:AddNewModifier( hAttacker, self:GetAbility(), "modifier_provide_vision", { duration = -1 } )
|
||||
end
|
||||
|
||||
if params.original_damage > 50 then
|
||||
local nFXIndex = ParticleManager:CreateParticle( "particles/units/heroes/hero_shredder/shredder_reactive_hit.vpcf", PATTACH_CUSTOMORIGIN, self:GetParent() )
|
||||
ParticleManager:SetParticleControlEnt( nFXIndex, 0, self:GetParent(), PATTACH_POINT_FOLLOW, "attach_chimmney", self:GetParent():GetAbsOrigin(), true )
|
||||
ParticleManager:SetParticleControlEnt( nFXIndex, 1, self:GetParent(), PATTACH_ABSORIGIN_FOLLOW, nil, self:GetParent():GetAbsOrigin(), true )
|
||||
ParticleManager:SetParticleControlEnt( nFXIndex, 2, self:GetParent(), PATTACH_POINT_FOLLOW, "attach_hitloc", self:GetParent():GetAbsOrigin(), true )
|
||||
ParticleManager:ReleaseParticleIndex( nFXIndex )
|
||||
|
||||
self:IncrementStackCount()
|
||||
EmitSoundOn( "Hero_Shredder.ReactiveArmor", self:GetParent() )
|
||||
if self:GetStackCount() >= self.max_stacks then
|
||||
self:SwitchMode()
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
return 0
|
||||
end
|
||||
|
||||
-----------------------------------------------------------------------------------------
|
||||
|
||||
function modifier_boss_timbersaw_reactive_armor:OnStackCountChanged( nOldCount )
|
||||
|
||||
|
||||
local nNewCount = self:GetStackCount()
|
||||
|
||||
local nStacksPerLayer = self.max_stacks / 4
|
||||
local nNumLayers = math.floor( nNewCount / nStacksPerLayer ) + 1
|
||||
|
||||
if IsServer() then
|
||||
if self.bEnraged == true then
|
||||
return
|
||||
end
|
||||
|
||||
|
||||
if self:GetParent().AI and self:GetParent().AI.bEnraged == true and self.bEnraged == false then
|
||||
self.bEnraged = true
|
||||
nNumLayers = 4
|
||||
end
|
||||
else
|
||||
|
||||
for _,nFXIndex in pairs ( self.ParticleIndices ) do
|
||||
if nNumLayers > 0 then
|
||||
ParticleManager:SetParticleControl( nFXIndex, 2, Vector( 1, 0, 0 ) )
|
||||
nNumLayers = nNumLayers - 1
|
||||
else
|
||||
ParticleManager:SetParticleControl( nFXIndex, 2, Vector( 0, 0, 0 ) )
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
-----------------------------------------------------------------------------------------
|
||||
|
||||
function modifier_boss_timbersaw_reactive_armor:SwitchMode()
|
||||
if IsServer() then
|
||||
if self.nPhysicalMode == 1 then
|
||||
self.nPhysicalMode = 0
|
||||
else
|
||||
self.nPhysicalMode = 1
|
||||
end
|
||||
|
||||
CustomNetTables:SetTableValue( "boss_net_table", "boss_timbersaw", { physical = self.nPhysicalMode } )
|
||||
self:SetStackCount( 0 )
|
||||
self:SendBuffRefreshToClients()
|
||||
--todo, toggle the visibility on the shield
|
||||
|
||||
local nFXIndex = nil
|
||||
ParticleManager:DestroyParticle( self.nModeFX, false )
|
||||
self.nModeFX = -1
|
||||
if self.nPhysicalMode == 1 then
|
||||
EmitSoundOn( "Item.CrimsonGuard.Cast", self:GetParent() )
|
||||
nFXIndex = ParticleManager:CreateParticle( "particles/items2_fx/vanguard_active_launch.vpcf", PATTACH_OVERHEAD_FOLLOW, self:GetParent() )
|
||||
ParticleManager:SetParticleControlEnt( nFXIndex, 1, self:GetParent(), PATTACH_ABSORIGIN_FOLLOW, nil, self:GetParent():GetAbsOrigin(), true )
|
||||
ParticleManager:SetParticleControl( nFXIndex, 2, Vector( 500, 0, 0 ) )
|
||||
ParticleManager:ReleaseParticleIndex( nFXIndex )
|
||||
|
||||
self.nModeFX = ParticleManager:CreateParticle( "particles/items2_fx/vanguard_active.vpcf", PATTACH_OVERHEAD_FOLLOW, self:GetCaster() )
|
||||
ParticleManager:SetParticleControlEnt( nFXIndex, 1, self:GetParent(), PATTACH_ABSORIGIN_FOLLOW, nil, self:GetCaster():GetAbsOrigin(), true )
|
||||
ParticleManager:SetParticleControl( nFXIndex, 2, Vector( 500, 0, 0 ) )
|
||||
else
|
||||
EmitSoundOn( "DOTA_Item.Pipe.Activate", self:GetParent() )
|
||||
nFXIndex = ParticleManager:CreateParticle( "particles/items2_fx/pipe_of_insight_launch.vpcf", PATTACH_OVERHEAD_FOLLOW, self:GetCaster() )
|
||||
ParticleManager:SetParticleControlEnt( nFXIndex, 1, self:GetCaster(), PATTACH_ABSORIGIN_FOLLOW, nil, self:GetCaster():GetAbsOrigin(), true )
|
||||
ParticleManager:SetParticleControl( nFXIndex, 2, Vector( 500, 0, 0 ) )
|
||||
ParticleManager:ReleaseParticleIndex( nFXIndex )
|
||||
|
||||
self.nModeFX = ParticleManager:CreateParticle( "particles/items2_fx/pipe_of_insight.vpcf", PATTACH_OVERHEAD_FOLLOW, self:GetCaster() )
|
||||
ParticleManager:SetParticleControlEnt( nFXIndex, 1, self:GetParent(), PATTACH_ABSORIGIN_FOLLOW, nil, self:GetCaster():GetAbsOrigin(), true )
|
||||
ParticleManager:SetParticleControl( nFXIndex, 2, Vector( 500, 0, 0 ) )
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
-----------------------------------------------------------------------------------------
|
||||
|
||||
function modifier_boss_timbersaw_reactive_armor:GetModifierConstantHealthRegen( params )
|
||||
return self:GetStackCount() * self.regen_per_stack
|
||||
end
|
||||
|
||||
-----------------------------------------------------------------------------------------
|
||||
|
||||
function modifier_boss_timbersaw_reactive_armor:GetModifierPhysicalArmorBonus( params )
|
||||
if self.nPhysicalMode == 1 then
|
||||
return self:GetStackCount() * self.armor_per_stack
|
||||
end
|
||||
return 0
|
||||
end
|
||||
|
||||
-----------------------------------------------------------------------------------------
|
||||
|
||||
function modifier_boss_timbersaw_reactive_armor:GetModifierMagicalResistanceBonus( params )
|
||||
if self.nPhysicalMode == 0 then
|
||||
return self:GetStackCount() * self.magic_resist_per_stack
|
||||
end
|
||||
|
||||
return 0
|
||||
end
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
function modifier_boss_timbersaw_reactive_armor:GetModifierStatusResistanceStacking( params )
|
||||
if IsServer() then
|
||||
if self.bEnraged then
|
||||
return self.status_resist * 2
|
||||
end
|
||||
end
|
||||
return self.status_resist
|
||||
end
|
||||
|
||||
----------------------------------------
|
||||
|
||||
function modifier_boss_timbersaw_reactive_armor:GetModifierMoveSpeedBonus_Percentage( params )
|
||||
if self.bEnraged then
|
||||
return 50
|
||||
end
|
||||
|
||||
return 0
|
||||
end
|
||||
@@ -0,0 +1,71 @@
|
||||
modifier_boss_visage_familiar_passive = class({})
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
function modifier_boss_visage_familiar_passive:IsPurgable()
|
||||
return false
|
||||
end
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
function modifier_boss_visage_familiar_passive:IsHidden()
|
||||
return true
|
||||
end
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
function modifier_boss_visage_familiar_passive:OnCreated( kv )
|
||||
|
||||
end
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
function modifier_boss_visage_familiar_passive:DeclareFunctions()
|
||||
local funcs =
|
||||
{
|
||||
MODIFIER_PROPERTY_MIN_HEALTH,
|
||||
MODIFIER_EVENT_ON_TAKEDAMAGE,
|
||||
}
|
||||
return funcs
|
||||
end
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
function modifier_boss_visage_familiar_passive:GetMinHealth( params )
|
||||
return 1
|
||||
end
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
function modifier_boss_visage_familiar_passive:OnTakeDamage( params )
|
||||
if IsServer() then
|
||||
if params.unit == self:GetParent() and self:GetParent():GetHealthPercent() < 2 then
|
||||
self:GetAbility():OnSpellStart()
|
||||
|
||||
local vLocation = self:GetParent():GetAbsOrigin()
|
||||
if RollPercentage( HEALTH_POTION_DROP_PCT * 3 ) then
|
||||
local newItem = CreateItem( "item_health_potion", nil, nil )
|
||||
newItem:SetPurchaseTime( 0 )
|
||||
if newItem:IsPermanent() and newItem:GetShareability() == ITEM_FULLY_SHAREABLE then
|
||||
item:SetStacksWithOtherOwners( true )
|
||||
end
|
||||
|
||||
local drop = CreateItemOnPositionSync( vLocation, newItem )
|
||||
newItem:LaunchLoot( true, 300, 0.75, vLocation )
|
||||
end
|
||||
|
||||
if RollPercentage( MANA_POTION_DROP_PCT * 3 ) then
|
||||
local newItem = CreateItem( "item_mana_potion", nil, nil )
|
||||
newItem:SetPurchaseTime( 0 )
|
||||
if newItem:IsPermanent() and newItem:GetShareability() == ITEM_FULLY_SHAREABLE then
|
||||
item:SetStacksWithOtherOwners( true )
|
||||
end
|
||||
|
||||
local drop = CreateItemOnPositionSync( vLocation, newItem )
|
||||
newItem:LaunchLoot( true, 300, 0.75, vLocation )
|
||||
end
|
||||
|
||||
end
|
||||
end
|
||||
return 0
|
||||
end
|
||||
@@ -0,0 +1,89 @@
|
||||
modifier_boss_visage_familiar_statue_stone_form = class({})
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
function modifier_boss_visage_familiar_statue_stone_form:IsPurgable()
|
||||
return false
|
||||
end
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
function modifier_boss_visage_familiar_statue_stone_form:IsHidden()
|
||||
return true
|
||||
end
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
function modifier_boss_visage_familiar_statue_stone_form:GetPriority( )
|
||||
return MODIFIER_PRIORITY_HIGH + 6
|
||||
end
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
function modifier_boss_visage_familiar_statue_stone_form:GetStatusEffectName()
|
||||
return "particles/status_fx/status_effect_earth_spirit_petrify.vpcf";
|
||||
end
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
function modifier_boss_visage_familiar_statue_stone_form:AddCustomTransmitterData()
|
||||
end
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
function modifier_boss_visage_familiar_statue_stone_form:HandleCustomTransmitterData( entry )
|
||||
end
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
function modifier_boss_visage_familiar_statue_stone_form:OnCreated( kv )
|
||||
if IsServer() then
|
||||
self:SetStackCount( 0 )
|
||||
self:StartIntervalThink( 0.77 )
|
||||
end
|
||||
end
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
function modifier_boss_visage_familiar_statue_stone_form:OnIntervalThink()
|
||||
if IsServer() then
|
||||
self:IncrementStackCount()
|
||||
if self:GetStackCount() > 5 then
|
||||
self:StartIntervalThink( -1 )
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
-- --------------------------------------------------------------------------------
|
||||
|
||||
-- function modifier_boss_visage_familiar_stone_form_buff:DeclareFunctions()
|
||||
-- local funcs =
|
||||
-- {
|
||||
-- MODIFIER_PROPERTY_OVERRIDE_ANIMATION,
|
||||
-- MODIFIER_PROPERTY_OVERRIDE_ANIMATION_WEIGHT,
|
||||
-- }
|
||||
-- return funcs
|
||||
-- end
|
||||
|
||||
-- --------------------------------------------------------------------------------
|
||||
|
||||
-- function modifier_boss_visage_familiar_stone_form_buff
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
function modifier_boss_visage_familiar_statue_stone_form:CheckState()
|
||||
local bOnGround = self:GetStackCount() > 1
|
||||
local state = {}
|
||||
state[MODIFIER_STATE_FROZEN] = self:GetStackCount() > 5
|
||||
state[MODIFIER_STATE_STUNNED] = false
|
||||
state[MODIFIER_STATE_INVULNERABLE] = true
|
||||
state[MODIFIER_STATE_FLYING] = false
|
||||
state[MODIFIER_STATE_NO_UNIT_COLLISION] = true
|
||||
state[MODIFIER_STATE_UNSELECTABLE] = true
|
||||
state[MODIFIER_STATE_NO_HEALTH_BAR] = true
|
||||
state[MODIFIER_STATE_ROOTED] = true
|
||||
state[MODIFIER_STATE_DISARMED] = true
|
||||
state[MODIFIER_STATE_NOT_ON_MINIMAP] = true
|
||||
state[MODIFIER_STATE_PROVIDES_VISION] = true
|
||||
return state
|
||||
end
|
||||
@@ -0,0 +1,119 @@
|
||||
modifier_boss_visage_familiar_stone_form_buff = class({})
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
function modifier_boss_visage_familiar_stone_form_buff:IsPurgable()
|
||||
return false
|
||||
end
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
function modifier_boss_visage_familiar_stone_form_buff:GetPriority( )
|
||||
return MODIFIER_PRIORITY_HIGH + 6
|
||||
end
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
function modifier_boss_visage_familiar_stone_form_buff:GetStatusEffectName()
|
||||
return "particles/status_fx/status_effect_earth_spirit_petrify.vpcf";
|
||||
end
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
function modifier_boss_visage_familiar_stone_form_buff:AddCustomTransmitterData()
|
||||
end
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
function modifier_boss_visage_familiar_stone_form_buff:HandleCustomTransmitterData( entry )
|
||||
end
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
function modifier_boss_visage_familiar_stone_form_buff:OnCreated( kv )
|
||||
self.stun_delay = self:GetAbility():GetSpecialValueFor( "stun_delay" )
|
||||
self.damage_radius = self:GetAbility():GetSpecialValueFor( "damage_radius" )
|
||||
self.damage = self:GetAbility():GetSpecialValueFor( "damage" )
|
||||
self.stun_duration = self:GetAbility():GetSpecialValueFor( "stun_duration" )
|
||||
if IsServer() then
|
||||
self.bStunned = false
|
||||
self:SetStackCount( 0 )
|
||||
self:StartIntervalThink( self.stun_delay )
|
||||
end
|
||||
end
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
function modifier_boss_visage_familiar_stone_form_buff:OnIntervalThink()
|
||||
if IsServer() then
|
||||
if not self.bStunned then
|
||||
self.bStunned = true
|
||||
local nFXIndex = ParticleManager:CreateParticle( "particles/units/heroes/hero_visage/visage_stone_form.vpcf", PATTACH_WORLDORIGIN, nil )
|
||||
ParticleManager:SetParticleControl( nFXIndex, 0, self:GetParent():GetAbsOrigin() )
|
||||
ParticleManager:SetParticleControl( nFXIndex, 1, Vector( self.damage_radius, 1, 1 ) )
|
||||
ParticleManager:SetParticleFoWProperties( nFXIndex, 0, -1, self.damage_radius )
|
||||
ParticleManager:ReleaseParticleIndex( nFXIndex )
|
||||
|
||||
EmitSoundOn( "Visage_Familar.StoneForm.Cast", self:GetParent() )
|
||||
|
||||
|
||||
self:GetParent():Heal( 99999, self:GetAbility() )
|
||||
self:SendBuffRefreshToClients()
|
||||
|
||||
local enemies = FindUnitsInRadius( self:GetParent():GetTeamNumber(), self:GetParent():GetAbsOrigin(), self:GetParent(), self.damage_radius, DOTA_UNIT_TARGET_TEAM_ENEMY, DOTA_UNIT_TARGET_HERO + DOTA_UNIT_TARGET_BASIC, DOTA_UNIT_TARGET_FLAG_MAGIC_IMMUNE_ENEMIES, 0, false )
|
||||
for _,enemy in pairs( enemies ) do
|
||||
if enemy ~= nil and enemy:IsInvulnerable() == false then
|
||||
local damageInfo =
|
||||
{
|
||||
victim = enemy,
|
||||
attacker = self:GetCaster(),
|
||||
damage = self.damage,
|
||||
damage_type = DAMAGE_TYPE_MAGICAL,
|
||||
ability = self,
|
||||
}
|
||||
|
||||
ApplyDamage( damageInfo )
|
||||
|
||||
EmitSoundOn( "Visage_Familar.StoneForm.Stun", enemy )
|
||||
enemy:AddNewModifier( self:GetCaster(), self:GetAbility(), "modifier_stunned", { duration = self.stun_duration } )
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
end
|
||||
|
||||
self:IncrementStackCount()
|
||||
end
|
||||
end
|
||||
|
||||
-- --------------------------------------------------------------------------------
|
||||
|
||||
-- function modifier_boss_visage_familiar_stone_form_buff:DeclareFunctions()
|
||||
-- local funcs =
|
||||
-- {
|
||||
-- MODIFIER_PROPERTY_OVERRIDE_ANIMATION,
|
||||
-- MODIFIER_PROPERTY_OVERRIDE_ANIMATION_WEIGHT,
|
||||
-- }
|
||||
-- return funcs
|
||||
-- end
|
||||
|
||||
-- --------------------------------------------------------------------------------
|
||||
|
||||
-- function modifier_boss_visage_familiar_stone_form_buff
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
function modifier_boss_visage_familiar_stone_form_buff:CheckState()
|
||||
local bOnGround = self:GetStackCount() > 1
|
||||
local state = {}
|
||||
state[MODIFIER_STATE_FROZEN] = self:GetStackCount() > 5
|
||||
state[MODIFIER_STATE_STUNNED] = true
|
||||
state[MODIFIER_STATE_INVULNERABLE] = true
|
||||
state[MODIFIER_STATE_FLYING] = ( not bOnGround )
|
||||
state[MODIFIER_STATE_NO_UNIT_COLLISION] = true
|
||||
state[MODIFIER_STATE_NO_HEALTH_BAR] = true
|
||||
state[MODIFIER_STATE_NOT_ON_MINIMAP] = true
|
||||
state[MODIFIER_STATE_UNSELECTABLE] = true
|
||||
state[MODIFIER_STATE_PROVIDES_VISION] = true
|
||||
return state
|
||||
end
|
||||
@@ -0,0 +1,226 @@
|
||||
modifier_boss_visage_passive = class({})
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
function modifier_boss_visage_passive:IsPurgable()
|
||||
return false
|
||||
end
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
function modifier_boss_visage_passive:IsHidden()
|
||||
return true
|
||||
end
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
function modifier_boss_visage_passive:GetPriority()
|
||||
return MODIFIER_PRIORITY_ULTRA + 10000
|
||||
end
|
||||
|
||||
-----------------------------------------------------------------------------------------
|
||||
|
||||
function modifier_boss_visage_passive:CheckState()
|
||||
local state = {}
|
||||
|
||||
if IsServer() then
|
||||
state[MODIFIER_STATE_HEXED] = false
|
||||
state[MODIFIER_STATE_ROOTED] = true
|
||||
state[MODIFIER_STATE_SILENCED] = false
|
||||
state[MODIFIER_STATE_STUNNED] = self:GetParent().bStone
|
||||
state[MODIFIER_STATE_FROZEN] = self:GetParent().bStone
|
||||
state[MODIFIER_STATE_FEARED] = false
|
||||
state[MODIFIER_STATE_CANNOT_BE_MOTION_CONTROLLED] = true
|
||||
state[MODIFIER_STATE_INVULNERABLE] = self:GetParent().bStone
|
||||
state[MODIFIER_STATE_NOT_ON_MINIMAP_FOR_ENEMIES] = self:GetParent().bStone
|
||||
state[MODIFIER_STATE_NO_HEALTH_BAR] = true
|
||||
state[MODIFIER_STATE_FLYING_FOR_PATHING_PURPOSES_ONLY] = true
|
||||
state[MODIFIER_STATE_UNSELECTABLE] = self:GetParent().bStone
|
||||
end
|
||||
|
||||
return state
|
||||
end
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
function modifier_boss_visage_passive:DeclareFunctions()
|
||||
local funcs =
|
||||
{
|
||||
MODIFIER_PROPERTY_IGNORE_CAST_ANGLE,
|
||||
MODIFIER_PROPERTY_DISABLE_TURNING,
|
||||
MODIFIER_EVENT_ON_TAKEDAMAGE
|
||||
}
|
||||
return funcs
|
||||
end
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
function modifier_boss_visage_passive:OnCreated( kv )
|
||||
self.stone_threshold = self:GetAbility():GetSpecialValueFor( "stone_threshold" )
|
||||
self.soul_assumption_count = self:GetAbility():GetSpecialValueFor( "soul_assumption_count" )
|
||||
self.soul_assumption_damage = self:GetAbility():GetSpecialValueFor( "soul_assumption_damage" )
|
||||
self.soul_assumption_speed = self:GetAbility():GetSpecialValueFor( "soul_assumption_speed" )
|
||||
self.stone_duration = self:GetAbility():GetSpecialValueFor( "stone_duration" )
|
||||
self.familiar_wake_interval = self:GetAbility():GetSpecialValueFor( "familiar_wake_interval" )
|
||||
self.flStoneEndTime = -1
|
||||
self.flNextFamiliarTime = -1
|
||||
self.flAssumptionTime = -1
|
||||
self.nBonusSouls = 0
|
||||
self.Familiars = {}
|
||||
self.nStoneFX = -1
|
||||
self.nChannelFX = -1
|
||||
|
||||
self:GetParent().bStone = false
|
||||
|
||||
if IsServer() then
|
||||
self:StartIntervalThink( 0.25 )
|
||||
self.flDamageRemaining = self.stone_threshold
|
||||
self:GetAbility().Familiars = FindUnitsInRadius( self:GetParent():GetTeamNumber(), self:GetParent():GetAbsOrigin(), nil, FIND_UNITS_EVERYWHERE, DOTA_UNIT_TARGET_TEAM_FRIENDLY, DOTA_UNIT_TARGET_BASIC, DOTA_UNIT_TARGET_FLAG_MAGIC_IMMUNE_ENEMIES + DOTA_UNIT_TARGET_FLAG_INVULNERABLE, FIND_CLOSEST, false )
|
||||
for k,v in pairs ( self:GetAbility().Familiars ) do
|
||||
if v:GetUnitName() ~= "npc_dota_boss_visage_familiar" then
|
||||
table.remove( self:GetAbility().Familiars, k )
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
function modifier_boss_visage_passive:OnIntervalThink()
|
||||
if IsServer() then
|
||||
if self:GetParent().bStone == true and ( GameRules:GetGameTime() > self.flStoneEndTime ) then
|
||||
self:EndStoneForm()
|
||||
end
|
||||
|
||||
if self.flNextFamiliarTime ~= -1 and ( GameRules:GetGameTime() > self.flNextFamiliarTime ) then
|
||||
local StoneFamiliars = {}
|
||||
for k,v in pairs ( self:GetAbility().Familiars ) do
|
||||
if v:FindModifierByName( "modifier_boss_visage_familiar_stone_form_buff" ) then
|
||||
table.insert( StoneFamiliars, v )
|
||||
end
|
||||
end
|
||||
|
||||
if #StoneFamiliars > 0 then
|
||||
self:GetAbility():WakeFamiliar( StoneFamiliars[ RandomInt( 1, #StoneFamiliars ) ] )
|
||||
self.flNextFamiliarTime = GameRules:GetGameTime() + self.familiar_wake_interval
|
||||
end
|
||||
end
|
||||
|
||||
if self.flAssumptionTime ~= -1 and ( GameRules:GetGameTime() > self.flAssumptionTime ) then
|
||||
ParticleManager:DestroyParticle( self.nChannelFX, false )
|
||||
self:DoSoulAssumption()
|
||||
self.flAssumptionTime = -1
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
function modifier_boss_visage_passive:GetModifierIgnoreCastAngle( params )
|
||||
return 1
|
||||
end
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
function modifier_boss_visage_passive:GetModifierDisableTurning( params )
|
||||
return 1
|
||||
end
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
function modifier_boss_visage_passive:OnTakeDamage( params )
|
||||
if IsServer() then
|
||||
if params.unit == self:GetParent() and self:GetParent().bStone == false then
|
||||
self.flDamageRemaining = self.flDamageRemaining - params.damage
|
||||
if self.flDamageRemaining <= 0 then
|
||||
self:BeginStoneForm()
|
||||
end
|
||||
|
||||
if self.flNextFamiliarTime == -1 then
|
||||
self.flNextFamiliarTime = GameRules:GetGameTime() + self.familiar_wake_interval
|
||||
end
|
||||
end
|
||||
end
|
||||
return 0
|
||||
end
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
function modifier_boss_visage_passive:DoSoulAssumption()
|
||||
if IsServer() then
|
||||
local hAliveHeroes = FindUnitsInRadius( self:GetParent():GetTeamNumber(), self:GetParent():GetAbsOrigin(), nil, FIND_UNITS_EVERYWHERE, DOTA_UNIT_TARGET_TEAM_ENEMY, DOTA_UNIT_TARGET_HERO, DOTA_UNIT_TARGET_FLAG_MAGIC_IMMUNE_ENEMIES + DOTA_UNIT_TARGET_FLAG_INVULNERABLE, FIND_CLOSEST, false )
|
||||
local nNumberAlivePlayers = #hAliveHeroes
|
||||
local nSouls = self.soul_assumption_count - ( AGHANIM_PLAYERS - nNumberAlivePlayers )
|
||||
nSouls = nSouls + self.nBonusSouls
|
||||
self.nBonusSouls = self.nBonusSouls + 1
|
||||
|
||||
for _,hHero in pairs ( hAliveHeroes ) do
|
||||
nSouls = nSouls - 1
|
||||
self:LaunchSoulAssumption( hHero )
|
||||
end
|
||||
|
||||
local PossibleFamiliars = deepcopy( self:GetAbility().Familiars )
|
||||
for i=1,nSouls do
|
||||
local nIdx = math.random( 1, #PossibleFamiliars )
|
||||
local hTargetFamiliar = PossibleFamiliars[ nIdx ]
|
||||
self:LaunchSoulAssumption( hTargetFamiliar )
|
||||
table.remove( PossibleFamiliars, nIdx )
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
function modifier_boss_visage_passive:BeginStoneForm()
|
||||
if IsServer() then
|
||||
self:GetParent().bStone = true
|
||||
self.flStoneEndTime = GameRules:GetGameTime() + self.stone_duration
|
||||
self.flAssumptionTime = GameRules:GetGameTime() + 2.0
|
||||
|
||||
self:GetParent():AddNewModifier( self:GetParent(), self, "modifier_boss_visage_familiar_statue_stone_form", { duration = self.stone_duration } )
|
||||
|
||||
self.nChannelFX = ParticleManager:CreateParticle( "particles/act_2/storegga_channel.vpcf", PATTACH_ABSORIGIN_FOLLOW, self:GetParent() )
|
||||
end
|
||||
end
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
function modifier_boss_visage_passive:EndStoneForm()
|
||||
if IsServer() then
|
||||
print( "Ending Stone Form!" )
|
||||
self:GetParent().bStone = false
|
||||
self.flStoneEndTime = 9999999999999999999999999999
|
||||
self.flDamageRemaining = self.stone_threshold
|
||||
|
||||
if self.nStoneFX ~= -1 then
|
||||
ParticleManager:DestroyParticle( self.nStoneFX, false )
|
||||
self.nStoneFX = -1
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
function modifier_boss_visage_passive:LaunchSoulAssumption( hTarget )
|
||||
if hTarget == nil or IsServer() == false then
|
||||
return
|
||||
end
|
||||
|
||||
local projectile =
|
||||
{
|
||||
Target = hTarget,
|
||||
Source = self:GetCaster(),
|
||||
Ability = self:GetAbility(),
|
||||
EffectName = "particles/units/heroes/hero_visage/visage_soul_assumption_bolt6.vpcf",
|
||||
iMoveSpeed = self:GetAbility():GetSpecialValueFor( "soul_assumption_speed" ),
|
||||
vSourceLoc = self:GetCaster():GetOrigin(),
|
||||
bDodgeable = false,
|
||||
bProvidesVision = false,
|
||||
bIgnoreObstructions = true,
|
||||
iSourceAttachment = 1,
|
||||
}
|
||||
|
||||
ProjectileManager:CreateTrackingProjectile( projectile )
|
||||
EmitSoundOn( "Hero_Visage.SoulAssumption.Cast", self:GetParent() )
|
||||
end
|
||||
|
||||
@@ -0,0 +1,2 @@
|
||||
|
||||
modifier_boss_visage_thinker_dummy = class({})
|
||||
@@ -0,0 +1,95 @@
|
||||
modifier_brewmaster_split = class({})
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
function modifier_brewmaster_split:IsHidden()
|
||||
return true
|
||||
end
|
||||
|
||||
-----------------------------------------------------------------------------------------
|
||||
|
||||
function modifier_brewmaster_split:IsPurgable()
|
||||
return false
|
||||
end
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
function modifier_brewmaster_split:GetPriority()
|
||||
return MODIFIER_PRIORITY_ULTRA + 10001
|
||||
end
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
function modifier_brewmaster_split:CheckState()
|
||||
local state =
|
||||
{
|
||||
[MODIFIER_STATE_INVULNERABLE] = true,
|
||||
[MODIFIER_STATE_NO_HEALTH_BAR] = true,
|
||||
[MODIFIER_STATE_STUNNED] = true,
|
||||
}
|
||||
|
||||
return state
|
||||
end
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
function modifier_brewmaster_split:GetEffectName()
|
||||
return "particles/units/heroes/hero_brewmaster/brewmaster_primal_split.vpcf"
|
||||
end
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
function modifier_brewmaster_split:GetEffectAttachType()
|
||||
return PATTACH_ABSORIGIN
|
||||
end
|
||||
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
function modifier_brewmaster_split:OnCreated( kv )
|
||||
if IsServer() then
|
||||
|
||||
end
|
||||
end
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
function modifier_brewmaster_split:OnDestroy()
|
||||
if IsServer() then
|
||||
EmitSoundOn( "Hero_Brewmaster.PrimalSplit.Spawn", self:GetParent() )
|
||||
|
||||
local vPos = self:GetParent():GetAbsOrigin()
|
||||
|
||||
local enemies = FindUnitsInRadius( DOTA_TEAM_BADGUYS, vPos, nil, FIND_UNITS_EVERYWHERE, DOTA_UNIT_TARGET_TEAM_ENEMY, DOTA_UNIT_TARGET_HERO + DOTA_UNIT_TARGET_BASIC, DOTA_UNIT_TARGET_FLAG_MAGIC_IMMUNE_ENEMIES + DOTA_UNIT_TARGET_FLAG_FOW_VISIBLE, FIND_CLOSEST, false )
|
||||
local target = enemies[RandomInt(1,#enemies)]
|
||||
|
||||
local earthspirit_name = "npc_dota_brewmaster_earth_unit"
|
||||
local earthspirit_origin = vPos
|
||||
local earthspirit = CreateUnitByName(earthspirit_name, earthspirit_origin, true, self:GetParent(), nil, DOTA_TEAM_BADGUYS)
|
||||
local earthspiritfx_name = "particles/units/heroes/hero_brewmaster/brewmaster_earth_ambient.vpcf"
|
||||
local earthspiritfx = ParticleManager:CreateParticle( earthspiritfx_name, PATTACH_ABSORIGIN_FOLLOW, earthspirit )
|
||||
ParticleManager:SetParticleControlEnt( earthspiritfx, 0, earthspirit, PATTACH_ABSORIGIN_FOLLOW, nil, earthspirit:GetOrigin(), true )
|
||||
earthspirit:SetInitialGoalEntity( target )
|
||||
|
||||
local stormspirit_name = "npc_dota_brewmaster_storm_unit"
|
||||
local stormspirit_origin = vPos
|
||||
local stormspirit = CreateUnitByName(stormspirit_name, stormspirit_origin, true, self:GetParent(), nil, DOTA_TEAM_BADGUYS)
|
||||
local stormspiritfx_name = "particles/units/heroes/hero_brewmaster/brewmaster_storm_ambient.vpcf"
|
||||
local stormspiritfx = ParticleManager:CreateParticle( stormspiritfx_name, PATTACH_ABSORIGIN_FOLLOW, stormspirit )
|
||||
ParticleManager:SetParticleControlEnt( stormspiritfx, 0, stormspirit, PATTACH_ABSORIGIN_FOLLOW, nil, stormspirit:GetOrigin(), true )
|
||||
stormspirit:SetInitialGoalEntity( target )
|
||||
|
||||
local firespirit_name = "npc_dota_brewmaster_fire_unit"
|
||||
local firespirit_origin = vPos
|
||||
local firespirit = CreateUnitByName(firespirit_name, firespirit_origin, true, self:GetParent(), nil, DOTA_TEAM_BADGUYS)
|
||||
local firespiritfx_name = "particles/units/heroes/hero_brewmaster/brewmaster_fire_ambient.vpcf"
|
||||
local firespiritfx = ParticleManager:CreateParticle( firespiritfx_name, PATTACH_ABSORIGIN_FOLLOW, firespirit )
|
||||
ParticleManager:SetParticleControlEnt( firespiritfx, 0, firespirit, PATTACH_ABSORIGIN_FOLLOW, nil, firespirit:GetOrigin(), true )
|
||||
firespirit:SetInitialGoalEntity( target )
|
||||
|
||||
self:GetParent():AddEffects( EF_NODRAW )
|
||||
self:GetParent():ForceKill( false )
|
||||
end
|
||||
end
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
@@ -0,0 +1,49 @@
|
||||
modifier_brewmaster_unit_passive = class({})
|
||||
|
||||
--------------------------------------------------------------
|
||||
|
||||
function modifier_brewmaster_unit_passive:DeclareFunctions()
|
||||
local funcs =
|
||||
{
|
||||
MODIFIER_EVENT_ON_DEATH,
|
||||
}
|
||||
|
||||
return funcs
|
||||
end
|
||||
|
||||
--------------------------------------------------------------
|
||||
|
||||
function modifier_brewmaster_unit_passive:OnDeath( params )
|
||||
if not IsServer() or params.unit ~= self:GetParent() then
|
||||
return 0
|
||||
end
|
||||
|
||||
print("Brewling died!")
|
||||
local killedUnit = self:GetParent()
|
||||
local unitName = killedUnit:GetUnitName()
|
||||
print(unitName)
|
||||
if killedUnit:GetUnitName() == "npc_dota_brewmaster_earth_unit" then
|
||||
local vPos = killedUnit:GetAbsOrigin()
|
||||
local fx_name = "particles/units/heroes/hero_brewmaster/brewmaster_earth_death_collapse.vpcf"
|
||||
local fx = ParticleManager:CreateParticle( fx_name, PATTACH_ABSORIGIN, killedUnit )
|
||||
ParticleManager:SetParticleControlEnt( fx, 0, killedUnit, PATTACH_ABSORIGIN, nil, killedUnit:GetOrigin(), true )
|
||||
killedUnit:SetModelScale(0.1)
|
||||
--ParticleManager:DestroyParticle( fx, false )
|
||||
elseif killedUnit:GetUnitName() == "npc_dota_brewmaster_storm_unit" then
|
||||
local vPos = killedUnit:GetAbsOrigin()
|
||||
local fx_name = "particles/units/heroes/hero_brewmaster/brewmaster_storm_death.vpcf"
|
||||
local fx = ParticleManager:CreateParticle( fx_name, PATTACH_ABSORIGIN, killedUnit )
|
||||
ParticleManager:SetParticleControlEnt( fx, 0, killedUnit, PATTACH_ABSORIGIN, nil, killedUnit:GetOrigin(), true )
|
||||
killedUnit:SetModelScale(0.1)
|
||||
--ParticleManager:DestroyParticle( fx, false )
|
||||
elseif killedUnit:GetUnitName() == "npc_dota_brewmaster_fire_unit" then
|
||||
local vPos = killedUnit:GetAbsOrigin()
|
||||
local fx_name = "particles/units/heroes/hero_brewmaster/brewmaster_fire_death.vpcf"
|
||||
local fx = ParticleManager:CreateParticle( fx_name, PATTACH_ABSORIGIN, killedUnit )
|
||||
ParticleManager:SetParticleControlEnt( fx, 0, killedUnit, PATTACH_ABSORIGIN, nil, killedUnit:GetOrigin(), true )
|
||||
killedUnit:SetModelScale(0.1)
|
||||
--ParticleManager:DestroyParticle( fx, false )
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
@@ -0,0 +1,50 @@
|
||||
|
||||
modifier_broodmother_accrue_children = class({})
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
function modifier_broodmother_accrue_children:IsHidden()
|
||||
return true
|
||||
end
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
function modifier_broodmother_accrue_children:IsPurgable()
|
||||
return false
|
||||
end
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
function modifier_broodmother_accrue_children:OnCreated( kv )
|
||||
if IsServer() then
|
||||
self.babies_to_spawn = self:GetAbility():GetSpecialValueFor( "babies_to_spawn" )
|
||||
end
|
||||
end
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
function modifier_broodmother_accrue_children:DeclareFunctions()
|
||||
local funcs = {
|
||||
MODIFIER_EVENT_ON_DEATH,
|
||||
}
|
||||
|
||||
return funcs
|
||||
end
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
function modifier_broodmother_accrue_children:OnDeath( params )
|
||||
if IsServer() then
|
||||
local hUnit = params.unit
|
||||
if hUnit == self:GetParent() then
|
||||
local hDummy = CreateUnitByName( "npc_dota_dummy_caster", self:GetParent():GetAbsOrigin(), true, self:GetParent(), self:GetParent(), self:GetParent():GetTeamNumber() )
|
||||
if hDummy ~= nil then
|
||||
hDummy.nAmountToSpawn = self.babies_to_spawn
|
||||
hDummy.hInitialGoalEntity = self:GetParent():GetInitialGoalEntity()
|
||||
hDummy:AddAbility( "broodmother_generate_children" ) -- the dummy is a creature and creatures auto-level their abilities
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
@@ -0,0 +1,131 @@
|
||||
|
||||
-- Note: this modifier's ability gets added by hand to the dummy unit that Broodmother creates.
|
||||
|
||||
modifier_broodmother_generate_children = class({})
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
function modifier_broodmother_generate_children:IsHidden()
|
||||
return true
|
||||
end
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
function modifier_broodmother_generate_children:IsPurgable()
|
||||
return false
|
||||
end
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
function modifier_broodmother_generate_children:OnCreated( kv )
|
||||
if IsServer() then
|
||||
self.hBabies = { }
|
||||
|
||||
self.spawn_interval = self:GetAbility():GetSpecialValueFor( "spawn_interval" )
|
||||
|
||||
-- Note: nAmountToSpawn gets attached to the parent (a dummy) by broodmother, prior to modifier being added
|
||||
self.nAmountToSpawn = self:GetParent().nAmountToSpawn
|
||||
self.bWantsToBeRemoved = false
|
||||
self.nMaxSpawnRadius = 75 + ( self.nAmountToSpawn * 15 )
|
||||
|
||||
self.szBabyUnit = "npc_dota_creature_broodmother_baby_c"
|
||||
|
||||
self.nFXIndex = ParticleManager:CreateParticle( "particles/baby_brood_venom_pool.vpcf", PATTACH_CUSTOMORIGIN, self:GetCaster() )
|
||||
ParticleManager:SetParticleControl( self.nFXIndex, 0, self:GetCaster():GetAbsOrigin() )
|
||||
ParticleManager:SetParticleControl( self.nFXIndex, 1, Vector( self.nMaxSpawnRadius, 1, 1 ) )
|
||||
|
||||
self:StartIntervalThink( self.spawn_interval )
|
||||
end
|
||||
end
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
function modifier_broodmother_generate_children:OnIntervalThink()
|
||||
if IsServer() then
|
||||
if #self.hBabies < self.nAmountToSpawn then
|
||||
self:CreateBaby()
|
||||
end
|
||||
|
||||
if self.bWantsToBeRemoved == false and #self.hBabies >= self.nAmountToSpawn then
|
||||
self.bWantsToBeRemoved = true
|
||||
end
|
||||
|
||||
if self.bWantsToBeRemoved then
|
||||
self:TryToRemoveMyself()
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
function modifier_broodmother_generate_children:CreateBaby()
|
||||
local hBaby = CreateUnitByName( self.szBabyUnit, self:GetParent():GetAbsOrigin(), true, self:GetParent(), self:GetParent(), self:GetParent():GetTeamNumber() )
|
||||
|
||||
local nMaxDistance = 75 + ( #self.hBabies * 15 )
|
||||
local vSpawnLoc = nil
|
||||
|
||||
local nMaxAttempts = 7
|
||||
local nAttempts = 0
|
||||
|
||||
repeat
|
||||
if nAttempts > nMaxAttempts then
|
||||
vSpawnLoc = nil
|
||||
printf( "WARNING - modifier_broodmother_generate_children:CreateBaby() - failed to find valid spawn loc for baby spider" )
|
||||
break
|
||||
end
|
||||
|
||||
local vPos = self:GetParent():GetAbsOrigin() + RandomVector( nMaxDistance )
|
||||
vSpawnLoc = FindPathablePositionNearby( vPos, 0, 100 )
|
||||
nAttempts = nAttempts + 1
|
||||
until ( GameRules.Aghanim:GetCurrentRoom():IsInRoomBounds( vSpawnLoc ) )
|
||||
|
||||
if hBaby and vSpawnLoc ~= nil then
|
||||
table.insert( self.hBabies, hBaby )
|
||||
|
||||
hBaby:SetInitialGoalEntity( self:GetParent().hInitialGoalEntity )
|
||||
hBaby:SetDeathXP( 0 )
|
||||
hBaby:SetMinimumGoldBounty( 0 )
|
||||
hBaby:SetMaximumGoldBounty( 0 )
|
||||
|
||||
local kv =
|
||||
{
|
||||
vLocX = vSpawnLoc.x,
|
||||
vLocY = vSpawnLoc.y,
|
||||
vLocZ = vSpawnLoc.z,
|
||||
}
|
||||
hBaby:AddNewModifier( self:GetParent(), self:GetAbility(), "modifier_frostivus2018_broodbaby_launch", kv )
|
||||
|
||||
EmitSoundOn( "Creature_Broodmother.CreateBabySpider", hBaby )
|
||||
end
|
||||
end
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
function modifier_broodmother_generate_children:TryToRemoveMyself()
|
||||
if IsServer() then
|
||||
-- Are all my babies done with their movement modifier?
|
||||
self.bSafeToRemove = true
|
||||
for _, hBaby in pairs( self.hBabies ) do
|
||||
if hBaby ~= nil and hBaby:IsNull() == false and hBaby:IsAlive() and hBaby:HasModifier( "modifier_frostivus2018_broodbaby_launch" ) then
|
||||
self.bSafeToRemove = false
|
||||
end
|
||||
end
|
||||
|
||||
if self.bSafeToRemove then
|
||||
self:Destroy()
|
||||
return
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
function modifier_broodmother_generate_children:OnDestroy()
|
||||
if IsServer() then
|
||||
ParticleManager:DestroyParticle( self.nFXIndex, false )
|
||||
self:GetParent():ForceKill( false )
|
||||
UTIL_Remove( self:GetParent() )
|
||||
end
|
||||
end
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
@@ -0,0 +1,38 @@
|
||||
|
||||
modifier_broodmother_web = class({})
|
||||
|
||||
-----------------------------------------------------------------------------
|
||||
|
||||
function modifier_broodmother_web:GetEffectName()
|
||||
return "particles/items2_fx/rod_of_atos.vpcf"
|
||||
end
|
||||
|
||||
-----------------------------------------------------------------------------
|
||||
|
||||
function modifier_broodmother_web:OnCreated( kv )
|
||||
if IsServer() then
|
||||
EmitSoundOn( "Creature_Spectre.Dagger.VictimLoop", self:GetParent() )
|
||||
end
|
||||
end
|
||||
|
||||
-----------------------------------------------------------------------------
|
||||
|
||||
function modifier_broodmother_web:OnDestroy()
|
||||
if IsServer() then
|
||||
StopSoundOn( "Creature_Spectre.Dagger.VictimLoop", self:GetParent() )
|
||||
EmitSoundOn( "Creature_Spectre.Dagger.VictimEnd", self:GetParent() )
|
||||
end
|
||||
end
|
||||
|
||||
-----------------------------------------------------------------------------
|
||||
|
||||
function modifier_broodmother_web:CheckState()
|
||||
local state =
|
||||
{
|
||||
[ MODIFIER_STATE_ROOTED ] = true,
|
||||
}
|
||||
|
||||
return state
|
||||
end
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
@@ -0,0 +1,34 @@
|
||||
modifier_creature_generic_high_status_resist_passive = class({})
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
function modifier_creature_generic_high_status_resist_passive:IsPurgable()
|
||||
return false;
|
||||
end
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
function modifier_creature_generic_high_status_resist_passive:IsHidden()
|
||||
return true;
|
||||
end
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
function modifier_creature_generic_high_status_resist_passive:DeclareFunctions()
|
||||
local funcs = {
|
||||
MODIFIER_PROPERTY_STATUS_RESISTANCE_STACKING,
|
||||
}
|
||||
return funcs
|
||||
end
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
function modifier_creature_generic_high_status_resist_passive:GetModifierStatusResistanceStacking( params )
|
||||
return 75
|
||||
end
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
function modifier_creature_generic_high_status_resist_passive:OnCreated( kv )
|
||||
if IsServer() then
|
||||
end
|
||||
end
|
||||
@@ -0,0 +1,64 @@
|
||||
modifier_creature_landmine_detonate = class({})
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
function modifier_creature_landmine_detonate:OnCreated( kv )
|
||||
if IsServer() then
|
||||
self.radius = self:GetAbility():GetSpecialValueFor( "detonate_radius" )
|
||||
self.damage = self:GetAbility():GetSpecialValueFor( "detonate_damage" )
|
||||
|
||||
self:StartIntervalThink( 0 )
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
function modifier_creature_landmine_detonate:OnIntervalThink()
|
||||
if IsServer() then
|
||||
|
||||
local nFXIndex = ParticleManager:CreateParticle( "particles/units/heroes/hero_techies/techies_land_mine_explode.vpcf", PATTACH_CUSTOMORIGIN, nil )
|
||||
ParticleManager:SetParticleControl( nFXIndex, 0, self:GetParent():GetOrigin() )
|
||||
ParticleManager:SetParticleControl( nFXIndex, 1, Vector( 1.0, 1.0, self.radius ) )
|
||||
ParticleManager:SetParticleControl( nFXIndex, 2, Vector( 1.0, 1.0, self.radius ) )
|
||||
ParticleManager:ReleaseParticleIndex( nFXIndex )
|
||||
|
||||
EmitSoundOn( "Hero_Techies.LandMine.Detonate", self:GetParent() )
|
||||
|
||||
self:StartIntervalThink( self:GetRemainingTime() / 3 )
|
||||
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
function modifier_creature_landmine_detonate:OnDestroy()
|
||||
if IsServer() then
|
||||
local enemies = FindUnitsInRadius( self:GetCaster():GetTeamNumber(), self:GetParent():GetOrigin(), self:GetCaster(), self.radius, DOTA_UNIT_TARGET_TEAM_ENEMY, DOTA_UNIT_TARGET_HERO + DOTA_UNIT_TARGET_BASIC, DOTA_UNIT_TARGET_FLAG_NOT_ANCIENTS, 0, false )
|
||||
if #enemies > 0 then
|
||||
for _,enemy in pairs(enemies) do
|
||||
if enemy ~= nil and ( not enemy:IsMagicImmune() ) and ( not enemy:IsInvulnerable() ) then
|
||||
local DamageInfo =
|
||||
{
|
||||
victim = enemy,
|
||||
attacker = self:GetCaster(),
|
||||
ability = self,
|
||||
damage = self.damage,
|
||||
damage_type = DAMAGE_TYPE_MAGICAL,
|
||||
}
|
||||
ApplyDamage( DamageInfo )
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
local nFXIndex = ParticleManager:CreateParticle( "particles/units/heroes/hero_techies/techies_land_mine_explode.vpcf", PATTACH_CUSTOMORIGIN, nil )
|
||||
ParticleManager:SetParticleControl( nFXIndex, 0, self:GetParent():GetOrigin() )
|
||||
ParticleManager:SetParticleControl( nFXIndex, 1, Vector( 1.0, 1.0, self.radius ) )
|
||||
ParticleManager:SetParticleControl( nFXIndex, 2, Vector( 1.0, 1.0, self.radius ) )
|
||||
ParticleManager:ReleaseParticleIndex( nFXIndex )
|
||||
|
||||
EmitSoundOn( "Hero_Techies.LandMine.Detonate", self:GetParent() )
|
||||
self:GetParent():ForceKill( false )
|
||||
end
|
||||
end
|
||||
@@ -0,0 +1,71 @@
|
||||
modifier_creature_pudge_miniboss_passive = class({})
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
function modifier_creature_pudge_miniboss_passive:IsPurgable()
|
||||
return false;
|
||||
end
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
function modifier_creature_pudge_miniboss_passive:IsHidden()
|
||||
return true;
|
||||
end
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
function modifier_creature_pudge_miniboss_passive:DeclareFunctions()
|
||||
local funcs =
|
||||
{
|
||||
MODIFIER_PROPERTY_STATUS_RESISTANCE_STACKING,
|
||||
MODIFIER_PROPERTY_ATTACKSPEED_REDUCTION_PERCENTAGE,
|
||||
MODIFIER_PROPERTY_MOVESPEED_REDUCTION_PERCENTAGE,
|
||||
MODIFIER_EVENT_ON_ATTACK_LANDED
|
||||
}
|
||||
return funcs
|
||||
end
|
||||
|
||||
|
||||
|
||||
function modifier_creature_pudge_miniboss_passive:OnAttackLanded( params )
|
||||
if IsServer() then
|
||||
if params.target ~= self:GetParent() then
|
||||
return
|
||||
end
|
||||
self:GetParent().hAttacker = params.attacker
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
function modifier_creature_pudge_miniboss_passive:GetModifierStatusResistanceStacking( params )
|
||||
return 75
|
||||
end
|
||||
|
||||
function modifier_creature_pudge_miniboss_passive:CheckState()
|
||||
local state = {}
|
||||
if IsServer() then
|
||||
state[MODIFIER_STATE_CANNOT_MISS] = true
|
||||
state[MODIFIER_STATE_INVISIBLE] = false
|
||||
end
|
||||
return state
|
||||
end
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
function modifier_creature_pudge_miniboss_passive:OnCreated( kv )
|
||||
if IsServer() then
|
||||
end
|
||||
end
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
function modifier_creature_pudge_miniboss_passive:GetModifierAttackSpeedReductionPercentage( params )
|
||||
return 0
|
||||
end
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
function modifier_creature_pudge_miniboss_passive:GetModifierMoveSpeedReductionPercentage( params )
|
||||
return 20
|
||||
end
|
||||
@@ -0,0 +1,63 @@
|
||||
modifier_creature_techies_land_mine = class({})
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
function modifier_creature_techies_land_mine:OnCreated( kv )
|
||||
if IsServer() then
|
||||
self.radius = self:GetAbility():GetSpecialValueFor( "radius" )
|
||||
self.activation_delay = self:GetAbility():GetSpecialValueFor( "activation_delay" )
|
||||
self.damage = self:GetAbility():GetSpecialValueFor( "damage" )
|
||||
--self.proximity_threshold = self:GetAbility():GetSpecialValueFor( "proximity_threshold" )
|
||||
|
||||
self:StartIntervalThink( self.activation_delay )
|
||||
end
|
||||
end
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
function modifier_creature_techies_land_mine:CheckState()
|
||||
local state = {}
|
||||
if IsServer() then
|
||||
state[MODIFIER_STATE_ROOTED] = true
|
||||
state[MODIFIER_STATE_MAGIC_IMMUNE] = true
|
||||
state[MODIFIER_STATE_INVULNERABLE] = true
|
||||
state[MODIFIER_STATE_ATTACK_IMMUNE] = true
|
||||
state[MODIFIER_STATE_NO_HEALTH_BAR] = true
|
||||
state[MODIFIER_STATE_UNSELECTABLE] = true
|
||||
state[MODIFIER_STATE_NO_UNIT_COLLISION] = true
|
||||
end
|
||||
|
||||
return state
|
||||
end
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
function modifier_creature_techies_land_mine:OnIntervalThink()
|
||||
if IsServer() then
|
||||
local enemies = FindUnitsInRadius( self:GetParent():GetTeamNumber(), self:GetParent():GetOrigin(), self:GetCaster(), self.radius, DOTA_UNIT_TARGET_TEAM_ENEMY, DOTA_UNIT_TARGET_HERO + DOTA_UNIT_TARGET_BASIC, DOTA_UNIT_TARGET_FLAG_NOT_ANCIENTS, 0, false )
|
||||
if #enemies > 0 then
|
||||
for _, enemy in pairs( enemies ) do
|
||||
if enemy ~= nil and ( not enemy:IsMagicImmune() ) and ( not enemy:IsInvulnerable() ) then
|
||||
local DamageInfo =
|
||||
{
|
||||
victim = enemy,
|
||||
attacker = self:GetParent(),
|
||||
ability = self:GetAbility(),
|
||||
damage = self.damage,
|
||||
damage_type = DAMAGE_TYPE_MAGICAL,
|
||||
}
|
||||
ApplyDamage( DamageInfo )
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
local nFXIndex = ParticleManager:CreateParticle( "particles/units/heroes/hero_techies/techies_land_mine_explode.vpcf", PATTACH_CUSTOMORIGIN, nil )
|
||||
ParticleManager:SetParticleControl( nFXIndex, 0, self:GetParent():GetOrigin() )
|
||||
ParticleManager:SetParticleControl( nFXIndex, 1, Vector( 1.0, 1.0, radius ) )
|
||||
ParticleManager:SetParticleControl( nFXIndex, 2, Vector( 1.0, 1.0, radius ) )
|
||||
ParticleManager:ReleaseParticleIndex( nFXIndex )
|
||||
|
||||
EmitSoundOn( "TreasureChest.MineTrap.Detonate", self:GetParent() )
|
||||
self:GetParent():ForceKill( false )
|
||||
end
|
||||
end
|
||||
@@ -0,0 +1,25 @@
|
||||
|
||||
modifier_drow_ranger_skeleton_archer = class({})
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
function modifier_drow_ranger_skeleton_archer:OnCreated( kv )
|
||||
if IsServer() then
|
||||
ParticleManager:ReleaseParticleIndex( ParticleManager:CreateParticle( "particles/units/heroes/hero_clinkz/clinkz_burning_army_start.vpcf", PATTACH_ABSORIGIN, self:GetParent() ) )
|
||||
|
||||
self.nFXIndex = ParticleManager:CreateParticle( "particles/units/heroes/hero_clinkz/clinkz_burning_army.vpcf", PATTACH_ABSORIGIN_FOLLOW, self:GetParent() )
|
||||
end
|
||||
end
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
function modifier_drow_ranger_skeleton_archer:OnDestroy()
|
||||
if IsServer() then
|
||||
if self.nFXIndex ~= nil then
|
||||
--print( 'modifier_drow_ranger_skeleton_archer:OnDestroy() removing particle' )
|
||||
ParticleManager:DestroyParticle( self.nFXIndex, false )
|
||||
end
|
||||
|
||||
self:GetParent():ForceKill( false )
|
||||
end
|
||||
end
|
||||
@@ -0,0 +1,49 @@
|
||||
|
||||
modifier_dummy_caster_passive = class({})
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
function modifier_dummy_caster_passive:IsHidden()
|
||||
return true
|
||||
end
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
function modifier_dummy_caster_passive:IsPurgable()
|
||||
return false
|
||||
end
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
function modifier_dummy_caster_passive:CheckState()
|
||||
local state = {}
|
||||
if IsServer() then
|
||||
state[ MODIFIER_STATE_INVULNERABLE ] = true
|
||||
state[ MODIFIER_STATE_MAGIC_IMMUNE ] = true
|
||||
state[ MODIFIER_STATE_UNSELECTABLE ] = true
|
||||
state[ MODIFIER_STATE_NOT_ON_MINIMAP ] = true
|
||||
state[ MODIFIER_STATE_NO_UNIT_COLLISION ] = true
|
||||
state[ MODIFIER_STATE_NO_HEALTH_BAR ] = true
|
||||
state[ MODIFIER_STATE_DISARMED ] = true
|
||||
state[ MODIFIER_STATE_ROOTED ] = true
|
||||
state[ MODIFIER_STATE_ATTACK_IMMUNE ] = true
|
||||
end
|
||||
|
||||
return state
|
||||
end
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
function modifier_dummy_caster_passive:DeclareFunctions()
|
||||
local funcs =
|
||||
{
|
||||
MODIFIER_PROPERTY_MANACOST_PERCENTAGE,
|
||||
}
|
||||
return funcs
|
||||
end
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
function modifier_dummy_caster_passive:GetModifierPercentageManacost()
|
||||
return 100
|
||||
end
|
||||
@@ -0,0 +1,35 @@
|
||||
|
||||
modifier_dummy_target_passive = class({})
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
function modifier_dummy_target_passive:IsHidden()
|
||||
return true
|
||||
end
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
function modifier_dummy_target_passive:IsPurgable()
|
||||
return false
|
||||
end
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
function modifier_dummy_target_passive:CheckState()
|
||||
local state = {}
|
||||
|
||||
if IsServer() then
|
||||
state[ MODIFIER_STATE_INVULNERABLE ] = true
|
||||
state[ MODIFIER_STATE_MAGIC_IMMUNE ] = true
|
||||
state[ MODIFIER_STATE_ATTACK_IMMUNE ] = true
|
||||
state[ MODIFIER_STATE_NOT_ON_MINIMAP ] = true
|
||||
state[ MODIFIER_STATE_NO_UNIT_COLLISION ] = true
|
||||
state[ MODIFIER_STATE_NO_HEALTH_BAR ] = true
|
||||
state[ MODIFIER_STATE_DISARMED ] = true
|
||||
state[ MODIFIER_STATE_ROOTED ] = true
|
||||
end
|
||||
|
||||
return state
|
||||
end
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
@@ -0,0 +1,65 @@
|
||||
|
||||
modifier_earth_spirit_statue_passive = class({})
|
||||
|
||||
-----------------------------------------------------------------------------------------
|
||||
|
||||
function modifier_earth_spirit_statue_passive:IsHidden()
|
||||
return true
|
||||
end
|
||||
|
||||
-----------------------------------------------------------------------------------------
|
||||
|
||||
function modifier_earth_spirit_statue_passive:IsPurgable()
|
||||
return false
|
||||
end
|
||||
|
||||
-----------------------------------------------------------------------------------------
|
||||
|
||||
function modifier_earth_spirit_statue_passive:GetPriority()
|
||||
return MODIFIER_PRIORITY_ULTRA + 10000
|
||||
end
|
||||
|
||||
-----------------------------------------------------------------------------------------
|
||||
|
||||
function modifier_earth_spirit_statue_passive:OnCreated( kv )
|
||||
if IsServer() then
|
||||
local kv = { duration = -1 }
|
||||
self:GetParent():AddNewModifier( self:GetParent(), self, "modifier_earth_spirit_statue_stoneform", kv )
|
||||
end
|
||||
end
|
||||
|
||||
-----------------------------------------------------------------------------------------
|
||||
|
||||
function modifier_earth_spirit_statue_passive:DeclareFunctions()
|
||||
local funcs =
|
||||
{
|
||||
MODIFIER_PROPERTY_PROVIDES_FOW_POSITION,
|
||||
}
|
||||
|
||||
return funcs
|
||||
end
|
||||
|
||||
-----------------------------------------------------------------------------------------
|
||||
|
||||
function modifier_earth_spirit_statue_passive:GetModifierProvidesFOWVision( params )
|
||||
return 1
|
||||
end
|
||||
|
||||
-----------------------------------------------------------------------------------------
|
||||
|
||||
function modifier_earth_spirit_statue_passive:CheckState()
|
||||
local state =
|
||||
{
|
||||
[ MODIFIER_STATE_ATTACK_IMMUNE ] = true,
|
||||
[ MODIFIER_STATE_OUT_OF_GAME ] = true,
|
||||
[ MODIFIER_STATE_INVULNERABLE ] = true,
|
||||
[ MODIFIER_STATE_MAGIC_IMMUNE ] = true,
|
||||
[ MODIFIER_STATE_DISARMED ] = true,
|
||||
[ MODIFIER_STATE_NO_HEALTH_BAR ] = true,
|
||||
[ MODIFIER_STATE_NOT_ON_MINIMAP ] = true,
|
||||
}
|
||||
|
||||
return state
|
||||
end
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
@@ -0,0 +1,252 @@
|
||||
|
||||
modifier_earth_spirit_statue_stoneform = class({})
|
||||
|
||||
-----------------------------------------------------------------------------------------
|
||||
|
||||
function modifier_earth_spirit_statue_stoneform:IsHidden()
|
||||
return true
|
||||
end
|
||||
|
||||
-----------------------------------------------------------------------------------------
|
||||
|
||||
function modifier_earth_spirit_statue_stoneform:IsPurgable()
|
||||
return false
|
||||
end
|
||||
|
||||
-----------------------------------------------------------------------------------------
|
||||
|
||||
function modifier_earth_spirit_statue_stoneform:GetPriority()
|
||||
return MODIFIER_PRIORITY_ULTRA
|
||||
end
|
||||
|
||||
-----------------------------------------------------------------------------------------
|
||||
|
||||
function modifier_earth_spirit_statue_stoneform:GetStatusEffectName()
|
||||
return "particles/status_fx/status_effect_earth_spirit_petrify.vpcf"
|
||||
end
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
|
||||
function modifier_earth_spirit_statue_stoneform:StatusEffectPriority()
|
||||
return 60
|
||||
end
|
||||
|
||||
-----------------------------------------------------------------------------------------
|
||||
|
||||
function modifier_earth_spirit_statue_stoneform:OnCreated( kv )
|
||||
if IsServer() then
|
||||
--printf( "modifier_earth_spirit_statue_stoneform - OnCreated" )
|
||||
|
||||
self.nFXIndex = ParticleManager:CreateParticle( "particles/units/heroes/hero_earth_spirit/earthspirit_petrify_debuff_stoned.vpcf", PATTACH_CUSTOMORIGIN_FOLLOW, self:GetCaster() )
|
||||
ParticleManager:SetParticleControlEnt( self.nFXIndex, 0, self:GetCaster(), PATTACH_ABSORIGIN_FOLLOW, nil, self:GetCaster():GetOrigin(), true )
|
||||
ParticleManager:SetParticleControlEnt( self.nFXIndex, 1, self:GetCaster(), PATTACH_ABSORIGIN_FOLLOW, nil, self:GetCaster():GetOrigin(), true )
|
||||
self:AddParticle( self.nFXIndex, false, false, -1, false, false )
|
||||
|
||||
--[[
|
||||
self.nFXIndexB = ParticleManager:CreateParticle( "particles/units/heroes/hero_earth_spirit/espirit_stoneremnant_base.vpcf", PATTACH_CUSTOMORIGIN_FOLLOW, self:GetCaster() )
|
||||
ParticleManager:SetParticleControlEnt( self.nFXIndexB, 0, self:GetCaster(), PATTACH_ABSORIGIN, self:GetCaster() )
|
||||
ParticleManager:SetParticleControlEnt( self.nFXIndexB, 1, self:GetCaster(), PATTACH_ABSORIGIN_FOLLOW, nil, self:GetCaster():GetOrigin(), true )
|
||||
--ParticleManager:SetParticleControlEnt( self.nFXIndexB, 2, self:GetCaster(), PATTACH_ABSORIGIN_FOLLOW, nil, self:GetCaster():GetOrigin(), true )
|
||||
]]
|
||||
|
||||
--[[ C++
|
||||
ParticleIndex_t nFXIndex = CreateBuffParticleEffect( "particles/units/heroes/hero_earth_spirit/earthspirit_petrify_debuff_stoned.vpcf", PATTACH_CUSTOMORIGIN_FOLLOW, GetParent() );
|
||||
GetParticleManager()->SetParticleControlEnt( nFXIndex, 0, GetParent(), PATTACH_ABSORIGIN_FOLLOW, NULL );
|
||||
GetParticleManager()->SetParticleControlEnt( nFXIndex, 1, GetParent(), PATTACH_ABSORIGIN_FOLLOW, NULL );
|
||||
AddParticle( nFXIndex, false );
|
||||
|
||||
m_nFXIndex = CreateBuffParticleEffect( "particles/units/heroes/hero_earth_spirit/espirit_stoneremnant_base.vpcf", PATTACH_ABSORIGIN_FOLLOW, GetParent() );
|
||||
GetParticleManager()->SetParticleControlEnt( m_nFXIndex, 0, GetParent(), PATTACH_ABSORIGIN, NULL );
|
||||
GetParticleManager()->SetParticleControlEnt( m_nFXIndex, 1, GetParent(), PATTACH_ABSORIGIN_FOLLOW, NULL );
|
||||
GetParticleManager()->SetParticleControl( m_nFXIndex, 2, Vector( GetCaster()->GetSequence().GetRaw(), GetCaster()->GetModelScale(), 0 ) );
|
||||
]]
|
||||
end
|
||||
end
|
||||
|
||||
-----------------------------------------------------------------------------------------
|
||||
|
||||
function modifier_earth_spirit_statue_stoneform:OnDestroy()
|
||||
if IsServer() then
|
||||
--printf( "modifier_earth_spirit_statue_stoneform - OnDestroy" )
|
||||
|
||||
--local kv = { duration = -1 }
|
||||
--self:GetParent():AddNewModifier( self:GetParent(), self, "modifier_earth_spirit_statue_active", kv )
|
||||
|
||||
EmitSoundOn( "Hero_EarthSpirit.StoneRemnant.Destroy", self:GetCaster() )
|
||||
end
|
||||
end
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
|
||||
function modifier_earth_spirit_statue_stoneform:DeclareFunctions()
|
||||
local funcs = {
|
||||
MODIFIER_PROPERTY_OVERRIDE_ANIMATION,
|
||||
MODIFIER_PROPERTY_OVERRIDE_ANIMATION_RATE,
|
||||
}
|
||||
|
||||
return funcs
|
||||
end
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
function modifier_earth_spirit_statue_stoneform:GetOverrideAnimation( params )
|
||||
return ACT_DOTA_IDLE
|
||||
--return ACT_DOTA_IDLE_STATUE
|
||||
end
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
|
||||
function modifier_earth_spirit_statue_stoneform:GetOverrideAnimationRate( params )
|
||||
return 0.0
|
||||
end
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
|
||||
function modifier_earth_spirit_statue_stoneform:CheckState()
|
||||
local state =
|
||||
{
|
||||
[ MODIFIER_STATE_STUNNED ] = true,
|
||||
--[ MODIFIER_STATE_FROZEN ] = true,
|
||||
--[ MODIFIER_STATE_PROVIDES_VISION ] = true,
|
||||
|
||||
[ MODIFIER_STATE_INVISIBLE ] = false,
|
||||
}
|
||||
|
||||
return state
|
||||
end
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
|
||||
|
||||
--[[
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Modifier: Petrify
|
||||
//-----------------------------------------------------------------------------
|
||||
class CDOTA_Modifier_AghsFort_EarthSpiritBoss_Petrify : public CDOTA_Buff
|
||||
{
|
||||
public:
|
||||
DECLARE_CLASS( CDOTA_Modifier_AghsFort_EarthSpiritBoss_Petrify, CDOTA_Buff );
|
||||
|
||||
virtual bool IsDebuff( void ) { return true; }
|
||||
virtual bool IsStunDebuff( void ) { return true; }
|
||||
virtual bool IsPurgable( void ) { return false; }
|
||||
|
||||
virtual void OnCreated( KeyValues *pKV );
|
||||
void OnDestroy( void );
|
||||
void DeclareFunctions( void );
|
||||
|
||||
virtual void CheckState( CDOTABuffState &buffState ) OVERRIDE;
|
||||
|
||||
bool HasBeenMagnetized( void ) { return m_bHasBeenMagnetized; }
|
||||
void SetMagnetized( bool bState ) { m_bHasBeenMagnetized = bState; }
|
||||
|
||||
virtual const char *GetStatusEffectName( void ) { return "particles/status_fx/status_effect_earth_spirit_petrify.vpcf"; }
|
||||
virtual int StatusEffectPriority( void ) { return 420; }
|
||||
|
||||
bool ProvidesTruesightForTeam( int nTeamNumber ) OVERRIDE { return nTeamNumber == GetTeam(); }
|
||||
ModifierVariant_t GetOverrideAnimationRate( const CModifierParams ¶ms );
|
||||
private:
|
||||
ParticleIndex_t m_nFXIndex;
|
||||
bool m_bHasBeenMagnetized;
|
||||
};
|
||||
|
||||
LINK_MODIFIER_TO_CLASS( modifier_aghsfort_earth_spirit_boss_petrify, CDOTA_Modifier_AghsFort_EarthSpiritBoss_Petrify );
|
||||
|
||||
//--------------------------------------------------------------------------------
|
||||
|
||||
void CDOTA_Modifier_AghsFort_EarthSpiritBoss_Petrify::OnCreated( KeyValues *pKV )
|
||||
{
|
||||
#ifdef SERVER_DLL
|
||||
m_bHasBeenMagnetized = false;
|
||||
|
||||
ParticleIndex_t nFXIndex = CreateBuffParticleEffect( "particles/units/heroes/hero_earth_spirit/earthspirit_petrify_debuff_stoned.vpcf", PATTACH_CUSTOMORIGIN_FOLLOW, GetParent() );
|
||||
GetParticleManager()->SetParticleControlEnt( nFXIndex, 0, GetParent(), PATTACH_ABSORIGIN_FOLLOW, NULL );
|
||||
GetParticleManager()->SetParticleControlEnt( nFXIndex, 1, GetParent(), PATTACH_ABSORIGIN_FOLLOW, NULL );
|
||||
AddParticle( nFXIndex, false );
|
||||
|
||||
|
||||
m_nFXIndex = CreateBuffParticleEffect( "particles/units/heroes/hero_earth_spirit/espirit_stoneremnant_base.vpcf", PATTACH_ABSORIGIN_FOLLOW, GetParent() );
|
||||
GetParticleManager()->SetParticleControlEnt( m_nFXIndex, 0, GetParent(), PATTACH_ABSORIGIN, NULL );
|
||||
GetParticleManager()->SetParticleControlEnt( m_nFXIndex, 1, GetParent(), PATTACH_ABSORIGIN_FOLLOW, NULL );
|
||||
GetParticleManager()->SetParticleControl( m_nFXIndex, 2, Vector( GetCaster()->GetSequence().GetRaw(), GetCaster()->GetModelScale(), 0 ) );
|
||||
|
||||
if ( FStrEq( GetParent()->GetUnitName(), "npc_dota_hero_wisp" ) )
|
||||
{
|
||||
ParticleIndex_t nFXIndexWisp = CreateBuffParticleEffect( "particles/units/heroes/hero_earth_spirit/earthspirit_petrify_wisp.vpcf", PATTACH_CUSTOMORIGIN_FOLLOW, GetParent() );
|
||||
GetParticleManager()->SetParticleControlEnt( nFXIndexWisp, 0, GetParent(), PATTACH_POINT_FOLLOW, "attach_hitloc" );
|
||||
AddParticle( nFXIndexWisp, false );
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------
|
||||
|
||||
void CDOTA_Modifier_AghsFort_EarthSpiritBoss_Petrify::OnDestroy( void )
|
||||
{
|
||||
float damage;
|
||||
float aoe;
|
||||
|
||||
DOTA_RETRIEVE_VALUE( damage );
|
||||
DOTA_RETRIEVE_VALUE( aoe );
|
||||
|
||||
#ifdef SERVER_DLL
|
||||
CUtlVector<EHANDLE> hEntities;
|
||||
FindUnitsInRadius( GetCaster()->GetGridNav(), GetCaster()->GetTeamNumber(), GetParent()->GetAbsOrigin(), GetCaster(), aoe, &hEntities, DOTA_UNIT_TARGET_TEAM_ENEMY, DOTA_UNIT_TARGET_CREEP | DOTA_UNIT_TARGET_HERO );
|
||||
GetParticleManager()->DestroyParticleEffect( m_nFXIndex, false );
|
||||
|
||||
GetParent()->UnitEmitSound( "Hero_EarthSpirit.StoneRemnant.Destroy" );
|
||||
|
||||
for ( int i = 0; i < hEntities.Count(); i++ )
|
||||
{
|
||||
CDOTA_BaseNPC *pNPC = ToDOTABaseNPC( hEntities[i] );
|
||||
if ( pNPC )
|
||||
{
|
||||
ApplyDamage( GetCaster(), pNPC, GetAbility(), damage, DAMAGE_TYPE_MAGICAL );
|
||||
}
|
||||
}
|
||||
|
||||
if ( GetParent()->GetLocomotionInterface() && !GetParent()->GetLocomotionInterface()->IsCurrentlyMotionControlled() )
|
||||
{
|
||||
FindClearSpaceForUnit( GetParent(), GetParent()->GetAbsOrigin(), false );
|
||||
}
|
||||
#endif
|
||||
|
||||
ParticleIndex_t nFXIndexShockC = CreateBuffParticleEffect( "particles/units/heroes/hero_earth_spirit/earthspirit_petrify_shockwave.vpcf", PATTACH_ABSORIGIN_FOLLOW, GetParent() );
|
||||
GetParticleManager()->SetParticleControlEnt( nFXIndexShockC, 0, GetParent(), PATTACH_ABSORIGIN, NULL, GetParent()->GetAbsOrigin() );
|
||||
GetParticleManager()->SetParticleControl( nFXIndexShockC, 3, Vector( aoe, aoe, aoe ) );
|
||||
GetParticleManager()->ReleaseParticleIndex( nFXIndexShockC );
|
||||
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------------
|
||||
|
||||
void CDOTA_Modifier_AghsFort_EarthSpiritBoss_Petrify::DeclareFunctions( void )
|
||||
{
|
||||
DOTA_LINK_FUNCTION( MODIFIER_PROPERTY_OVERRIDE_ANIMATION_RATE, &CDOTA_Modifier_AghsFort_EarthSpiritBoss_Petrify::GetOverrideAnimationRate );
|
||||
}
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
ModifierVariant_t CDOTA_Modifier_AghsFort_EarthSpiritBoss_Petrify::GetOverrideAnimationRate( const CModifierParams ¶ms )
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
void CDOTA_Modifier_AghsFort_EarthSpiritBoss_Petrify::CheckState( CDOTABuffState &buffState )
|
||||
{
|
||||
BaseClass::CheckState( buffState );
|
||||
|
||||
buffState.Enable( MODIFIER_STATE_STUNNED );
|
||||
buffState.Enable( MODIFIER_STATE_FROZEN );
|
||||
buffState.Enable( MODIFIER_STATE_ATTACK_IMMUNE );
|
||||
buffState.Enable( MODIFIER_STATE_INVULNERABLE );
|
||||
buffState.Enable( MODIFIER_STATE_OUT_OF_GAME );
|
||||
buffState.Enable( MODIFIER_STATE_NO_HEALTH_BAR );
|
||||
buffState.Disable( MODIFIER_STATE_INVISIBLE );
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
]]
|
||||
@@ -0,0 +1,8 @@
|
||||
|
||||
modifier_elemental_tiny_create_io_dummy = class({})
|
||||
|
||||
--------------------------------------------------------------
|
||||
|
||||
function modifier_elemental_tiny_create_io_dummy:IsHidden()
|
||||
return true
|
||||
end
|
||||
@@ -0,0 +1,97 @@
|
||||
|
||||
modifier_elemental_tiny_grab = class({})
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
function modifier_elemental_tiny_grab:IsHidden()
|
||||
return true
|
||||
end
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
function modifier_elemental_tiny_grab:IsPurgable()
|
||||
return false
|
||||
end
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
function modifier_elemental_tiny_grab:OnCreated( kv )
|
||||
if IsServer() then
|
||||
if self:ApplyHorizontalMotionController() == false then
|
||||
self:Destroy()
|
||||
return
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
function modifier_elemental_tiny_grab:DeclareFunctions()
|
||||
local funcs =
|
||||
{
|
||||
MODIFIER_PROPERTY_OVERRIDE_ANIMATION,
|
||||
MODIFIER_EVENT_ON_DEATH,
|
||||
}
|
||||
return funcs
|
||||
end
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
function modifier_elemental_tiny_grab:CheckState()
|
||||
local state =
|
||||
{
|
||||
[MODIFIER_STATE_STUNNED] = true,
|
||||
[MODIFIER_STATE_INVULNERABLE] = true,
|
||||
[MODIFIER_STATE_OUT_OF_GAME] = true,
|
||||
}
|
||||
return state
|
||||
end
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
function modifier_elemental_tiny_grab:OnDestroy()
|
||||
if IsServer() then
|
||||
self:GetParent():RemoveHorizontalMotionController( self )
|
||||
end
|
||||
end
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
function modifier_elemental_tiny_grab:UpdateHorizontalMotion( me, dt )
|
||||
if IsServer() then
|
||||
local vLocation = nil
|
||||
if self:GetParent() ~= nil and self:GetParent():IsAlive() then
|
||||
local attach = self:GetCaster():ScriptLookupAttachment( "attach_attack" )
|
||||
vLocation = self:GetCaster():GetAttachmentOrigin( attach )
|
||||
me:SetOrigin( vLocation )
|
||||
end
|
||||
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
function modifier_elemental_tiny_grab:OnHorizontalMotionInterrupted()
|
||||
if IsServer() then
|
||||
self:Destroy()
|
||||
end
|
||||
end
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
function modifier_elemental_tiny_grab:GetOverrideAnimation( params )
|
||||
return ACT_DOTA_FLAIL
|
||||
end
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
function modifier_elemental_tiny_grab:OnDeath( params )
|
||||
if IsServer() then
|
||||
if params.unit == self:GetCaster() then
|
||||
self:Destroy()
|
||||
end
|
||||
end
|
||||
|
||||
return 0
|
||||
end
|
||||
@@ -0,0 +1,224 @@
|
||||
|
||||
modifier_enraged_wildkin_tornado_passive = class({})
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
function modifier_enraged_wildkin_tornado_passive:OnCreated( kv )
|
||||
self.radius = self:GetAbility():GetSpecialValueFor( "tornado_radius" )
|
||||
self.harpy_spawn_interval = self:GetAbility():GetSpecialValueFor( "harpy_spawn_interval" )
|
||||
self.harpy_spawn_amount = self:GetAbility():GetSpecialValueFor( "harpy_spawn_amount" )
|
||||
self.max_total_harpies = self:GetAbility():GetSpecialValueFor( "max_total_harpies" )
|
||||
|
||||
self.szHarpyUnit = "npc_aghsfort_creature_tornado_harpy"
|
||||
self.flLastHarpyTime = GameRules:GetGameTime()
|
||||
|
||||
self:StartIntervalThink( 0.5 )
|
||||
end
|
||||
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
function modifier_enraged_wildkin_tornado_passive:IsHidden()
|
||||
return true
|
||||
end
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
function modifier_enraged_wildkin_tornado_passive:IsAura()
|
||||
return true
|
||||
end
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
function modifier_enraged_wildkin_tornado_passive:GetModifierAura()
|
||||
return "modifier_enraged_wildkin_tornado_passive_debuff"
|
||||
end
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
function modifier_enraged_wildkin_tornado_passive:GetAuraSearchTeam()
|
||||
return DOTA_UNIT_TARGET_TEAM_ENEMY
|
||||
end
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
function modifier_enraged_wildkin_tornado_passive:GetAuraSearchType()
|
||||
return DOTA_UNIT_TARGET_HERO + DOTA_UNIT_TARGET_CREEP
|
||||
end
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
function modifier_enraged_wildkin_tornado_passive:GetAuraSearchFlags()
|
||||
return DOTA_UNIT_TARGET_FLAG_NOT_ANCIENTS
|
||||
end
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
function modifier_enraged_wildkin_tornado_passive:GetAuraRadius()
|
||||
return self.radius
|
||||
end
|
||||
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
function modifier_enraged_wildkin_tornado_passive:OnRefresh( kv )
|
||||
self.radius = self:GetAbility():GetSpecialValueFor( "tornado_radius" )
|
||||
end
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
function modifier_enraged_wildkin_tornado_passive:DeclareFunctions()
|
||||
local funcs = {
|
||||
MODIFIER_PROPERTY_MOVESPEED_ABSOLUTE,
|
||||
}
|
||||
|
||||
return funcs
|
||||
end
|
||||
|
||||
function modifier_enraged_wildkin_tornado_passive:OnIntervalThink()
|
||||
if IsServer() then
|
||||
|
||||
--if self:GetCaster() == nil or self:GetCaster():IsAlive() ~= true then
|
||||
-- self:GetParent():ForceKill(false)
|
||||
-- return
|
||||
--end
|
||||
|
||||
--local vDirection = self:GetParent():GetAbsOrigin() - self:GetCaster():GetAbsOrigin()
|
||||
--self:GetCaster():SetForwardVector(vDirection)
|
||||
|
||||
|
||||
if self.nPreviewFX ~= nil then
|
||||
ParticleManager:DestroyParticle( self.nPreviewFX, false )
|
||||
end
|
||||
|
||||
|
||||
if self:GetParent():IsMoving() == false then
|
||||
self:DoMove()
|
||||
end
|
||||
if GameRules:GetGameTime() - self.flLastHarpyTime > self.harpy_spawn_interval then
|
||||
-- for some reason can't find the harpies by names, so finding them by model
|
||||
local hHarpies = Entities:FindAllByModel( "models/creeps/neutral_creeps/n_creep_harpy_b/n_creep_harpy_b.vmdl" )
|
||||
if #hHarpies < self.max_total_harpies then
|
||||
--print ("we're at", #hHarpies, "now, max is", self.max_total_harpies)
|
||||
self:SpawnHarpy()
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
end
|
||||
end
|
||||
|
||||
function modifier_enraged_wildkin_tornado_passive:DoMove()
|
||||
if IsServer() then
|
||||
|
||||
local heroes = FindRealLivingEnemyHeroesInRadius( self:GetParent():GetTeamNumber(), self:GetParent():GetAbsOrigin(), FIND_UNITS_EVERYWHERE )
|
||||
if #heroes > 0 then
|
||||
local hero = heroes[RandomInt(1, #heroes)]
|
||||
|
||||
for i=1,4 do
|
||||
|
||||
local vLoc = FindPathablePositionNearby(hero:GetAbsOrigin(), 200, 200 )
|
||||
if GameRules.Aghanim:GetCurrentRoom():IsInRoomBounds( vLoc ) then
|
||||
|
||||
ExecuteOrderFromTable({
|
||||
UnitIndex = self:GetParent():entindex(),
|
||||
OrderType = DOTA_UNIT_ORDER_MOVE_TO_POSITION,
|
||||
Position = vLoc,
|
||||
Queue = false,
|
||||
})
|
||||
|
||||
break
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
return
|
||||
end
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
function modifier_enraged_wildkin_tornado_passive:GetModifierMoveSpeed_Absolute( params )
|
||||
return 320
|
||||
end
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
function modifier_enraged_wildkin_tornado_passive:SpawnHarpy()
|
||||
if IsServer() then
|
||||
local hUnit = self:GetParent()
|
||||
if hUnit == nil then
|
||||
return
|
||||
end
|
||||
if not hUnit:IsAlive() then
|
||||
return
|
||||
end
|
||||
|
||||
for i = 1, self.harpy_spawn_amount do
|
||||
local hHarpy = CreateUnitByName( self.szHarpyUnit, self:GetParent():GetAbsOrigin(), true, self:GetParent(), self:GetParent(), self:GetParent():GetTeamNumber() )
|
||||
local nMaxDistance = 200
|
||||
local vLoc = FindPathablePositionNearby(self:GetParent():GetAbsOrigin(), 150, nMaxDistance )
|
||||
|
||||
hHarpy:SetInitialGoalEntity( self:GetParent().hInitialGoalEntity )
|
||||
hHarpy:SetDeathXP( 0 )
|
||||
hHarpy:SetMinimumGoldBounty( 0 )
|
||||
hHarpy:SetMaximumGoldBounty( 0 )
|
||||
|
||||
local kv =
|
||||
{
|
||||
vLocX = vLoc.x,
|
||||
vLocY = vLoc.y,
|
||||
vLocZ = vLoc.z,
|
||||
}
|
||||
hHarpy:AddNewModifier( self:GetParent(), self:GetAbility(), "modifier_frostivus2018_broodbaby_launch", kv )
|
||||
|
||||
end
|
||||
|
||||
self.nPreviewFX = ParticleManager:CreateParticle( "particles/dark_moon/darkmoon_creep_warning.vpcf", PATTACH_ABSORIGIN_FOLLOW, self:GetParent() )
|
||||
ParticleManager:SetParticleControlEnt( self.nPreviewFX, 0, self:GetParent(), PATTACH_ABSORIGIN_FOLLOW, nil, self:GetParent():GetOrigin(), true )
|
||||
ParticleManager:SetParticleControl( self.nPreviewFX, 1, Vector( 100, 100, 100 ) )
|
||||
ParticleManager:SetParticleControl( self.nPreviewFX, 15, Vector( 29, 55, 184 ) )
|
||||
|
||||
|
||||
self.flLastHarpyTime = GameRules:GetGameTime()
|
||||
EmitSoundOn( "Creature_Bomb_Squad.LandMine.Plant", hHarpy )
|
||||
|
||||
end
|
||||
|
||||
return
|
||||
end
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
function modifier_enraged_wildkin_tornado_passive:CheckState()
|
||||
local state = {}
|
||||
if IsServer() then
|
||||
state =
|
||||
{
|
||||
[MODIFIER_STATE_STUNNED] = false,
|
||||
[MODIFIER_STATE_ROOTED] = false,
|
||||
[MODIFIER_STATE_MAGIC_IMMUNE] = true,
|
||||
[MODIFIER_STATE_INVULNERABLE] = true,
|
||||
[MODIFIER_STATE_NO_HEALTH_BAR] = true,
|
||||
[MODIFIER_STATE_FLYING] = true,
|
||||
[MODIFIER_STATE_NO_UNIT_COLLISION] = true,
|
||||
[MODIFIER_STATE_UNSELECTABLE] = true,
|
||||
}
|
||||
end
|
||||
|
||||
return state
|
||||
end
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
function modifier_enraged_wildkin_tornado_passive:GetEffectName( )
|
||||
return "particles/creatures/enraged_wildkin/enraged_wildkin_tornado.vpcf"
|
||||
end
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
function modifier_enraged_wildkin_tornado_passive:OnDestroy( )
|
||||
if IsServer() then
|
||||
if self:GetCaster() and self:GetCaster():IsAlive() then
|
||||
self:GetCaster():Interrupt()
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -0,0 +1,49 @@
|
||||
modifier_enraged_wildkin_tornado_passive_debuff = class({})
|
||||
|
||||
-----------------------------------------------------------------------------------------
|
||||
|
||||
function modifier_enraged_wildkin_tornado_passive_debuff:OnCreated( kv )
|
||||
self.movespeed_pct = self:GetAbility():GetSpecialValueFor( "movespeed_pct" )
|
||||
self.damage = self:GetAbility():GetSpecialValueFor( "damage" )
|
||||
if IsServer() then
|
||||
self:StartIntervalThink( 0.5 )
|
||||
end
|
||||
end
|
||||
|
||||
-----------------------------------------------------------------------------------------
|
||||
|
||||
function modifier_enraged_wildkin_tornado_passive_debuff:DeclareFunctions()
|
||||
local funcs =
|
||||
{
|
||||
MODIFIER_PROPERTY_MOVESPEED_BONUS_PERCENTAGE,
|
||||
}
|
||||
return funcs
|
||||
end
|
||||
|
||||
|
||||
-----------------------------------------------------------------------------------------
|
||||
|
||||
function modifier_enraged_wildkin_tornado_passive_debuff:GetModifierMoveSpeedBonus_Percentage( params )
|
||||
return -self.movespeed_pct
|
||||
end
|
||||
|
||||
-----------------------------------------------------------------------------------------
|
||||
|
||||
function modifier_enraged_wildkin_tornado_passive_debuff:OnIntervalThink()
|
||||
if IsServer() then
|
||||
if self:GetParent() and self:GetParent():IsInvulnerable() == false then
|
||||
|
||||
local damageInfo =
|
||||
{
|
||||
victim = self:GetParent(),
|
||||
attacker = self:GetCaster(),
|
||||
damage = self.damage / 2,
|
||||
damage_type = DAMAGE_TYPE_MAGICAL,
|
||||
ability = self:GetAbility()
|
||||
}
|
||||
|
||||
ApplyDamage( damageInfo )
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -0,0 +1,16 @@
|
||||
modifier_evil_greevil_passive = class({})
|
||||
|
||||
--------------------------------------------------------------
|
||||
|
||||
function modifier_evil_greevil_passive:CheckState()
|
||||
local state = {}
|
||||
|
||||
if IsServer() then
|
||||
state[MODIFIER_STATE_MAGIC_IMMUNE] = true
|
||||
end
|
||||
|
||||
return state
|
||||
end
|
||||
|
||||
--------------------------------------------------------------
|
||||
|
||||
@@ -0,0 +1,59 @@
|
||||
|
||||
modifier_huge_brood_passive = class({})
|
||||
|
||||
-----------------------------------------------------------------------------------------
|
||||
|
||||
function modifier_huge_brood_passive:IsHidden()
|
||||
return true
|
||||
end
|
||||
|
||||
-----------------------------------------------------------------------------------------
|
||||
|
||||
function modifier_huge_brood_passive:IsPurgable()
|
||||
return false
|
||||
end
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
function modifier_huge_brood_passive:GetPriority()
|
||||
return MODIFIER_PRIORITY_ULTRA + 10000
|
||||
end
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
function modifier_huge_brood_passive:OnCreated( kv )
|
||||
self.status_resistance = self:GetAbility():GetSpecialValueFor( "status_resistance" )
|
||||
end
|
||||
|
||||
|
||||
-----------------------------------------------------------------------------------------
|
||||
|
||||
function modifier_huge_brood_passive:CheckState()
|
||||
local state =
|
||||
{
|
||||
[MODIFIER_STATE_FEARED] = false,
|
||||
--[MODIFIER_STATE_CANNOT_BE_MOTION_CONTROLLED] = true,
|
||||
--[MODIFIER_STATE_UNSLOWABLE] = true,
|
||||
}
|
||||
|
||||
return state
|
||||
end
|
||||
|
||||
-----------------------------------------------------------------------------------------
|
||||
|
||||
function modifier_huge_brood_passive:DeclareFunctions()
|
||||
local funcs =
|
||||
{
|
||||
MODIFIER_PROPERTY_STATUS_RESISTANCE_STACKING,
|
||||
}
|
||||
|
||||
return funcs
|
||||
end
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
function modifier_huge_brood_passive:GetModifierStatusResistanceStacking( params )
|
||||
return self.status_resistance
|
||||
end
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
@@ -0,0 +1,50 @@
|
||||
|
||||
modifier_huge_broodmother_accrue_children = class({})
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
function modifier_huge_broodmother_accrue_children:IsHidden()
|
||||
return true
|
||||
end
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
function modifier_huge_broodmother_accrue_children:IsPurgable()
|
||||
return false
|
||||
end
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
function modifier_huge_broodmother_accrue_children:OnCreated( kv )
|
||||
if IsServer() then
|
||||
self.babies_to_spawn = self:GetAbility():GetSpecialValueFor( "babies_to_spawn" )
|
||||
end
|
||||
end
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
function modifier_huge_broodmother_accrue_children:DeclareFunctions()
|
||||
local funcs = {
|
||||
MODIFIER_EVENT_ON_DEATH,
|
||||
}
|
||||
|
||||
return funcs
|
||||
end
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
function modifier_huge_broodmother_accrue_children:OnDeath( params )
|
||||
if IsServer() then
|
||||
local hUnit = params.unit
|
||||
if hUnit == self:GetParent() then
|
||||
local hDummy = CreateUnitByName( "npc_dota_dummy_caster", self:GetParent():GetAbsOrigin(), true, self:GetParent(), self:GetParent(), self:GetParent():GetTeamNumber() )
|
||||
if hDummy ~= nil then
|
||||
hDummy.nAmountToSpawn = self.babies_to_spawn
|
||||
hDummy.hInitialGoalEntity = self:GetParent():GetInitialGoalEntity()
|
||||
hDummy:AddAbility( "huge_broodmother_generate_children" ) -- the dummy is a creature and creatures auto-level their abilities
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
@@ -0,0 +1,131 @@
|
||||
|
||||
-- Note: this modifier's ability gets added by hand to the dummy unit that Broodmother creates.
|
||||
|
||||
modifier_huge_broodmother_generate_children_thinker = class({})
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
function modifier_huge_broodmother_generate_children_thinker:IsHidden()
|
||||
return true
|
||||
end
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
function modifier_huge_broodmother_generate_children_thinker:IsPurgable()
|
||||
return false
|
||||
end
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
function modifier_huge_broodmother_generate_children_thinker:OnCreated( kv )
|
||||
if IsServer() then
|
||||
self.hBabies = { }
|
||||
|
||||
self.spawn_interval = self:GetAbility():GetSpecialValueFor( "spawn_interval" )
|
||||
|
||||
-- Note: nAmountToSpawn gets attached to the parent (a dummy) by broodmother, prior to modifier being added
|
||||
self.nAmountToSpawn = self:GetParent().nAmountToSpawn
|
||||
self.bWantsToBeRemoved = false
|
||||
self.nMaxSpawnRadius = 75 + ( self.nAmountToSpawn * 15 )
|
||||
|
||||
self.szBabyUnit = "npc_dota_creature_broodmother_baby_d"
|
||||
|
||||
self.nFXIndex = ParticleManager:CreateParticle( "particles/baby_brood_venom_pool.vpcf", PATTACH_CUSTOMORIGIN, self:GetCaster() )
|
||||
ParticleManager:SetParticleControl( self.nFXIndex, 0, self:GetCaster():GetAbsOrigin() )
|
||||
ParticleManager:SetParticleControl( self.nFXIndex, 1, Vector( self.nMaxSpawnRadius, 1, 1 ) )
|
||||
|
||||
self:StartIntervalThink( self.spawn_interval )
|
||||
end
|
||||
end
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
function modifier_huge_broodmother_generate_children_thinker:OnIntervalThink()
|
||||
if IsServer() then
|
||||
if #self.hBabies < self.nAmountToSpawn then
|
||||
self:CreateBaby()
|
||||
end
|
||||
|
||||
if self.bWantsToBeRemoved == false and #self.hBabies >= self.nAmountToSpawn then
|
||||
self.bWantsToBeRemoved = true
|
||||
end
|
||||
|
||||
if self.bWantsToBeRemoved then
|
||||
self:TryToRemoveMyself()
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
function modifier_huge_broodmother_generate_children_thinker:CreateBaby()
|
||||
local hBaby = CreateUnitByName( self.szBabyUnit, self:GetParent():GetAbsOrigin(), true, self:GetParent(), self:GetParent(), self:GetParent():GetTeamNumber() )
|
||||
|
||||
local nMaxDistance = 75 + ( #self.hBabies * 15 )
|
||||
local vSpawnLoc = nil
|
||||
|
||||
local nMaxAttempts = 7
|
||||
local nAttempts = 0
|
||||
|
||||
repeat
|
||||
if nAttempts > nMaxAttempts then
|
||||
vSpawnLoc = nil
|
||||
printf( "WARNING - modifier_broodmother_generate_children:CreateBaby() - failed to find valid spawn loc for baby spider" )
|
||||
break
|
||||
end
|
||||
|
||||
local vPos = self:GetParent():GetAbsOrigin() + RandomVector( nMaxDistance )
|
||||
vSpawnLoc = FindPathablePositionNearby( vPos, 0, 100 )
|
||||
nAttempts = nAttempts + 1
|
||||
until ( GameRules.Aghanim:GetCurrentRoom():IsInRoomBounds( vSpawnLoc ) )
|
||||
|
||||
if hBaby and vSpawnLoc ~= nil then
|
||||
table.insert( self.hBabies, hBaby )
|
||||
|
||||
hBaby:SetInitialGoalEntity( self:GetParent().hInitialGoalEntity )
|
||||
hBaby:SetDeathXP( 0 )
|
||||
hBaby:SetMinimumGoldBounty( 0 )
|
||||
hBaby:SetMaximumGoldBounty( 0 )
|
||||
|
||||
local kv =
|
||||
{
|
||||
vLocX = vSpawnLoc.x,
|
||||
vLocY = vSpawnLoc.y,
|
||||
vLocZ = vSpawnLoc.z,
|
||||
}
|
||||
hBaby:AddNewModifier( self:GetParent(), self:GetAbility(), "modifier_frostivus2018_broodbaby_launch", kv )
|
||||
|
||||
EmitSoundOn( "Creature_Broodmother.CreateBabySpider", hBaby )
|
||||
end
|
||||
end
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
function modifier_huge_broodmother_generate_children_thinker:TryToRemoveMyself()
|
||||
if IsServer() then
|
||||
-- Are all my babies done with their movement modifier?
|
||||
self.bSafeToRemove = true
|
||||
for _, hBaby in pairs( self.hBabies ) do
|
||||
if hBaby ~= nil and hBaby:IsNull() == false and hBaby:IsAlive() and hBaby:HasModifier( "modifier_frostivus2018_broodbaby_launch" ) then
|
||||
self.bSafeToRemove = false
|
||||
end
|
||||
end
|
||||
|
||||
if self.bSafeToRemove then
|
||||
self:Destroy()
|
||||
return
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
function modifier_huge_broodmother_generate_children_thinker:OnDestroy()
|
||||
if IsServer() then
|
||||
ParticleManager:DestroyParticle( self.nFXIndex, false )
|
||||
self:GetParent():ForceKill( false )
|
||||
UTIL_Remove( self:GetParent() )
|
||||
end
|
||||
end
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
@@ -0,0 +1,140 @@
|
||||
|
||||
modifier_lifestealer_damage_counter = class({})
|
||||
|
||||
-----------------------------------------------------------------------------------------
|
||||
|
||||
function modifier_lifestealer_damage_counter:IsPurgable()
|
||||
return false
|
||||
end
|
||||
|
||||
-----------------------------------------------------------------------------------------
|
||||
|
||||
function modifier_lifestealer_damage_counter:OnCreated( kv )
|
||||
if IsServer() then
|
||||
self.damage_threshold = self:GetAbility():GetSpecialValueFor( "damage_threshold" )
|
||||
self.enrage_duration = self:GetAbility():GetSpecialValueFor( "enrage_duration" )
|
||||
self.damage_counter_tiers = self:GetAbility():GetSpecialValueFor( "damage_counter_tiers" )
|
||||
self.time_before_reduction = self:GetAbility():GetSpecialValueFor( "time_before_reduction" )
|
||||
|
||||
self.nRecentDamageTaken = kv.damage or 0
|
||||
self.nOverheadParticleTier = 0
|
||||
self.nDamagePerTier = self.damage_threshold / self.damage_counter_tiers
|
||||
self.fLastDamageTakenTime = GameRules:GetGameTime()
|
||||
self.fLastReductionTime = GameRules:GetGameTime()
|
||||
|
||||
--printf( "self.nDamagePerTier: %d", self.nDamagePerTier )
|
||||
|
||||
-- Created overhead particle
|
||||
local vPos = Vector( 0, 0, 0 )
|
||||
self.nFXIndex = ParticleManager:CreateParticle( "particles/creatures/lifestealer/lifestealer_damage_counter_overhead.vpcf", PATTACH_OVERHEAD_FOLLOW, self:GetParent() )
|
||||
ParticleManager:SetParticleControl( self.nFXIndex, 0, vPos )
|
||||
ParticleManager:SetParticleControl( self.nFXIndex, 1, vPos )
|
||||
ParticleManager:SetParticleControl( self.nFXIndex, 2, vPos )
|
||||
ParticleManager:SetParticleControl( self.nFXIndex, 3, vPos )
|
||||
ParticleManager:SetParticleControl( self.nFXIndex, 4, vPos )
|
||||
ParticleManager:SetParticleControl( self.nFXIndex, 5, vPos )
|
||||
ParticleManager:SetParticleControl( self.nFXIndex, 6, vPos )
|
||||
ParticleManager:SetParticleControl( self.nFXIndex, 7, vPos )
|
||||
ParticleManager:SetParticleControl( self.nFXIndex, 8, Vector( 1, 0, 0 ) )
|
||||
ParticleManager:SetParticleControl( self.nFXIndex, 9, Vector( 2, 0, 0 ) )
|
||||
ParticleManager:SetParticleControl( self.nFXIndex, 10, Vector( 3, 0, 0 ) )
|
||||
ParticleManager:SetParticleControl( self.nFXIndex, 11, Vector( 4, 0, 0 ) )
|
||||
ParticleManager:SetParticleControl( self.nFXIndex, 12, Vector( 5, 0, 0 ) )
|
||||
self:AddParticle( self.nFXIndex, false, false, -1, false, true )
|
||||
|
||||
local nInitialTier = 1
|
||||
self:IncrementOverheadParticle( nInitialTier )
|
||||
|
||||
self:StartIntervalThink( 0.1 )
|
||||
end
|
||||
end
|
||||
|
||||
-----------------------------------------------------------------------------------------
|
||||
|
||||
function modifier_lifestealer_damage_counter:OnIntervalThink()
|
||||
if IsServer() then
|
||||
-- If some time has passed since I took damage, then reduce my ragebar tier by 1
|
||||
if GameRules:GetGameTime() >= self.fLastDamageTakenTime + self.time_before_reduction then
|
||||
if GameRules:GetGameTime() >= self.fLastReductionTime + self.time_before_reduction then
|
||||
--printf( "It's been at least %.2f secs since the last time I took damage", self.time_before_reduction )
|
||||
self.nRecentDamageTaken = self.nRecentDamageTaken - self.nDamagePerTier
|
||||
local nTier = math.floor( self.nRecentDamageTaken / self.nDamagePerTier )
|
||||
--printf( " self.nRecentDamageTaken: %d, self.nDamagePerTier: %d, nTier: %d", self.nRecentDamageTaken, self.nDamagePerTier, nTier )
|
||||
|
||||
if nTier < self.nOverheadParticleTier then
|
||||
--printf( " Reduce ragebar -- DecrementOverheadParticle" )
|
||||
self:DecrementOverheadParticle( nTier )
|
||||
end
|
||||
|
||||
self.fLastReductionTime = GameRules:GetGameTime()
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
-----------------------------------------------------------------------------------------
|
||||
|
||||
function modifier_lifestealer_damage_counter:DeclareFunctions()
|
||||
local funcs =
|
||||
{
|
||||
MODIFIER_EVENT_ON_TAKEDAMAGE,
|
||||
}
|
||||
|
||||
return funcs
|
||||
end
|
||||
|
||||
-----------------------------------------------------------------------------------------
|
||||
|
||||
function modifier_lifestealer_damage_counter:OnTakeDamage( params )
|
||||
if IsServer() then
|
||||
local hAttacker = params.attacker
|
||||
local hVictim = params.unit
|
||||
if hAttacker ~= nil and hVictim ~= nil and hVictim == self:GetParent() then
|
||||
local hToothy = hVictim
|
||||
self.fLastDamageTakenTime = GameRules:GetGameTime()
|
||||
--printf( "OnTakeDamage - hVictim is: %s", hVictim:GetUnitName() )
|
||||
self.nRecentDamageTaken = self.nRecentDamageTaken + params.damage
|
||||
|
||||
local nTier = math.floor( self.nRecentDamageTaken / self.nDamagePerTier )
|
||||
|
||||
if nTier > self.nOverheadParticleTier then
|
||||
self:IncrementOverheadParticle( nTier )
|
||||
end
|
||||
|
||||
if self.nRecentDamageTaken >= self.damage_threshold then
|
||||
if not ( hToothy:IsSilenced() or hToothy:IsStunned() or hToothy:IsHexed() or hToothy:IsFrozen() ) then
|
||||
hToothy:AddNewModifier( hToothy, self:GetAbility(), "modifier_lifestealer_enraged", { duration = self.enrage_duration } )
|
||||
self:Destroy()
|
||||
end
|
||||
else
|
||||
self:ForceRefresh()
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
return 0
|
||||
end
|
||||
|
||||
-----------------------------------------------------------------------------------------
|
||||
|
||||
function modifier_lifestealer_damage_counter:IncrementOverheadParticle( nTier )
|
||||
local nTiersSinceLastUpdate = nTier - self.nOverheadParticleTier
|
||||
|
||||
for i = 1, nTiersSinceLastUpdate do
|
||||
ParticleManager:SetParticleControl( self.nFXIndex, self.nOverheadParticleTier + i, Vector( 1, 0, 0 ) )
|
||||
end
|
||||
|
||||
self.nOverheadParticleTier = nTier
|
||||
end
|
||||
|
||||
-----------------------------------------------------------------------------------------
|
||||
|
||||
function modifier_lifestealer_damage_counter:DecrementOverheadParticle( nTier )
|
||||
if self.nOverheadParticleTier - 1 > 0 then
|
||||
ParticleManager:SetParticleControl( self.nFXIndex, self.nOverheadParticleTier, Vector( 0, 0, 0 ) )
|
||||
--printf( "DecrementOverheadParticle - self.nOverheadParticleTier: %d", self.nOverheadParticleTier )
|
||||
self.nOverheadParticleTier = nTier
|
||||
else
|
||||
self:Destroy()
|
||||
end
|
||||
end
|
||||
@@ -0,0 +1,94 @@
|
||||
|
||||
modifier_lifestealer_enraged = class({})
|
||||
|
||||
-----------------------------------------------------------------------------------------
|
||||
|
||||
function modifier_lifestealer_enraged:IsPurgable()
|
||||
return false
|
||||
end
|
||||
|
||||
-----------------------------------------------------------------------------------------
|
||||
|
||||
function modifier_lifestealer_enraged:GetStatusEffectName()
|
||||
return "particles/status_fx/status_effect_life_stealer_rage.vpcf"
|
||||
end
|
||||
|
||||
-----------------------------------------------------------------------------------------
|
||||
|
||||
function modifier_lifestealer_enraged:StatusEffectPriority()
|
||||
return 60
|
||||
end
|
||||
|
||||
-----------------------------------------------------------------------------------------
|
||||
|
||||
function modifier_lifestealer_enraged:OnCreated( kv )
|
||||
self.enrage_movespeed_bonus = self:GetAbility():GetSpecialValueFor( "enrage_movespeed_bonus" )
|
||||
self.enrage_attack_speed_bonus = self:GetAbility():GetSpecialValueFor( "enrage_attack_speed_bonus" )
|
||||
self.enrage_model_scale_bonus = self:GetAbility():GetSpecialValueFor( "enrage_model_scale_bonus" )
|
||||
|
||||
if IsServer() then
|
||||
self.nFXIndex = ParticleManager:CreateParticle( "particles/units/heroes/hero_life_stealer/life_stealer_rage.vpcf", PATTACH_ABSORIGIN_FOLLOW, self:GetCaster() )
|
||||
ParticleManager:SetParticleControlEnt( self.nFXIndex, 0, self:GetCaster(), PATTACH_POINT_FOLLOW, "attach_attack1", self:GetCaster():GetAbsOrigin(), true )
|
||||
ParticleManager:SetParticleControlEnt( self.nFXIndex, 1, self:GetCaster(), PATTACH_POINT_FOLLOW, "attach_attack2", self:GetCaster():GetAbsOrigin(), true )
|
||||
ParticleManager:SetParticleControlEnt( self.nFXIndex, 2, self:GetCaster(), PATTACH_POINT_FOLLOW, "attach_hitloc", self:GetCaster():GetAbsOrigin(), true )
|
||||
ParticleManager:SetParticleControlEnt( self.nFXIndex, 3, self:GetCaster(), PATTACH_ABSORIGIN_FOLLOW, nil, self:GetCaster():GetAbsOrigin(), false )
|
||||
self:AddParticle( self.nFXIndex, false, false, -1, false, false )
|
||||
|
||||
EmitSoundOn( "Lifestealer.Enraged.Activate", self:GetParent() )
|
||||
|
||||
local hEnragedPulseAbility = self:GetParent():FindAbilityByName( "aghsfort_lifestealer_enraged_pulse" )
|
||||
|
||||
if hEnragedPulseAbility then
|
||||
ExecuteOrderFromTable({
|
||||
UnitIndex = self:GetParent():entindex(),
|
||||
OrderType = DOTA_UNIT_ORDER_CAST_NO_TARGET,
|
||||
AbilityIndex = hEnragedPulseAbility:entindex()
|
||||
})
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
-----------------------------------------------------------------------------------------
|
||||
|
||||
function modifier_lifestealer_enraged:DeclareFunctions()
|
||||
local funcs =
|
||||
{
|
||||
MODIFIER_PROPERTY_MOVESPEED_BONUS_CONSTANT,
|
||||
MODIFIER_PROPERTY_ATTACKSPEED_BONUS_CONSTANT,
|
||||
MODIFIER_PROPERTY_MODEL_SCALE,
|
||||
}
|
||||
|
||||
return funcs
|
||||
end
|
||||
|
||||
-----------------------------------------------------------------------------------------
|
||||
|
||||
function modifier_lifestealer_enraged:GetModifierMoveSpeedBonus_Constant( params )
|
||||
return self.enrage_movespeed_bonus
|
||||
end
|
||||
|
||||
-----------------------------------------------------------------------------------------
|
||||
|
||||
function modifier_lifestealer_enraged:GetModifierAttackSpeedBonus_Constant( params )
|
||||
return self.enrage_attack_speed_bonus
|
||||
end
|
||||
|
||||
-----------------------------------------------------------------------------------------
|
||||
|
||||
function modifier_lifestealer_enraged:GetModifierModelScale( params )
|
||||
return self.enrage_model_scale_bonus
|
||||
end
|
||||
|
||||
-----------------------------------------------------------------------------------------
|
||||
|
||||
function modifier_lifestealer_enraged:CheckState()
|
||||
local state = {}
|
||||
|
||||
if IsServer() then
|
||||
state[ MODIFIER_STATE_MAGIC_IMMUNE ] = true
|
||||
end
|
||||
|
||||
return state
|
||||
end
|
||||
|
||||
-----------------------------------------------------------------------------------------
|
||||
@@ -0,0 +1,58 @@
|
||||
|
||||
modifier_lifestealer_passive = class({})
|
||||
|
||||
-----------------------------------------------------------------------------------------
|
||||
|
||||
function modifier_lifestealer_passive:IsHidden()
|
||||
return true
|
||||
end
|
||||
|
||||
-----------------------------------------------------------------------------------------
|
||||
|
||||
function modifier_lifestealer_passive:IsPurgable()
|
||||
return false
|
||||
end
|
||||
|
||||
-----------------------------------------------------------------------------------------
|
||||
|
||||
function modifier_lifestealer_passive:GetPriority()
|
||||
return MODIFIER_PRIORITY_ULTRA + 10000
|
||||
end
|
||||
|
||||
-----------------------------------------------------------------------------------------
|
||||
|
||||
function modifier_lifestealer_passive:OnCreated( kv )
|
||||
if IsServer() then
|
||||
self.damage_counter_duration = self:GetAbility():GetSpecialValueFor( "damage_counter_duration" )
|
||||
end
|
||||
end
|
||||
|
||||
-----------------------------------------------------------------------------------------
|
||||
|
||||
function modifier_lifestealer_passive:DeclareFunctions()
|
||||
local funcs =
|
||||
{
|
||||
MODIFIER_EVENT_ON_TAKEDAMAGE,
|
||||
}
|
||||
|
||||
return funcs
|
||||
end
|
||||
|
||||
-----------------------------------------------------------------------------------------
|
||||
|
||||
function modifier_lifestealer_passive:OnTakeDamage( params )
|
||||
if IsServer() then
|
||||
local hAttacker = params.attacker
|
||||
local hVictim = params.unit
|
||||
if hAttacker ~= nil and hVictim ~= nil and hVictim == self:GetParent() then
|
||||
if self:GetParent():FindModifierByName( "modifier_lifestealer_damage_counter" ) == nil then
|
||||
if self:GetParent():FindModifierByName( "modifier_lifestealer_enraged" ) == nil then
|
||||
local kv = { duration = -1 } -- self.damage_counter_duration
|
||||
self:GetParent():AddNewModifier( self:GetParent(), self:GetAbility(), "modifier_lifestealer_damage_counter", kv )
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
return 0
|
||||
end
|
||||
@@ -0,0 +1,82 @@
|
||||
|
||||
modifier_mini_spider_slow_attack = class({})
|
||||
|
||||
------------------------------------------------------------------------------------
|
||||
|
||||
function modifier_mini_spider_slow_attack:IsHidden()
|
||||
return true
|
||||
end
|
||||
|
||||
------------------------------------------------------------------------------------
|
||||
|
||||
function modifier_mini_spider_slow_attack:OnCreated( kv )
|
||||
self.duration = self:GetAbility():GetSpecialValueFor( "duration" )
|
||||
|
||||
if IsServer() then
|
||||
-- Give the spider a chance to get aggro on its own; if it doesn't have it after some delay, we'll assign it
|
||||
local fDelay = 1.5
|
||||
self:StartIntervalThink( fDelay )
|
||||
end
|
||||
end
|
||||
|
||||
------------------------------------------------------------------------------------
|
||||
|
||||
|
||||
function modifier_mini_spider_slow_attack:OnIntervalThink()
|
||||
if IsServer() then
|
||||
if self:GetParent():GetInitialGoalEntity() ~= nil then
|
||||
return -1
|
||||
end
|
||||
|
||||
local hHeroes = FindRealLivingEnemyHeroesInRadius( self:GetParent():GetTeamNumber(), self:GetParent():GetOrigin(), FIND_UNITS_EVERYWHERE )
|
||||
local hNearestHero = hHeroes[ 1 ]
|
||||
if hNearestHero ~= nil then
|
||||
self:GetParent():SetInitialGoalEntity( hNearestHero )
|
||||
end
|
||||
|
||||
return -1
|
||||
end
|
||||
end
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
function modifier_mini_spider_slow_attack:CheckState()
|
||||
local state =
|
||||
{
|
||||
[MODIFIER_STATE_FLYING_FOR_PATHING_PURPOSES_ONLY] = false,
|
||||
}
|
||||
|
||||
return state
|
||||
end
|
||||
|
||||
------------------------------------------------------------------------------------
|
||||
|
||||
function modifier_mini_spider_slow_attack:DeclareFunctions()
|
||||
local funcs =
|
||||
{
|
||||
MODIFIER_EVENT_ON_ATTACKED,
|
||||
}
|
||||
|
||||
return funcs
|
||||
end
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
function modifier_mini_spider_slow_attack:OnAttacked( params )
|
||||
if IsServer() then
|
||||
if params.attacker == self:GetParent() then
|
||||
local hTarget = params.target
|
||||
if hTarget ~= nil then
|
||||
local hDebuff = hTarget:FindModifierByName( "modifier_mini_spider_slow_attack_debuff" )
|
||||
if hDebuff ~= nil then
|
||||
hDebuff:SetDuration( self.duration, true )
|
||||
hDebuff:IncrementStackCount()
|
||||
else
|
||||
hTarget:AddNewModifier( self:GetCaster(), self:GetAbility(), "modifier_mini_spider_slow_attack_debuff", { duration = self.duration } )
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
------------------------------------------------------------------------------------
|
||||
@@ -0,0 +1,32 @@
|
||||
|
||||
modifier_mini_spider_slow_attack_debuff = class({})
|
||||
|
||||
------------------------------------------------------------------------------------
|
||||
|
||||
function modifier_mini_spider_slow_attack_debuff:GetEffectName()
|
||||
return "particles/units/heroes/hero_venomancer/venomancer_poison_debuff.vpcf"
|
||||
end
|
||||
|
||||
------------------------------------------------------------------------------------
|
||||
|
||||
function modifier_mini_spider_slow_attack_debuff:OnCreated( kv )
|
||||
self.movement_speed_slow = self:GetAbility():GetSpecialValueFor( "movement_speed_slow" )
|
||||
end
|
||||
|
||||
------------------------------------------------------------------------------------
|
||||
|
||||
function modifier_mini_spider_slow_attack_debuff:DeclareFunctions()
|
||||
local funcs =
|
||||
{
|
||||
MODIFIER_PROPERTY_MOVESPEED_BONUS_PERCENTAGE,
|
||||
}
|
||||
return funcs
|
||||
end
|
||||
|
||||
------------------------------------------------------------------------------------
|
||||
|
||||
function modifier_mini_spider_slow_attack_debuff:GetModifierMoveSpeedBonus_Percentage( params )
|
||||
return self.movement_speed_slow * self:GetStackCount()
|
||||
end
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
@@ -0,0 +1,101 @@
|
||||
modifier_morty_start_passive = class({})
|
||||
----------------------------------------------------------------------------------
|
||||
|
||||
function modifier_morty_start_passive:IsHidden()
|
||||
return true
|
||||
end
|
||||
|
||||
----------------------------------------------------------------------------------
|
||||
|
||||
function modifier_morty_start_passive:IsPurgable()
|
||||
return false
|
||||
end
|
||||
|
||||
----------------------------------------------------------------------------------
|
||||
|
||||
function modifier_morty_start_passive:OnCreated( kv )
|
||||
if IsServer() then
|
||||
self.hPlayerEnt = nil
|
||||
self.bRideComplete = false
|
||||
self.bRideStarted = false
|
||||
end
|
||||
end
|
||||
|
||||
----------------------------------------------------------------------------------
|
||||
|
||||
function modifier_morty_start_passive:CheckState()
|
||||
local state =
|
||||
{
|
||||
[MODIFIER_STATE_NO_HEALTH_BAR] = true,
|
||||
[MODIFIER_STATE_COMMAND_RESTRICTED] = true,
|
||||
}
|
||||
return state
|
||||
end
|
||||
|
||||
|
||||
-----------------------------------------------------------------------
|
||||
|
||||
function modifier_morty_start_passive:DeclareFunctions()
|
||||
local funcs =
|
||||
{
|
||||
MODIFIER_EVENT_ON_ORDER,
|
||||
}
|
||||
return funcs
|
||||
end
|
||||
|
||||
-----------------------------------------------------------------------
|
||||
|
||||
function modifier_morty_start_passive:OnOrder( params )
|
||||
if IsServer() then
|
||||
local hOrderedUnit = params.unit
|
||||
local hTargetUnit = params.target
|
||||
local nOrderType = params.order_type
|
||||
if nOrderType ~= DOTA_UNIT_ORDER_MOVE_TO_TARGET and nOrderType ~= DOTA_UNIT_ORDER_ATTACK_TARGET then
|
||||
return
|
||||
end
|
||||
|
||||
if hTargetUnit == nil or hTargetUnit ~= self:GetParent() then
|
||||
return
|
||||
end
|
||||
|
||||
if hOrderedUnit ~= nil and hOrderedUnit:IsRealHero() and hOrderedUnit:GetTeamNumber() == DOTA_TEAM_GOODGUYS and hTargetUnit:GetOwnerEntity() == hOrderedUnit then
|
||||
self.hPlayerEnt = hOrderedUnit
|
||||
self:StartIntervalThink( 0.25 )
|
||||
return
|
||||
end
|
||||
|
||||
self:StartIntervalThink( -1 )
|
||||
end
|
||||
|
||||
return 0
|
||||
end
|
||||
|
||||
|
||||
-----------------------------------------------------------------------
|
||||
|
||||
function modifier_morty_start_passive:OnIntervalThink()
|
||||
if IsServer() then
|
||||
if self.hPlayerEnt ~= nil then
|
||||
local flTalkDistance = 250.0
|
||||
if flTalkDistance >= ( self.hPlayerEnt:GetOrigin() - self:GetParent():GetOrigin() ):Length2D() then
|
||||
if GameRules.Aghanim ~= nil and self.bRideStarted == false then
|
||||
self.hPlayerEnt:Interrupt()
|
||||
|
||||
self:StartIntervalThink( -1 )
|
||||
self.bRideStarted = true
|
||||
|
||||
local hRideMorty = self.hPlayerEnt:AddNewModifier( self:GetParent(), nil, "modifier_ride_morty", {} )
|
||||
if hRideMorty ~= nil then
|
||||
self.hPlayerEnt:RemoveModifierByName( "modifier_bonus_room_start" )
|
||||
end
|
||||
|
||||
if self.Encounter ~= nil then
|
||||
self.Encounter:OnPlayerRideMorty( self.hPlayerEnt:GetPlayerOwnerID(), self:GetParent() )
|
||||
end
|
||||
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -0,0 +1,56 @@
|
||||
|
||||
modifier_nyx_suicide_heal = class({})
|
||||
|
||||
--------------------------------------------------------------
|
||||
|
||||
function modifier_nyx_suicide_heal:IsHidden()
|
||||
return true
|
||||
end
|
||||
|
||||
--------------------------------------------------------------
|
||||
|
||||
function modifier_nyx_suicide_heal:IsPurgable()
|
||||
return true
|
||||
end
|
||||
|
||||
--------------------------------------------------------------
|
||||
|
||||
function modifier_nyx_suicide_heal:DeclareFunctions()
|
||||
local funcs =
|
||||
{
|
||||
MODIFIER_EVENT_ON_DEATH,
|
||||
}
|
||||
|
||||
return funcs
|
||||
end
|
||||
-------------------------------------------------------------------
|
||||
|
||||
function modifier_nyx_suicide_heal:OnDeath( params )
|
||||
if IsServer() then
|
||||
if params.unit == self:GetParent() then
|
||||
local heal = self:GetAbility():GetSpecialValueFor( "heal" )
|
||||
local radius = self:GetAbility():GetSpecialValueFor( "radius" )
|
||||
|
||||
if self:GetParent().nFXIndex ~= nil then
|
||||
ParticleManager:DestroyParticle( self:GetParent().nFXIndex, true )
|
||||
end
|
||||
|
||||
EmitSoundOn( "Burrower.HealExplosion", self:GetParent() )
|
||||
|
||||
local nFXIndex2 = ParticleManager:CreateParticle( "particles/nyx_swarm_explosion/nyx_swarm_explosion.vpcf", PATTACH_CUSTOMORIGIN, nil )
|
||||
ParticleManager:SetParticleControlEnt( nFXIndex2, 0, self:GetParent(), PATTACH_POINT_FOLLOW, "attach_hitloc", self:GetParent():GetOrigin(), true )
|
||||
ParticleManager:SetParticleControlEnt( nFXIndex2, 1, self:GetParent(), PATTACH_ABSORIGIN_FOLLOW, nil, self:GetParent():GetOrigin(), true )
|
||||
ParticleManager:SetParticleControl( nFXIndex2, 2, Vector( radius, radius, radius ) )
|
||||
ParticleManager:ReleaseParticleIndex( nFXIndex2 )
|
||||
|
||||
local entities = FindUnitsInRadius( self:GetParent():GetTeamNumber(), self:GetParent():GetOrigin(), nil, radius, DOTA_UNIT_TARGET_TEAM_BOTH, DOTA_UNIT_TARGET_HERO + DOTA_UNIT_TARGET_BASIC, DOTA_UNIT_TARGET_FLAG_MAGIC_IMMUNE_ENEMIES + DOTA_UNIT_TARGET_FLAG_FOW_VISIBLE, FIND_CLOSEST, false )
|
||||
for _,entity in pairs( entities ) do
|
||||
if entity ~= nil and entity:IsAlive() then
|
||||
entity:Heal( heal, self:GetAbility() )
|
||||
ParticleManager:ReleaseParticleIndex( ParticleManager:CreateParticle( "particles/items3_fx/fish_bones_active.vpcf", PATTACH_ABSORIGIN_FOLLOW, entity ) )
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -0,0 +1,52 @@
|
||||
|
||||
modifier_ogre_magi_area_ignite_thinker = class({})
|
||||
|
||||
----------------------------------------------------------------------------------------
|
||||
|
||||
function modifier_ogre_magi_area_ignite_thinker:OnCreated( kv )
|
||||
if IsServer() then
|
||||
self.radius = self:GetAbility():GetSpecialValueFor( "radius" )
|
||||
self.area_duration = self:GetAbility():GetSpecialValueFor( "area_duration" )
|
||||
self.linger_duration = self:GetAbility():GetSpecialValueFor( "linger_duration" )
|
||||
self.bImpact = false
|
||||
end
|
||||
end
|
||||
|
||||
----------------------------------------------------------------------------------------
|
||||
|
||||
function modifier_ogre_magi_area_ignite_thinker:OnImpact()
|
||||
if IsServer() then
|
||||
local nFXIndex = ParticleManager:CreateParticle( "particles/neutral_fx/black_dragon_fireball.vpcf", PATTACH_WORLDORIGIN, nil );
|
||||
ParticleManager:SetParticleControl( nFXIndex, 0, self:GetParent():GetOrigin() );
|
||||
ParticleManager:SetParticleControl( nFXIndex, 1, self:GetParent():GetOrigin() );
|
||||
ParticleManager:SetParticleControl( nFXIndex, 2, Vector( self.area_duration, 0, 0 ) );
|
||||
ParticleManager:ReleaseParticleIndex( nFXIndex );
|
||||
|
||||
EmitSoundOn( "OgreMagi.Ignite.Target", self:GetParent() )
|
||||
|
||||
self:SetDuration( self.area_duration, true )
|
||||
self.bImpact = true
|
||||
|
||||
self:StartIntervalThink( 0.5 )
|
||||
end
|
||||
end
|
||||
|
||||
----------------------------------------------------------------------------------------
|
||||
|
||||
function modifier_ogre_magi_area_ignite_thinker:OnIntervalThink()
|
||||
if IsServer() then
|
||||
if self.bImpact == false then
|
||||
self:OnImpact()
|
||||
return
|
||||
end
|
||||
|
||||
local enemies = FindUnitsInRadius( self:GetParent():GetTeamNumber(), self:GetParent():GetOrigin(), self:GetParent(), self.radius, DOTA_UNIT_TARGET_TEAM_ENEMY, DOTA_UNIT_TARGET_HERO + DOTA_UNIT_TARGET_BASIC, DOTA_UNIT_TARGET_FLAG_MAGIC_IMMUNE_ENEMIES, 0, false )
|
||||
for _,enemy in pairs( enemies ) do
|
||||
if enemy ~= nil then
|
||||
enemy:AddNewModifier( self:GetCaster(), self:GetAbility(), "modifier_ogre_magi_ignite", { duration = self.linger_duration } )
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
----------------------------------------------------------------------------------------
|
||||
@@ -0,0 +1,64 @@
|
||||
|
||||
modifier_ogre_magi_channelled_bloodlust = class({})
|
||||
|
||||
-----------------------------------------------------------------------------
|
||||
|
||||
function modifier_ogre_magi_channelled_bloodlust:GetAttributes()
|
||||
return MODIFIER_ATTRIBUTE_MULTIPLE
|
||||
end
|
||||
|
||||
-----------------------------------------------------------------------------
|
||||
|
||||
function modifier_ogre_magi_channelled_bloodlust:GetEffectName()
|
||||
return "particles/units/heroes/hero_ogre_magi/ogre_magi_bloodlust_buff.vpcf"
|
||||
end
|
||||
|
||||
-----------------------------------------------------------------------------
|
||||
|
||||
function modifier_ogre_magi_channelled_bloodlust:OnCreated( kv )
|
||||
if not self:GetAbility() then
|
||||
return
|
||||
end
|
||||
|
||||
self.bonus_attack_speed = self:GetAbility():GetSpecialValueFor( "bonus_attack_speed" )
|
||||
self.bonus_movement_speed = self:GetAbility():GetSpecialValueFor( "bonus_movement_speed" )
|
||||
self.modelscale = self:GetAbility():GetSpecialValueFor( "modelscale" )
|
||||
|
||||
if IsServer() then
|
||||
local nFXIndex = ParticleManager:CreateParticle( "particles/units/heroes/hero_pugna/pugna_life_drain.vpcf", PATTACH_CUSTOMORIGIN, self:GetParent() )
|
||||
ParticleManager:SetParticleControlEnt( nFXIndex, 0, self:GetCaster(), PATTACH_POINT_FOLLOW, "attach_hitloc", self:GetCaster():GetOrigin(), true )
|
||||
ParticleManager:SetParticleControlEnt( nFXIndex, 1, self:GetParent(), PATTACH_POINT_FOLLOW, "attach_hitloc", self:GetParent():GetOrigin(), true )
|
||||
self:AddParticle( nFXIndex , true, false, 0, false, false )
|
||||
end
|
||||
end
|
||||
|
||||
-----------------------------------------------------------------------------
|
||||
|
||||
function modifier_ogre_magi_channelled_bloodlust:DeclareFunctions()
|
||||
local funcs =
|
||||
{
|
||||
MODIFIER_PROPERTY_ATTACKSPEED_BONUS_CONSTANT,
|
||||
MODIFIER_PROPERTY_MOVESPEED_BONUS_PERCENTAGE,
|
||||
MODIFIER_PROPERTY_MODEL_SCALE,
|
||||
}
|
||||
return funcs
|
||||
end
|
||||
|
||||
|
||||
-----------------------------------------------------------------------------
|
||||
|
||||
function modifier_ogre_magi_channelled_bloodlust:GetModifierAttackSpeedBonus_Constant( params )
|
||||
return self.bonus_attack_speed
|
||||
end
|
||||
|
||||
-----------------------------------------------------------------------------
|
||||
|
||||
function modifier_ogre_magi_channelled_bloodlust:GetModifierMoveSpeedBonus_Percentage( params )
|
||||
return self.bonus_movement_speed
|
||||
end
|
||||
|
||||
-----------------------------------------------------------------------------
|
||||
|
||||
function modifier_ogre_magi_channelled_bloodlust:GetModifierModelScale( params )
|
||||
return self.modelscale
|
||||
end
|
||||
@@ -0,0 +1,52 @@
|
||||
|
||||
modifier_ogre_seer_area_ignite_thinker = class({})
|
||||
|
||||
----------------------------------------------------------------------------------------
|
||||
|
||||
function modifier_ogre_seer_area_ignite_thinker:OnCreated( kv )
|
||||
if IsServer() then
|
||||
self.radius = self:GetAbility():GetSpecialValueFor( "radius" )
|
||||
self.area_duration = self:GetAbility():GetSpecialValueFor( "area_duration" )
|
||||
self.linger_duration = self:GetAbility():GetSpecialValueFor( "linger_duration" )
|
||||
self.bImpact = false
|
||||
end
|
||||
end
|
||||
|
||||
----------------------------------------------------------------------------------------
|
||||
|
||||
function modifier_ogre_seer_area_ignite_thinker:OnImpact()
|
||||
if IsServer() then
|
||||
local nFXIndex = ParticleManager:CreateParticle( "particles/neutral_fx/black_dragon_fireball.vpcf", PATTACH_WORLDORIGIN, nil );
|
||||
ParticleManager:SetParticleControl( nFXIndex, 0, self:GetParent():GetOrigin() );
|
||||
ParticleManager:SetParticleControl( nFXIndex, 1, self:GetParent():GetOrigin() );
|
||||
ParticleManager:SetParticleControl( nFXIndex, 2, Vector( self.area_duration, 0, 0 ) );
|
||||
ParticleManager:ReleaseParticleIndex( nFXIndex );
|
||||
|
||||
EmitSoundOn( "OgreMagi.Ignite.Target", self:GetParent() )
|
||||
|
||||
self:SetDuration( self.area_duration, true )
|
||||
self.bImpact = true
|
||||
|
||||
self:StartIntervalThink( 0.5 )
|
||||
end
|
||||
end
|
||||
|
||||
----------------------------------------------------------------------------------------
|
||||
|
||||
function modifier_ogre_seer_area_ignite_thinker:OnIntervalThink()
|
||||
if IsServer() then
|
||||
if self.bImpact == false then
|
||||
self:OnImpact()
|
||||
return
|
||||
end
|
||||
|
||||
local enemies = FindUnitsInRadius( self:GetParent():GetTeamNumber(), self:GetParent():GetOrigin(), self:GetParent(), self.radius, DOTA_UNIT_TARGET_TEAM_ENEMY, DOTA_UNIT_TARGET_HERO + DOTA_UNIT_TARGET_BASIC, DOTA_UNIT_TARGET_FLAG_MAGIC_IMMUNE_ENEMIES, 0, false )
|
||||
for _,enemy in pairs( enemies ) do
|
||||
if enemy ~= nil then
|
||||
enemy:AddNewModifier( self:GetCaster(), self:GetAbility(), "modifier_ogre_magi_ignite", { duration = self.linger_duration } )
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
----------------------------------------------------------------------------------------
|
||||
@@ -0,0 +1,80 @@
|
||||
|
||||
modifier_ogre_tank_melee_smash_thinker = class({})
|
||||
|
||||
-----------------------------------------------------------------------------
|
||||
|
||||
function modifier_ogre_tank_melee_smash_thinker:OnCreated( kv )
|
||||
if IsServer() then
|
||||
self.impact_radius = self:GetAbility():GetSpecialValueFor( "impact_radius" )
|
||||
self.stun_duration = self:GetAbility():GetSpecialValueFor( "stun_duration" )
|
||||
self.damage = self:GetAbility():GetSpecialValueFor( "damage" )
|
||||
|
||||
self:StartIntervalThink( 0.01 )
|
||||
end
|
||||
end
|
||||
|
||||
-----------------------------------------------------------------------------
|
||||
|
||||
function modifier_ogre_tank_melee_smash_thinker:OnIntervalThink()
|
||||
if IsServer() then
|
||||
if self:GetCaster() == nil or self:GetCaster():IsNull() or self:GetCaster():IsAlive() == false or self:GetCaster():IsStunned() then
|
||||
--print( string.format( "Caster is nil, dead, or stunned, removing smash thinker" ) )
|
||||
UTIL_Remove( self:GetParent() )
|
||||
return -1
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
-----------------------------------------------------------------------------
|
||||
|
||||
function modifier_ogre_tank_melee_smash_thinker:OnDestroy()
|
||||
if IsServer() then
|
||||
if self:GetCaster() ~= nil and self:GetCaster():IsAlive() then
|
||||
EmitSoundOnLocationWithCaster( self:GetParent():GetOrigin(), "OgreTank.GroundSmash", self:GetCaster() )
|
||||
local nFXIndex = ParticleManager:CreateParticle( "particles/creatures/ogre/ogre_melee_smash.vpcf", PATTACH_WORLDORIGIN, self:GetCaster() )
|
||||
ParticleManager:SetParticleControl( nFXIndex, 0, self:GetParent():GetOrigin() )
|
||||
ParticleManager:SetParticleControl( nFXIndex, 1, Vector( self.impact_radius, self.impact_radius, self.impact_radius ) )
|
||||
ParticleManager:ReleaseParticleIndex( nFXIndex )
|
||||
|
||||
local nTeamFlags = DOTA_UNIT_TARGET_TEAM_ENEMY
|
||||
if self:GetCaster():FindModifierByName( "modifier_aghsfort_winter_wyvern_winters_curse" ) then
|
||||
nTeamFlags = DOTA_UNIT_TARGET_TEAM_BOTH
|
||||
end
|
||||
|
||||
local enemies = FindUnitsInRadius( self:GetParent():GetTeamNumber(), self:GetParent():GetOrigin(), self:GetParent(), self.impact_radius, nTeamFlags, DOTA_UNIT_TARGET_HERO + DOTA_UNIT_TARGET_BASIC, DOTA_UNIT_TARGET_FLAG_MAGIC_IMMUNE_ENEMIES, 0, false )
|
||||
for _,enemy in pairs( enemies ) do
|
||||
if not ( enemy:IsNull() ) and enemy ~= nil and enemy:IsInvulnerable() == false then
|
||||
local damageInfo =
|
||||
{
|
||||
victim = enemy,
|
||||
attacker = self:GetCaster(),
|
||||
damage = self.damage,
|
||||
damage_type = DAMAGE_TYPE_PHYSICAL,
|
||||
ability = self,
|
||||
}
|
||||
|
||||
ApplyDamage( damageInfo )
|
||||
if not ( enemy:IsNull() ) and enemy ~= nil and enemy:IsAlive() == false then
|
||||
local nFXIndex = ParticleManager:CreateParticle( "particles/units/heroes/hero_phantom_assassin/phantom_assassin_crit_impact.vpcf", PATTACH_CUSTOMORIGIN, nil )
|
||||
ParticleManager:SetParticleControlEnt( nFXIndex, 0, enemy, PATTACH_POINT_FOLLOW, "attach_hitloc", enemy:GetOrigin(), true )
|
||||
ParticleManager:SetParticleControl( nFXIndex, 1, enemy:GetOrigin() )
|
||||
ParticleManager:SetParticleControlForward( nFXIndex, 1, -self:GetCaster():GetForwardVector() )
|
||||
ParticleManager:SetParticleControlEnt( nFXIndex, 10, enemy, PATTACH_ABSORIGIN_FOLLOW, nil, enemy:GetOrigin(), true )
|
||||
ParticleManager:ReleaseParticleIndex( nFXIndex )
|
||||
|
||||
EmitSoundOn( "Dungeon.BloodSplatterImpact", enemy )
|
||||
elseif not ( enemy:IsNull() ) and enemy ~= nil then
|
||||
enemy:AddNewModifier( self:GetCaster(), self:GetAbility(), "modifier_stunned", { duration = self.stun_duration } )
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
ScreenShake( self:GetParent():GetOrigin(), 10.0, 100.0, 0.5, 1300.0, 0, true )
|
||||
|
||||
UTIL_Remove( self:GetParent() )
|
||||
end
|
||||
end
|
||||
|
||||
-----------------------------------------------------------------------------
|
||||
|
||||
@@ -0,0 +1,237 @@
|
||||
|
||||
modifier_ogreseal_flop = class({})
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
local OGRE_MINIMUM_HEIGHT_ABOVE_LOWEST = 150
|
||||
local OGRE_MINIMUM_HEIGHT_ABOVE_HIGHEST = 33
|
||||
local OGRE_ACCELERATION_Z = 1250
|
||||
local OGRE_MAX_HORIZONTAL_ACCELERATION = 800
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
function modifier_ogreseal_flop:IsStunDebuff()
|
||||
return true
|
||||
end
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
function modifier_ogreseal_flop:IsHidden()
|
||||
return true
|
||||
end
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
function modifier_ogreseal_flop:IsPurgable()
|
||||
return false
|
||||
end
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
function modifier_ogreseal_flop:RemoveOnDeath()
|
||||
return false
|
||||
end
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
function modifier_ogreseal_flop:OnCreated( kv )
|
||||
if IsServer() then
|
||||
if self.nHopCount == nil then
|
||||
self.nHopCount = 1
|
||||
self.flop_distances = { 200, 400, 400 }
|
||||
|
||||
local nFXIndex = ParticleManager:CreateParticle( "particles/creatures/ogre_seal/ogre_seal_warcry.vpcf", PATTACH_ABSORIGIN_FOLLOW, self:GetParent() )
|
||||
ParticleManager:SetParticleControlEnt( nFXIndex, 1, self:GetParent(), PATTACH_POINT_FOLLOW, "attach_hitloc", self:GetParent():GetOrigin(), true )
|
||||
if self:GetCaster():IsRealHero() == false then
|
||||
ParticleManager:SetParticleControlEnt( nFXIndex, 2, self:GetParent(), PATTACH_POINT_FOLLOW, "mouth", self:GetParent():GetOrigin(), true )
|
||||
ParticleManager:SetParticleControlEnt( nFXIndex, 6, self:GetParent(), PATTACH_POINT_FOLLOW, "eye_L", self:GetParent():GetOrigin(), true )
|
||||
ParticleManager:SetParticleControlEnt( nFXIndex, 7, self:GetParent(), PATTACH_POINT_FOLLOW, "eye_R", self:GetParent():GetOrigin(), true )
|
||||
end
|
||||
|
||||
self:AddParticle( nFXIndex, false, false, -1, false, false )
|
||||
end
|
||||
|
||||
if self:GetCaster():IsRealHero() then
|
||||
self:GetCaster():StartGesture( ACT_DOTA_FLAIL )
|
||||
end
|
||||
|
||||
self.bHorizontalMotionInterrupted = false
|
||||
self.bDamageApplied = false
|
||||
self.bTargetTeleported = false
|
||||
|
||||
if self:ApplyHorizontalMotionController() == false or self:ApplyVerticalMotionController() == false then
|
||||
self:Destroy()
|
||||
return
|
||||
end
|
||||
|
||||
self.flTimer = 0.0
|
||||
self.vStartPosition = GetGroundPosition( self:GetParent():GetOrigin(), self:GetParent() )
|
||||
self.flCurrentTimeHoriz = 0.0
|
||||
self.flCurrentTimeVert = 0.0
|
||||
|
||||
self.vLoc = Vector( kv.vLocX, kv.vLocY, kv.vLocZ )
|
||||
self.vLastKnownTargetPos = self.vLoc
|
||||
|
||||
local duration = self:GetAbility():GetSpecialValueFor( "duration" )
|
||||
local flDesiredHeight = OGRE_MINIMUM_HEIGHT_ABOVE_LOWEST * self.nHopCount * duration * duration
|
||||
local flLowZ = math.min( self.vLastKnownTargetPos.z, self.vStartPosition.z )
|
||||
local flHighZ = math.max( self.vLastKnownTargetPos.z, self.vStartPosition.z )
|
||||
local flArcTopZ = math.max( flLowZ + flDesiredHeight, flHighZ + OGRE_MINIMUM_HEIGHT_ABOVE_HIGHEST * self.nHopCount )
|
||||
|
||||
local flArcDeltaZ = flArcTopZ - self.vStartPosition.z
|
||||
self.flInitialVelocityZ = math.sqrt( 2.0 * flArcDeltaZ * OGRE_ACCELERATION_Z * self.nHopCount )
|
||||
|
||||
local flDeltaZ = self.vLastKnownTargetPos.z - self.vStartPosition.z
|
||||
local flSqrtDet = math.sqrt( math.max( 0, ( self.flInitialVelocityZ * self.flInitialVelocityZ ) - 2.0 * OGRE_ACCELERATION_Z * self.nHopCount * flDeltaZ ) )
|
||||
self.flPredictedTotalTime = math.max( ( self.flInitialVelocityZ + flSqrtDet) / ( OGRE_ACCELERATION_Z * self.nHopCount ), ( self.flInitialVelocityZ - flSqrtDet) / ( OGRE_ACCELERATION_Z * self.nHopCount ) )
|
||||
|
||||
self.vHorizontalVelocity = ( self.vLastKnownTargetPos - self.vStartPosition ) / self.flPredictedTotalTime
|
||||
self.vHorizontalVelocity.z = 0.0
|
||||
end
|
||||
end
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
function modifier_ogreseal_flop:OnDestroy()
|
||||
if IsServer() then
|
||||
self:GetParent():RemoveHorizontalMotionController( self )
|
||||
self:GetParent():RemoveVerticalMotionController( self )
|
||||
|
||||
if self:GetCaster():IsRealHero() then
|
||||
self:GetCaster():RemoveGesture( ACT_DOTA_FLAIL )
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
function modifier_ogreseal_flop:DeclareFunctions()
|
||||
local funcs =
|
||||
{
|
||||
-- MODIFIER_PROPERTY_OVERRIDE_ANIMATION,
|
||||
}
|
||||
|
||||
return funcs
|
||||
end
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
function modifier_ogreseal_flop:CheckState()
|
||||
local state =
|
||||
{
|
||||
[MODIFIER_STATE_STUNNED] = true,
|
||||
}
|
||||
|
||||
return state
|
||||
end
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
function modifier_ogreseal_flop:UpdateHorizontalMotion( me, dt )
|
||||
if IsServer() then
|
||||
self.flTimer = self.flTimer + dt
|
||||
self.flCurrentTimeHoriz = math.min( self.flCurrentTimeHoriz + dt, self.flPredictedTotalTime )
|
||||
local t = self.flCurrentTimeHoriz / self.flPredictedTotalTime
|
||||
local vStartToTarget = self.vLastKnownTargetPos - self.vStartPosition
|
||||
local vDesiredPos = self.vStartPosition + t * vStartToTarget
|
||||
|
||||
GridNav:DestroyTreesAroundPoint( me:GetAbsOrigin(), 75, false )
|
||||
|
||||
--[[
|
||||
-- Prevent players from hopping through obstructions (players can cast ogre seal flop with the Ogre Seal Totem item)
|
||||
if me:IsRealHero() then
|
||||
if ( not GridNav:CanFindPath( me:GetOrigin(), vDesiredPos ) ) then
|
||||
self:Destroy()
|
||||
return
|
||||
end
|
||||
end
|
||||
]]
|
||||
|
||||
local vOldPos = me:GetOrigin()
|
||||
local vToDesired = vDesiredPos - vOldPos
|
||||
vToDesired.z = 0.0
|
||||
local vDesiredVel = vToDesired / dt
|
||||
local vVelDif = vDesiredVel - self.vHorizontalVelocity
|
||||
local flVelDif = vVelDif:Length2D()
|
||||
vVelDif = vVelDif:Normalized()
|
||||
local flVelDelta = math.min( flVelDif, OGRE_MAX_HORIZONTAL_ACCELERATION * self.nHopCount )
|
||||
|
||||
self.vHorizontalVelocity = self.vHorizontalVelocity + vVelDif * flVelDelta * dt
|
||||
local vNewPos = vOldPos + self.vHorizontalVelocity * dt
|
||||
me:SetOrigin( vNewPos )
|
||||
end
|
||||
end
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
function modifier_ogreseal_flop:UpdateVerticalMotion( me, dt )
|
||||
if IsServer() then
|
||||
self.flCurrentTimeVert = self.flCurrentTimeVert + dt
|
||||
local bGoingDown = ( -OGRE_ACCELERATION_Z * self.nHopCount * self.flCurrentTimeVert + self.flInitialVelocityZ ) < 0
|
||||
|
||||
local vNewPos = me:GetOrigin()
|
||||
vNewPos.z = self.vStartPosition.z + ( -0.5 * OGRE_ACCELERATION_Z * self.nHopCount * ( self.flCurrentTimeVert * self.flCurrentTimeVert ) + self.flInitialVelocityZ * self.flCurrentTimeVert )
|
||||
|
||||
local flGroundHeight = GetGroundHeight( vNewPos, self:GetParent() )
|
||||
local bLanded = false
|
||||
if ( vNewPos.z < flGroundHeight and bGoingDown == true ) then
|
||||
vNewPos.z = flGroundHeight
|
||||
bLanded = true
|
||||
end
|
||||
|
||||
me:SetOrigin( vNewPos )
|
||||
if bLanded == true then
|
||||
|
||||
local bDoneHopping = self.nHopCount == 3
|
||||
|
||||
if self.bHorizontalMotionInterrupted == false then
|
||||
if self.nHopCount > 1 then
|
||||
|
||||
self:GetAbility():TryToDamage()
|
||||
self.flTimer = 0.0
|
||||
end
|
||||
else
|
||||
bDoneHopping = true
|
||||
end
|
||||
|
||||
if bDoneHopping then
|
||||
self:Destroy()
|
||||
|
||||
else
|
||||
self.nHopCount = self.nHopCount + 1
|
||||
self.vLoc = self.vLoc + self:GetCaster():GetForwardVector() * self.flop_distances[ self.nHopCount ]
|
||||
local kv =
|
||||
{
|
||||
vLocX = self.vLoc.x,
|
||||
vLocY = self.vLoc.y,
|
||||
vLocZ = self.vLoc.z,
|
||||
}
|
||||
self:OnCreated( kv )
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
function modifier_ogreseal_flop:OnHorizontalMotionInterrupted()
|
||||
if IsServer() then
|
||||
self.bHorizontalMotionInterrupted = true
|
||||
end
|
||||
end
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
function modifier_ogreseal_flop:OnVerticalMotionInterrupted()
|
||||
if IsServer() then
|
||||
self:Destroy()
|
||||
end
|
||||
end
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
function modifier_ogreseal_flop:GetOverrideAnimation( params )
|
||||
return ACT_DOTA_OVERRIDE_ABILITY_2
|
||||
end
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
@@ -0,0 +1,47 @@
|
||||
|
||||
modifier_phoenix_passive = class({})
|
||||
|
||||
-----------------------------------------------------------------------------------------
|
||||
|
||||
function modifier_phoenix_passive:IsHidden()
|
||||
return true
|
||||
end
|
||||
|
||||
-----------------------------------------------------------------------------------------
|
||||
|
||||
function modifier_phoenix_passive:IsPurgable()
|
||||
return false
|
||||
end
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
function modifier_phoenix_passive:GetPriority()
|
||||
return MODIFIER_PRIORITY_ULTRA + 10000
|
||||
end
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
function modifier_phoenix_passive:OnCreated( kv )
|
||||
if IsServer() then
|
||||
self:GetParent().bAbsoluteNoCC = true -- keep this for the modifier blacklist
|
||||
end
|
||||
end
|
||||
|
||||
-----------------------------------------------------------------------------------------
|
||||
|
||||
function modifier_phoenix_passive:CheckState()
|
||||
local state =
|
||||
{
|
||||
[MODIFIER_STATE_HEXED] = false,
|
||||
[MODIFIER_STATE_ROOTED] = false,
|
||||
[MODIFIER_STATE_SILENCED] = false,
|
||||
[MODIFIER_STATE_STUNNED] = false,
|
||||
[MODIFIER_STATE_FROZEN] = false,
|
||||
[MODIFIER_STATE_FEARED] = false,
|
||||
|
||||
-- absolute_no_cc was preventing Phoenix from being motion controlled by his own Dive
|
||||
--[MODIFIER_STATE_CANNOT_BE_MOTION_CONTROLLED] = true,
|
||||
}
|
||||
|
||||
return state
|
||||
end
|
||||
@@ -0,0 +1,129 @@
|
||||
|
||||
modifier_puck_flying_bomb = class({})
|
||||
|
||||
-------------------------------------------------------------------
|
||||
|
||||
function modifier_puck_flying_bomb:IsHidden()
|
||||
return true
|
||||
end
|
||||
|
||||
-------------------------------------------------------------------
|
||||
|
||||
function modifier_puck_flying_bomb:IsPurgable()
|
||||
return false
|
||||
end
|
||||
|
||||
-------------------------------------------------------------------
|
||||
|
||||
function modifier_puck_flying_bomb:RemoveOnDeath()
|
||||
return false
|
||||
end
|
||||
|
||||
-------------------------------------------------------------------
|
||||
|
||||
function modifier_puck_flying_bomb:OnCreated( kv )
|
||||
if IsServer() then
|
||||
self.explosion_damage = self:GetAbility():GetSpecialValueFor( "explosion_damage" )
|
||||
self.flight_duration = self:GetAbility():GetSpecialValueFor( "flight_duration" )
|
||||
self.stun_duration = self:GetAbility():GetSpecialValueFor( "stun_duration" )
|
||||
self.explosion_radius = self:GetAbility():GetSpecialValueFor( "explosion_radius" )
|
||||
self.flight_speed = self:GetAbility():GetSpecialValueFor( "flight_speed" )
|
||||
|
||||
self.hBomb = CreateUnitByName( "npc_dota_beastmaster_axe", self:GetParent():GetOrigin(), false, nil, nil, self:GetParent():GetTeamNumber() )
|
||||
if self.hBomb == nil then
|
||||
self:Destroy()
|
||||
return
|
||||
end
|
||||
|
||||
self.hBomb:SetBaseMoveSpeed( self.flight_speed )
|
||||
|
||||
self.hBomb:AddEffects( EF_NODRAW )
|
||||
self.hBomb:AddNewModifier( self:GetCaster(), self:GetAbility(), "modifier_beastmaster_axe_invulnerable", kv )
|
||||
|
||||
self.vSourceLoc = self:GetCaster():GetOrigin()
|
||||
--self.vSourceLoc.z = self.vSourceLoc.z + 50
|
||||
self.vTargetLoc = Vector( kv["x"], kv["y"], self.vSourceLoc.z )
|
||||
local flGroundHeight = GetGroundHeight( self.vTargetLoc, nil )
|
||||
self.vTargetLoc.z = flGroundHeight + 50
|
||||
|
||||
local nDestinationRadius = self.explosion_radius / 2
|
||||
self.nPreviewFX = ParticleManager:CreateParticle( "particles/creatures/puck/flying_bomb_destination.vpcf", PATTACH_ABSORIGIN, self:GetCaster() )
|
||||
ParticleManager:SetParticleControlEnt( self.nPreviewFX, 0, self, PATTACH_ABSORIGIN, nil, self.vTargetLoc, true )
|
||||
ParticleManager:SetParticleControl( self.nPreviewFX, 1, Vector( nDestinationRadius, nDestinationRadius, nDestinationRadius ) )
|
||||
ParticleManager:SetParticleControl( self.nPreviewFX, 15, Vector( 190, 6, 215 ) )
|
||||
|
||||
local vForward = self:GetCaster():GetForwardVector()
|
||||
self.hBomb:SetForwardVector( vForward )
|
||||
|
||||
self.nBombFXIndex = ParticleManager:CreateParticle( "particles/creatures/puck/puck_flying_bomb.vpcf", PATTACH_CUSTOMORIGIN, nil )
|
||||
ParticleManager:SetParticleControlEnt( self.nBombFXIndex, 0, self.hBomb, PATTACH_ABSORIGIN_FOLLOW, nil, self.hBomb:GetOrigin(), true )
|
||||
|
||||
EmitSoundOn( "Puck.FlyingBomb.Flight", self.hBomb )
|
||||
|
||||
self:StartIntervalThink( 0.05 )
|
||||
end
|
||||
end
|
||||
|
||||
-------------------------------------------------------------------
|
||||
|
||||
function modifier_puck_flying_bomb:OnIntervalThink()
|
||||
if IsServer() then
|
||||
if not self.bIssuedMoveCommand then
|
||||
ExecuteOrderFromTable({
|
||||
UnitIndex = self.hBomb:entindex(),
|
||||
OrderType = DOTA_UNIT_ORDER_MOVE_TO_POSITION,
|
||||
Position = self.vTargetLoc,
|
||||
})
|
||||
|
||||
self.bIssuedMoveCommand = true
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
function modifier_puck_flying_bomb:OnDestroy()
|
||||
if IsServer() then
|
||||
if self.nPreviewFX ~= nil then
|
||||
ParticleManager:DestroyParticle( self.nPreviewFX, false )
|
||||
self.nPreviewFX = nil
|
||||
end
|
||||
|
||||
local enemies = FindUnitsInRadius( self:GetParent():GetTeamNumber(), self.hBomb:GetOrigin(), self.hBomb, self.explosion_radius, DOTA_UNIT_TARGET_TEAM_ENEMY, DOTA_UNIT_TARGET_HERO + DOTA_UNIT_TARGET_BASIC, DOTA_UNIT_TARGET_FLAG_MAGIC_IMMUNE_ENEMIES, 0, false )
|
||||
for _,enemy in pairs( enemies ) do
|
||||
if enemy ~= nil and enemy:IsInvulnerable() == false then
|
||||
local damageInfo =
|
||||
{
|
||||
victim = enemy,
|
||||
attacker = self:GetCaster(),
|
||||
damage = self.explosion_damage,
|
||||
damage_type = self:GetAbility():GetAbilityDamageType(),
|
||||
ability = self:GetAbility(),
|
||||
}
|
||||
ApplyDamage( damageInfo )
|
||||
enemy:AddNewModifier( self:GetCaster(), self:GetAbility(), "modifier_stunned", { duration = self.stun_duration } )
|
||||
|
||||
local nFXIndex = ParticleManager:CreateParticle( "particles/units/heroes/hero_beastmaster/beastmaster_wildaxes_hit.vpcf", PATTACH_CUSTOMORIGIN, nil )
|
||||
ParticleManager:SetParticleControlEnt( nFXIndex, 0, enemy, PATTACH_POINT_FOLLOW, "attach_hitloc", enemy:GetOrigin(), true )
|
||||
ParticleManager:ReleaseParticleIndex( nFXIndex )
|
||||
end
|
||||
end
|
||||
|
||||
if self.nBombFXIndex then
|
||||
ParticleManager:DestroyParticle( self.nBombFXIndex, true )
|
||||
end
|
||||
|
||||
local vDetonationPos = self.hBomb:GetAbsOrigin() + Vector( 0, 0, 100 )
|
||||
local nDetonationFX = ParticleManager:CreateParticle( "particles/creatures/puck/puck_bomb_detonation.vpcf", PATTACH_CUSTOMORIGIN, nil )
|
||||
ParticleManager:SetParticleControl( nDetonationFX, 0, vDetonationPos )
|
||||
ParticleManager:SetParticleControl( nDetonationFX, 1, Vector( self.explosion_radius, self.explosion_radius, self.explosion_radius ) )
|
||||
ParticleManager:ReleaseParticleIndex( nDetonationFX )
|
||||
|
||||
StopSoundOn( "Puck.FlyingBomb.Flight", self.hBomb )
|
||||
EmitSoundOn( "Puck.FlyingBomb.Detonate", self.hBomb )
|
||||
|
||||
UTIL_Remove( self.hBomb )
|
||||
end
|
||||
end
|
||||
|
||||
-------------------------------------------------------------------
|
||||
@@ -0,0 +1,98 @@
|
||||
|
||||
modifier_rock_golem_split = class({})
|
||||
|
||||
-----------------------------------------------------------------------------------------
|
||||
|
||||
function modifier_rock_golem_split:GetTexture()
|
||||
return "sandking_caustic_finale"
|
||||
end
|
||||
|
||||
-----------------------------------------------------------------------------------------
|
||||
|
||||
function modifier_rock_golem_split:OnCreated( kv )
|
||||
|
||||
if not IsServer() then
|
||||
return
|
||||
end
|
||||
|
||||
self.unit_count = self:GetAbility():GetSpecialValueFor( "unit_count" )
|
||||
self.spawn_radius = self:GetAbility():GetSpecialValueFor( "spawn_radius" )
|
||||
self.knockback_duration_min = self:GetAbility():GetSpecialValueFor( "knockback_duration_min" )
|
||||
self.knockback_duration_max = self:GetAbility():GetSpecialValueFor( "knockback_duration_max" )
|
||||
self.knockback_distance_min = self:GetAbility():GetSpecialValueFor( "knockback_distance_min" )
|
||||
self.knockback_distance_max = self:GetAbility():GetSpecialValueFor( "knockback_distance_max" )
|
||||
self.knockback_height_min = self:GetAbility():GetSpecialValueFor( "knockback_height_min" )
|
||||
self.knockback_height_max = self:GetAbility():GetSpecialValueFor( "knockback_height_max" )
|
||||
|
||||
self.split_fx = self:GetAbility().strSplitFx
|
||||
self.summoned_unit = self:GetAbility().strSummonedUnit
|
||||
|
||||
end
|
||||
|
||||
-----------------------------------------------------------------------------------------
|
||||
|
||||
function modifier_rock_golem_split:DeclareFunctions()
|
||||
local funcs =
|
||||
{
|
||||
MODIFIER_EVENT_ON_DEATH,
|
||||
}
|
||||
|
||||
return funcs
|
||||
end
|
||||
|
||||
-----------------------------------------------------------------------------------------
|
||||
|
||||
function modifier_rock_golem_split:OnDeath( params )
|
||||
if not IsServer() or params.unit ~= self:GetParent() then
|
||||
return 0
|
||||
end
|
||||
|
||||
EmitSoundOn( "Ability.SplitA", self:GetParent() )
|
||||
|
||||
local nDeathFX = ParticleManager:CreateParticle( self.split_fx, PATTACH_ABSORIGIN, self:GetParent() )
|
||||
|
||||
ParticleManager:SetParticleControl( nDeathFX, 1, Vector( 100, 1, 1 ) );
|
||||
ParticleManager:SetParticleControl( nDeathFX, 2, Vector( 1, 1, 1 ) );
|
||||
ParticleManager:SetParticleControl( nDeathFX, 3, Vector( 100, 100, 100 ) );
|
||||
ParticleManager:SetParticleControl( nDeathFX, 4, Vector( 200, 200, 200 ) );
|
||||
ParticleManager:SetParticleControl( nDeathFX, 14, Vector( 1, 1, 1 ) );
|
||||
ParticleManager:SetParticleControl( nDeathFX, 15, Vector( 100, 100, 100 ) );
|
||||
|
||||
ParticleManager:ReleaseParticleIndex( nDeathFX )
|
||||
|
||||
for i = 1,self.unit_count do
|
||||
local knockback_duration = RandomFloat( self.knockback_duration_min, self.knockback_duration_max )
|
||||
local knockback_distance = RandomFloat( self.knockback_distance_min, self.knockback_distance_max )
|
||||
local knockback_height = RandomFloat( self.knockback_height_min, self.knockback_height_max )
|
||||
print( 'duration: ' .. knockback_duration .. '. distance ' .. knockback_distance .. '. height ' .. knockback_height )
|
||||
|
||||
local kv =
|
||||
{
|
||||
center_x = self:GetParent():GetAbsOrigin().x,
|
||||
center_y = self:GetParent():GetAbsOrigin().y,
|
||||
center_z = self:GetParent():GetAbsOrigin().z,
|
||||
should_stun = true,
|
||||
duration = knockback_duration,
|
||||
knockback_duration = knockback_duration,
|
||||
knockback_distance = knockback_distance,
|
||||
knockback_height = knockback_height,
|
||||
}
|
||||
|
||||
vSpawnPosition = self:GetParent():GetAbsOrigin() + RandomVector( self.spawn_radius )
|
||||
vSpawnPosition = FindPathablePositionNearby( vSpawnPosition, 250, 250 )
|
||||
|
||||
vSpawnDirection = vSpawnPosition - self:GetParent():GetAbsOrigin()
|
||||
vSpawnDirection = vSpawnDirection:Normalized()
|
||||
local angles = VectorAngles( vSpawnDirection )
|
||||
|
||||
local hSplitUnit = CreateUnitByName( self.summoned_unit , vSpawnPosition, true,
|
||||
self:GetCaster(), self:GetCaster(), self:GetCaster():GetTeamNumber() )
|
||||
|
||||
hSplitUnit:SetAbsAngles( angles.x, angles.y, angles.z )
|
||||
|
||||
hSplitUnit:AddNewModifier( hSplitUnit, self:GetAbility(), "modifier_knockback", kv )
|
||||
|
||||
end
|
||||
|
||||
return 0
|
||||
end
|
||||
@@ -0,0 +1,110 @@
|
||||
modifier_sand_king_boss_burrow = class({})
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
function modifier_sand_king_boss_burrow:IsHidden()
|
||||
return true
|
||||
end
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
function modifier_sand_king_boss_burrow:IsPurgable()
|
||||
return false
|
||||
end
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
function modifier_sand_king_boss_burrow:GetPriority()
|
||||
return MODIFIER_PRIORITY_SUPER_ULTRA
|
||||
end
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
function modifier_sand_king_boss_burrow:OnCreated( kv )
|
||||
if IsServer() then
|
||||
local flInterval = 0.65
|
||||
if self:GetParent():GetHealthPercent() < 50 then
|
||||
flInterval = 0.5
|
||||
end
|
||||
if self:GetParent():GetHealthPercent() < 25 then
|
||||
flInterval = 0.3
|
||||
end
|
||||
self:StartIntervalThink( flInterval )
|
||||
end
|
||||
end
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
function modifier_sand_king_boss_burrow:CheckState()
|
||||
local state =
|
||||
{
|
||||
[MODIFIER_STATE_ROOTED] = true,
|
||||
[MODIFIER_STATE_DISARMED] = true,
|
||||
[MODIFIER_STATE_STUNNED] = false,
|
||||
}
|
||||
return state
|
||||
end
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
function modifier_sand_king_boss_burrow:DeclareFunctions()
|
||||
local funcs =
|
||||
{
|
||||
MODIFIER_PROPERTY_TRANSLATE_ACTIVITY_MODIFIERS,
|
||||
MODIFIER_PROPERTY_TURN_RATE_PERCENTAGE,
|
||||
}
|
||||
return funcs
|
||||
end
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
function modifier_sand_king_boss_burrow:GetActivityTranslationModifiers( params )
|
||||
return "burrowed"
|
||||
end
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
function modifier_sand_king_boss_burrow:GetModifierTurnRate_Percentage( params )
|
||||
return -50
|
||||
end
|
||||
|
||||
-----------------------------------------------------------------------------------------
|
||||
|
||||
function modifier_sand_king_boss_burrow:OnIntervalThink()
|
||||
if IsServer() then
|
||||
local nBurrowerType = RandomInt( 0, 1 )
|
||||
local szBurrowerName = nil
|
||||
if nBurrowerType == 0 then
|
||||
szBurrowerName = "npc_dota_creature_healing_burrower"
|
||||
end
|
||||
if nBurrowerType == 1 then
|
||||
szBurrowerName = "npc_dota_creature_big_exploding_burrower"
|
||||
end
|
||||
|
||||
local hMinion = CreateUnitByName( szBurrowerName, self:GetCaster():GetAbsOrigin(), true, self:GetCaster(), self:GetCaster(), self:GetCaster():GetTeamNumber() )
|
||||
if hMinion ~= nil then
|
||||
if self:GetCaster().zone ~= nil then
|
||||
self:GetCaster().zone:AddEnemyToZone( hMinion )
|
||||
end
|
||||
hMinion.hParent = self:GetCaster()
|
||||
|
||||
local vCasterPos = self:GetCaster():GetAbsOrigin()
|
||||
local vSpawnPoint = vCasterPos + RandomVector( 1 ) * 2500
|
||||
if nBurrowerType ~= 0 then
|
||||
vSpawnPoint = vCasterPos + RandomVector( RandomFloat( 200, 500 ) )
|
||||
end
|
||||
|
||||
FindClearSpaceForUnit( hMinion, vSpawnPoint, true )
|
||||
|
||||
local nFXIndex = ParticleManager:CreateParticle( "particles/units/heroes/hero_visage/visage_summon_familiars.vpcf", PATTACH_CUSTOMORIGIN, self:GetCaster() )
|
||||
ParticleManager:SetParticleControl( nFXIndex, 0, vSpawnPoint )
|
||||
ParticleManager:ReleaseParticleIndex( nFXIndex )
|
||||
|
||||
if nBurrowerType == 0 then
|
||||
local nFxIndex2 = ParticleManager:CreateParticle( "particles/units/heroes/hero_huskar/huskar_inner_vitality.vpcf", PATTACH_ABSORIGIN_FOLLOW, hMinion )
|
||||
ParticleManager:SetParticleControlEnt( nFxIndex2, 0, hMinion, PATTACH_ABSORIGIN_FOLLOW, nil, hMinion:GetOrigin(), false )
|
||||
hMinion.nFXIndex = nFxIndex2
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -0,0 +1,123 @@
|
||||
modifier_sand_king_boss_burrowstrike = class ({})
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
function modifier_sand_king_boss_burrowstrike:IsPurgable()
|
||||
return false
|
||||
end
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
function modifier_sand_king_boss_burrowstrike:IsHidden()
|
||||
return true
|
||||
end
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
function modifier_sand_king_boss_burrowstrike:GetPriority()
|
||||
return MODIFIER_PRIORITY_SUPER_ULTRA
|
||||
end
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
function modifier_sand_king_boss_burrowstrike:OnCreated( kv )
|
||||
if IsServer() then
|
||||
self.vTarget = Vector( kv["x"], kv["y"], kv["z"] )
|
||||
self.vDir = self.vTarget - self:GetParent():GetOrigin()
|
||||
self.vDir = self.vDir:Normalized()
|
||||
|
||||
local flHealthPct = self:GetParent():GetHealthPercent() / 100
|
||||
self.speed = self:GetAbility():GetSpecialValueFor( "speed" ) + ( self:GetAbility():GetSpecialValueFor( "scaling_speed" ) * ( 1 - flHealthPct ) )
|
||||
self.radius = self:GetAbility():GetSpecialValueFor( "radius" )
|
||||
|
||||
self:GetParent():AddEffects( EF_NODRAW )
|
||||
self.nFXIndex = -1
|
||||
self.nFXIndex2 = -1
|
||||
self.nFXIndex3 = -1
|
||||
self:OnIntervalThink()
|
||||
self:StartIntervalThink( 0.33 )
|
||||
if self:ApplyHorizontalMotionController() == false then
|
||||
self:Destroy()
|
||||
return
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
function modifier_sand_king_boss_burrowstrike:OnDestroy()
|
||||
if IsServer() then
|
||||
self:GetParent():RemoveHorizontalMotionController( self )
|
||||
self:GetParent():RemoveEffects( EF_NODRAW )
|
||||
local kv =
|
||||
{
|
||||
x = self.vDir.x,
|
||||
y = self.vDir.y,
|
||||
z = self.vDir.z,
|
||||
}
|
||||
self:GetParent():AddNewModifier( self:GetParent(), self:GetAbility(), "modifier_sand_king_boss_burrowstrike_end", kv )
|
||||
end
|
||||
end
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
function modifier_sand_king_boss_burrowstrike:OnIntervalThink()
|
||||
if IsServer() then
|
||||
if self.nFXIndex ~= -1 then
|
||||
ParticleManager:DestroyParticle( self.nFXIndex, false )
|
||||
end
|
||||
if self.nFXIndex2 ~= -1 then
|
||||
ParticleManager:DestroyParticle( self.nFXIndex2, false )
|
||||
end
|
||||
if self.nFXIndex3 ~= -1 then
|
||||
ParticleManager:DestroyParticle( self.nFXIndex3, false )
|
||||
end
|
||||
|
||||
self.nFXIndex = ParticleManager:CreateParticle("particles/units/heroes/hero_nyx_assassin/nyx_assassin_burrow.vpcf", PATTACH_CUSTOMORIGIN, nil )
|
||||
ParticleManager:SetParticleControl( self.nFXIndex, 0, self:GetParent():GetOrigin() )
|
||||
ParticleManager:SetParticleControlForward( self.nFXIndex, 0, self:GetParent():GetForwardVector() )
|
||||
self.nFXIndex2 = ParticleManager:CreateParticle("particles/units/heroes/hero_nyx_assassin/nyx_assassin_burrow.vpcf", PATTACH_CUSTOMORIGIN, nil )
|
||||
ParticleManager:SetParticleControl( self.nFXIndex2, 0, self:GetParent():GetOrigin() + RandomVector( 1 ) * RandomInt( 50, 150 ) )
|
||||
ParticleManager:SetParticleControlForward( self.nFXIndex2, 0, self:GetParent():GetRightVector() )
|
||||
self.nFXIndex3 = ParticleManager:CreateParticle("particles/units/heroes/hero_nyx_assassin/nyx_assassin_burrow.vpcf", PATTACH_CUSTOMORIGIN, nil )
|
||||
ParticleManager:SetParticleControl( self.nFXIndex3, 0, self:GetParent():GetOrigin() + RandomVector( 1 ) * RandomInt( 50, 150 ) )
|
||||
ParticleManager:SetParticleControlForward( self.nFXIndex3, 0, -self:GetParent():GetRightVector() )
|
||||
|
||||
EmitSoundOn( "Hero_NyxAssassin.Burrow.In", self:GetParent() )
|
||||
|
||||
local enemies = FindUnitsInRadius( self:GetParent():GetTeamNumber(), self:GetParent():GetOrigin(), self:GetParent(), self.radius / 2, DOTA_UNIT_TARGET_TEAM_ENEMY, DOTA_UNIT_TARGET_HERO + DOTA_UNIT_TARGET_BASIC, DOTA_UNIT_TARGET_FLAG_MAGIC_IMMUNE_ENEMIES, 0, false )
|
||||
if #enemies > 0 then
|
||||
self:Destroy()
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
function modifier_sand_king_boss_burrowstrike:UpdateHorizontalMotion( me, dt )
|
||||
if IsServer() then
|
||||
local vNewLocation = self:GetParent():GetOrigin() + self.vDir * self.speed * dt
|
||||
me:SetOrigin( vNewLocation )
|
||||
end
|
||||
end
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
function modifier_sand_king_boss_burrowstrike:OnHorizontalMotionInterrupted()
|
||||
if IsServer() then
|
||||
self:Destroy()
|
||||
end
|
||||
end
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
function modifier_sand_king_boss_burrowstrike:CheckState()
|
||||
local state =
|
||||
{
|
||||
[MODIFIER_STATE_STUNNED] = true,
|
||||
[MODIFIER_STATE_INVULNERABLE] = true,
|
||||
}
|
||||
return state
|
||||
end
|
||||
|
||||
|
||||
@@ -0,0 +1,215 @@
|
||||
modifier_sand_king_boss_burrowstrike_end = class ({})
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
function modifier_sand_king_boss_burrowstrike_end:IsPurgable()
|
||||
return false
|
||||
end
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
function modifier_sand_king_boss_burrowstrike_end:IsHidden()
|
||||
return true
|
||||
end
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
function modifier_sand_king_boss_burrowstrike_end:GetPriority()
|
||||
return MODIFIER_PRIORITY_SUPER_ULTRA
|
||||
end
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
function modifier_sand_king_boss_burrowstrike_end:OnCreated( kv )
|
||||
if IsServer() then
|
||||
self.vDir = Vector( kv["x"], kv["y"], kv["z"] )
|
||||
|
||||
local flHealthPct = self:GetParent():GetHealthPercent() / 100
|
||||
self.speed = self:GetAbility():GetSpecialValueFor( "speed" ) + ( self:GetAbility():GetSpecialValueFor( "scaling_speed" ) * ( 1 - flHealthPct ) )
|
||||
|
||||
self.delay = self:GetAbility():GetSpecialValueFor( "delay" )
|
||||
self.damage = self:GetAbility():GetSpecialValueFor( "damage" )
|
||||
self.radius = self:GetAbility():GetSpecialValueFor( "radius" )
|
||||
self.stun_duration = self:GetAbility():GetSpecialValueFor( "stun_duration" )
|
||||
self.knockback_distance = self:GetAbility():GetSpecialValueFor( "knockback_distance" )
|
||||
self.knockback_height = self:GetAbility():GetSpecialValueFor( "knockback_height" )
|
||||
|
||||
self.bExitGround = false
|
||||
|
||||
self:StartIntervalThink( 0.1 )
|
||||
|
||||
|
||||
if self:ApplyHorizontalMotionController() == false then
|
||||
self:Destroy()
|
||||
return
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
function modifier_sand_king_boss_burrowstrike_end:OnIntervalThink()
|
||||
if IsServer() then
|
||||
if self.bExitGround == false then
|
||||
EmitSoundOn( "SandKingBoss.BurrowStrike", self:GetParent() )
|
||||
|
||||
local enemies = FindUnitsInRadius( self:GetParent():GetTeamNumber(), self:GetParent():GetOrigin(), self:GetParent(), self.radius, DOTA_UNIT_TARGET_TEAM_ENEMY, DOTA_UNIT_TARGET_HERO + DOTA_UNIT_TARGET_BASIC, DOTA_UNIT_TARGET_FLAG_MAGIC_IMMUNE_ENEMIES, 0, false )
|
||||
for _,enemy in pairs( enemies ) do
|
||||
if enemy ~= nil and enemy:IsInvulnerable() == false then
|
||||
local damageInfo =
|
||||
{
|
||||
victim = enemy,
|
||||
attacker = self:GetCaster(),
|
||||
damage = self.damage,
|
||||
damage_type = DAMAGE_TYPE_MAGICAL,
|
||||
ability = self,
|
||||
}
|
||||
|
||||
ApplyDamage( damageInfo )
|
||||
local kv =
|
||||
{
|
||||
center_x = self:GetParent():GetOrigin().x,
|
||||
center_y = self:GetParent():GetOrigin().y,
|
||||
center_z = self:GetParent():GetOrigin().z,
|
||||
should_stun = true,
|
||||
duration = self.stun_duration,
|
||||
knockback_duration = self.stun_duration,
|
||||
knockback_distance = self.knockback_distance,
|
||||
knockback_height = self.knockback_height,
|
||||
}
|
||||
enemy:AddNewModifier( self:GetCaster(), self:GetAbility(), "modifier_knockback", kv )
|
||||
|
||||
local nFXIndex = ParticleManager:CreateParticle( "particles/units/heroes/hero_elder_titan/elder_titan_echo_stomp_impact_physical.vpcf", PATTACH_ABSORIGIN_FOLLOW, enemy )
|
||||
local vDirection = enemy:GetOrigin() - self:GetParent():GetOrigin()
|
||||
vDirection.z = 0.0
|
||||
vDirection = vDirection:Normalized()
|
||||
|
||||
ParticleManager:SetParticleControl( nFXIndex, 1, enemy:GetOrigin() )
|
||||
ParticleManager:SetParticleControlForward( nFXIndex, 1, vDirection )
|
||||
ParticleManager:ReleaseParticleIndex( nFXIndex )
|
||||
end
|
||||
end
|
||||
self.bExitGround = true
|
||||
self:StartIntervalThink( self.delay - 0.1 )
|
||||
else
|
||||
local nFXCastIndex = ParticleManager:CreateParticle( "particles/units/heroes/hero_elder_titan/elder_titan_echo_stomp_physical.vpcf", PATTACH_ABSORIGIN_FOLLOW, self:GetParent() )
|
||||
ParticleManager:SetParticleControl( nFXCastIndex, 1, Vector( self.radius, self.radius, self.radius ) )
|
||||
ParticleManager:ReleaseParticleIndex( nFXCastIndex )
|
||||
EmitSoundOn( "Burrower.Explosion", self:GetCaster() )
|
||||
|
||||
local enemies = FindUnitsInRadius( self:GetParent():GetTeamNumber(), self:GetParent():GetOrigin(), self:GetParent(), self.radius, DOTA_UNIT_TARGET_TEAM_ENEMY, DOTA_UNIT_TARGET_HERO + DOTA_UNIT_TARGET_BASIC, DOTA_UNIT_TARGET_FLAG_MAGIC_IMMUNE_ENEMIES, 0, false )
|
||||
for _,enemy in pairs( enemies ) do
|
||||
if enemy ~= nil and enemy:IsInvulnerable() == false then
|
||||
local damageInfo =
|
||||
{
|
||||
victim = enemy,
|
||||
attacker = self:GetCaster(),
|
||||
damage = self.damage,
|
||||
damage_type = DAMAGE_TYPE_MAGICAL,
|
||||
ability = self,
|
||||
}
|
||||
|
||||
ApplyDamage( damageInfo )
|
||||
local kv =
|
||||
{
|
||||
center_x = self:GetParent():GetOrigin().x,
|
||||
center_y = self:GetParent():GetOrigin().y,
|
||||
center_z = self:GetParent():GetOrigin().z,
|
||||
should_stun = true,
|
||||
duration = self.stun_duration,
|
||||
knockback_duration = self.stun_duration,
|
||||
knockback_distance = self.knockback_distance,
|
||||
knockback_height = self.knockback_height,
|
||||
}
|
||||
enemy:AddNewModifier( self:GetCaster(), self:GetAbility(), "modifier_knockback", kv )
|
||||
|
||||
local nFXIndex = ParticleManager:CreateParticle( "particles/units/heroes/hero_elder_titan/elder_titan_echo_stomp_impact_physical.vpcf", PATTACH_ABSORIGIN_FOLLOW, enemy )
|
||||
local vDirection = enemy:GetOrigin() - self:GetParent():GetOrigin()
|
||||
vDirection.z = 0.0
|
||||
vDirection = vDirection:Normalized()
|
||||
|
||||
ParticleManager:SetParticleControl( nFXIndex, 1, enemy:GetOrigin() )
|
||||
ParticleManager:SetParticleControlForward( nFXIndex, 1, vDirection )
|
||||
ParticleManager:ReleaseParticleIndex( nFXIndex )
|
||||
end
|
||||
end
|
||||
self:Destroy()
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
function modifier_sand_king_boss_burrowstrike_end:UpdateHorizontalMotion( me, dt )
|
||||
if IsServer() then
|
||||
local vNewLocation = self:GetParent():GetOrigin() + self.vDir * ( self.speed / 2 ) * dt
|
||||
me:SetOrigin( vNewLocation )
|
||||
end
|
||||
end
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
function modifier_sand_king_boss_burrowstrike_end:OnHorizontalMotionInterrupted()
|
||||
if IsServer() then
|
||||
self:Destroy()
|
||||
end
|
||||
end
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
function modifier_sand_king_boss_burrowstrike_end:OnDestroy()
|
||||
if IsServer() then
|
||||
self:GetParent():RemoveHorizontalMotionController( self )
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
function modifier_sand_king_boss_burrowstrike_end:CheckState()
|
||||
if IsServer() then
|
||||
local state =
|
||||
{
|
||||
[MODIFIER_STATE_INVISIBLE] = self.bExitGround ~= true,
|
||||
[MODIFIER_STATE_STUNNED] = true,
|
||||
}
|
||||
end
|
||||
return state
|
||||
end
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
function modifier_sand_king_boss_burrowstrike_end:DeclareFunctions()
|
||||
local funcs =
|
||||
{
|
||||
MODIFIER_PROPERTY_OVERRIDE_ANIMATION,
|
||||
MODIFIER_PROPERTY_OVERRIDE_ANIMATION_RATE,
|
||||
MODIFIER_PROPERTY_TRANSLATE_ACTIVITY_MODIFIERS,
|
||||
MODIFIER_PROPERTY_DISABLE_TURNING,
|
||||
}
|
||||
return funcs
|
||||
end
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
function modifier_sand_king_boss_burrowstrike_end:GetModifierDisableTurning( params )
|
||||
return 1
|
||||
end
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
function modifier_sand_king_boss_burrowstrike_end:GetOverrideAnimation( params )
|
||||
return ACT_DOTA_SAND_KING_BURROW_OUT
|
||||
end
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
|
||||
function modifier_sand_king_boss_burrowstrike_end:GetOverrideAnimationRate( params )
|
||||
return 0.5
|
||||
end
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
|
||||
function modifier_sand_king_boss_burrowstrike_end:GetActivityTranslationModifiers( params )
|
||||
return "sandking_rubyspire_burrowstrike"
|
||||
end
|
||||
@@ -0,0 +1,70 @@
|
||||
|
||||
modifier_sand_king_boss_caustic_finale = class({})
|
||||
|
||||
-----------------------------------------------------------------------------------------
|
||||
|
||||
function modifier_sand_king_boss_caustic_finale:GetTexture()
|
||||
return "sandking_caustic_finale"
|
||||
end
|
||||
|
||||
-----------------------------------------------------------------------------------------
|
||||
|
||||
function modifier_sand_king_boss_caustic_finale:OnCreated( kv )
|
||||
self.caustic_radius = self:GetAbility():GetSpecialValueFor( "caustic_radius" )
|
||||
self.caustic_damage = self:GetAbility():GetSpecialValueFor( "caustic_damage" )
|
||||
self.nArmorReductionPerStack = math.max( math.floor( self:GetAbility():GetSpecialValueFor( "caustic_armor_reduction_pct" ) * self:GetParent():GetPhysicalArmorValue( false ) / 100 ), 1 )
|
||||
if IsServer() then
|
||||
ParticleManager:ReleaseParticleIndex( ParticleManager:CreateParticle( "particles/units/heroes/hero_sandking/sandking_caustic_finale_debuff.vpcf", PATTACH_ABSORIGIN, self:GetParent() ) )
|
||||
end
|
||||
end
|
||||
|
||||
-----------------------------------------------------------------------------------------
|
||||
|
||||
function modifier_sand_king_boss_caustic_finale:DeclareFunctions()
|
||||
local funcs =
|
||||
{
|
||||
MODIFIER_PROPERTY_PHYSICAL_ARMOR_BONUS,
|
||||
MODIFIER_EVENT_ON_DEATH,
|
||||
}
|
||||
|
||||
return funcs
|
||||
end
|
||||
|
||||
-----------------------------------------------------------------------------------------
|
||||
|
||||
function modifier_sand_king_boss_caustic_finale:GetModifierPhysicalArmorBonus()
|
||||
if self.nArmorReductionPerStack == nil then
|
||||
return 0
|
||||
end
|
||||
|
||||
return self.nArmorReductionPerStack * self:GetStackCount() * -1
|
||||
end
|
||||
|
||||
-----------------------------------------------------------------------------------------
|
||||
|
||||
function modifier_sand_king_boss_caustic_finale:OnDeath( params )
|
||||
if IsServer() then
|
||||
if params.unit == self:GetParent() then
|
||||
EmitSoundOn( "Ability.SandKing_CausticFinale", self:GetParent() )
|
||||
ParticleManager:ReleaseParticleIndex( ParticleManager:CreateParticle( "particles/units/heroes/hero_sandking/sandking_caustic_finale_explode.vpcf", PATTACH_ABSORIGIN, self:GetParent() ) )
|
||||
local enemies = FindUnitsInRadius( self:GetCaster():GetTeamNumber(), self:GetParent():GetOrigin(), nil, self.caustic_radius, DOTA_UNIT_TARGET_TEAM_ENEMY, DOTA_UNIT_TARGET_HERO + DOTA_UNIT_TARGET_BASIC, DOTA_UNIT_TARGET_FLAG_FOW_VISIBLE, FIND_CLOSEST, false )
|
||||
for _,hEnemy in pairs( enemies ) do
|
||||
if hEnemy ~= nil and hEnemy:IsAlive() and hEnemy:IsInvulnerable() == false then
|
||||
local damageInfo =
|
||||
{
|
||||
victim = hEnemy,
|
||||
attacker = self:GetCaster(),
|
||||
damage = self.caustic_damage,
|
||||
damage_type = DAMAGE_TYPE_MAGICAL,
|
||||
ability = self,
|
||||
}
|
||||
ApplyDamage( damageInfo )
|
||||
|
||||
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
return 0
|
||||
end
|
||||
@@ -0,0 +1,99 @@
|
||||
modifier_sand_king_boss_directional_move = class({})
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
function modifier_sand_king_boss_directional_move:IsHidden()
|
||||
return true
|
||||
end
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
function modifier_sand_king_boss_directional_move:IsPurgable()
|
||||
return false
|
||||
end
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
function modifier_sand_king_boss_directional_move:OnCreated( kv )
|
||||
if IsServer() then
|
||||
|
||||
self.speed = self:GetAbility():GetSpecialValueFor( "speed" )
|
||||
if self:ApplyHorizontalMotionController() == false then
|
||||
self:Destroy()
|
||||
return
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
function modifier_sand_king_boss_directional_move:OnDestroy()
|
||||
if IsServer() then
|
||||
self:GetParent():RemoveHorizontalMotionController( self )
|
||||
self:GetParent():Interrupt()
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
function modifier_sand_king_boss_directional_move:UpdateHorizontalMotion( me, dt )
|
||||
if IsServer() then
|
||||
self.vMoveDir = nil
|
||||
if self:GetAbility():GetAbilityName() == "sand_king_boss_move_left" then
|
||||
self.vMoveDir = -self:GetParent():GetRightVector()
|
||||
end
|
||||
if self:GetAbility():GetAbilityName() == "sand_king_boss_move_right" then
|
||||
self.vMoveDir = self:GetParent():GetRightVector()
|
||||
end
|
||||
if self:GetAbility():GetAbilityName() == "sand_king_boss_move_back" then
|
||||
self.vMoveDir = -self:GetParent():GetForwardVector()
|
||||
end
|
||||
local vNewPos = self:GetParent():GetOrigin() + ( self.vMoveDir * self.speed * dt )
|
||||
if not GridNav:CanFindPath( self:GetParent():GetOrigin(), vNewPos ) then
|
||||
self:Destroy()
|
||||
return
|
||||
end
|
||||
me:SetOrigin( vNewPos )
|
||||
end
|
||||
end
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
function modifier_sand_king_boss_directional_move:OnHorizontalMotionInterrupted()
|
||||
if IsServer() then
|
||||
self:Destroy()
|
||||
end
|
||||
end
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
function modifier_sand_king_boss_directional_move:DeclareFunctions()
|
||||
local funcs =
|
||||
{
|
||||
MODIFIER_PROPERTY_TRANSLATE_ACTIVITY_MODIFIERS,
|
||||
MODIFIER_PROPERTY_TURN_RATE_PERCENTAGE,
|
||||
}
|
||||
return funcs
|
||||
end
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
function modifier_sand_king_boss_directional_move:GetActivityTranslationModifiers( params )
|
||||
if self:GetAbility():GetAbilityName() == "sand_king_boss_move_left" then -- @fixme: GetAbility can be nil here
|
||||
return "left"
|
||||
end
|
||||
if self:GetAbility():GetAbilityName() == "sand_king_boss_move_right" then
|
||||
return "right"
|
||||
end
|
||||
if self:GetAbility():GetAbilityName() == "sand_king_boss_move_back" then
|
||||
return "backward"
|
||||
end
|
||||
return ""
|
||||
end
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
function modifier_sand_king_boss_directional_move:GetModifierTurnRate_Percentage( params )
|
||||
return -90
|
||||
end
|
||||
@@ -0,0 +1,111 @@
|
||||
modifier_sand_king_boss_epicenter = class({})
|
||||
|
||||
-----------------------------------------------------------------------------
|
||||
|
||||
function modifier_sand_king_boss_epicenter:IsHidden()
|
||||
return true
|
||||
end
|
||||
|
||||
-----------------------------------------------------------------------------
|
||||
|
||||
function modifier_sand_king_boss_epicenter:IsPurgable()
|
||||
return false
|
||||
end
|
||||
|
||||
-----------------------------------------------------------------------------
|
||||
|
||||
function modifier_sand_king_boss_epicenter:OnCreated( kv )
|
||||
if IsServer() then
|
||||
if self:GetAbility().nCastCount == nil then
|
||||
self:GetAbility().nCastCount = 1
|
||||
else
|
||||
self:GetAbility().nCastCount = self:GetAbility().nCastCount + 1
|
||||
end
|
||||
self.damage = self:GetAbility():GetSpecialValueFor( "damage" )
|
||||
self.interval = self:GetAbility():GetSpecialValueFor( "interval" )
|
||||
self.pulse_width = self:GetAbility():GetSpecialValueFor( "pulse_width" )
|
||||
self.pulse_end_width = self:GetAbility():GetSpecialValueFor( "pulse_end_width" )
|
||||
self.pulse_speed = math.min( self:GetAbility():GetSpecialValueFor( "min_pulse_speed" ) + self:GetAbility():GetSpecialValueFor( "speed_step" ) * self:GetAbility().nCastCount, self:GetAbility():GetSpecialValueFor( "max_pulse_speed" ) )
|
||||
self.pulse_distance = self:GetAbility():GetSpecialValueFor( "pulse_distance" )
|
||||
self.random_pulses_step = self:GetAbility():GetSpecialValueFor( "random_pulses_step" )
|
||||
self.random_pulses = math.min( self:GetAbility():GetSpecialValueFor( "min_random_pulses" ) + ( self:GetAbility().nCastCount * self.random_pulses_step ), self:GetAbility():GetSpecialValueFor( "max_random_pulses" ) )
|
||||
self:StartIntervalThink( self.interval )
|
||||
end
|
||||
end
|
||||
|
||||
-----------------------------------------------------------------------------
|
||||
|
||||
function modifier_sand_king_boss_epicenter:OnDestroy()
|
||||
if IsServer() then
|
||||
end
|
||||
end
|
||||
|
||||
-----------------------------------------------------------------------------
|
||||
|
||||
function modifier_sand_king_boss_epicenter:OnIntervalThink()
|
||||
if IsServer() then
|
||||
EmitSoundOn( "SandKing.Epicenter.PulsesBegin", self:GetCaster() )
|
||||
local enemies = FindUnitsInRadius( self:GetParent():GetTeamNumber(), self:GetParent():GetOrigin(), self:GetCaster(), FIND_UNITS_EVERYWHERE, 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 enemy ~= nil then
|
||||
local vDirection = ( enemy:GetOrigin() + RandomVector( 1 ) * self.pulse_width ) - self:GetCaster():GetOrigin()
|
||||
vDirection.z = 0.0
|
||||
vDirection = vDirection:Normalized()
|
||||
|
||||
local info =
|
||||
{
|
||||
Ability = self:GetAbility(),
|
||||
vSpawnOrigin = self:GetCaster():GetOrigin(),
|
||||
fStartRadius = self.pulse_width,
|
||||
fEndRadius = self.pulse_end_width,
|
||||
vVelocity = vDirection * self.pulse_speed,
|
||||
fDistance = self.pulse_distance,
|
||||
Source = self:GetCaster(),
|
||||
iUnitTargetTeam = DOTA_UNIT_TARGET_TEAM_ENEMY,
|
||||
iUnitTargetType = DOTA_UNIT_TARGET_HERO + DOTA_UNIT_TARGET_BASIC,
|
||||
}
|
||||
|
||||
local proj = {}
|
||||
proj.handle = ProjectileManager:CreateLinearProjectile( info )
|
||||
proj.nFXIndex = ParticleManager:CreateParticle( "particles/test_particle/sand_king_projectile.vpcf", PATTACH_CUSTOMORIGIN, nil )
|
||||
ParticleManager:SetParticleControl( proj.nFXIndex, 0, self:GetParent():GetOrigin() )
|
||||
ParticleManager:SetParticleControl( proj.nFXIndex, 1, vDirection * self.pulse_speed )
|
||||
ParticleManager:SetParticleControl( proj.nFXIndex, 2, Vector( self.pulse_width, self.pulse_width, 0 ) )
|
||||
ParticleManager:SetParticleControl( proj.nFXIndex, 4, Vector( self.pulse_distance / self.pulse_speed + 1, 0, 0 ) )
|
||||
|
||||
table.insert( self:GetAbility().Projectiles, proj )
|
||||
EmitSoundOn( "SandKing.Epicenter.Pulse", self:GetParent() )
|
||||
end
|
||||
end
|
||||
|
||||
for i=1,self.random_pulses do
|
||||
local vDirection = ( self:GetCaster():GetOrigin() + ( RandomVector( 1 ) * self.pulse_distance ) ) - self:GetCaster():GetOrigin()
|
||||
vDirection.z = 0.0
|
||||
vDirection = vDirection:Normalized()
|
||||
|
||||
local info =
|
||||
{
|
||||
Ability = self:GetAbility(),
|
||||
vSpawnOrigin = self:GetCaster():GetOrigin(),
|
||||
fStartRadius = self.pulse_width,
|
||||
fEndRadius = self.pulse_end_width,
|
||||
vVelocity = vDirection * self.pulse_speed,
|
||||
fDistance = self.pulse_distance,
|
||||
Source = self:GetCaster(),
|
||||
iUnitTargetTeam = DOTA_UNIT_TARGET_TEAM_ENEMY,
|
||||
iUnitTargetType = DOTA_UNIT_TARGET_HERO + DOTA_UNIT_TARGET_BASIC,
|
||||
}
|
||||
|
||||
local proj = {}
|
||||
proj.handle = ProjectileManager:CreateLinearProjectile( info )
|
||||
proj.nFXIndex = ParticleManager:CreateParticle( "particles/test_particle/sand_king_projectile.vpcf", PATTACH_CUSTOMORIGIN, nil )
|
||||
ParticleManager:SetParticleControl( proj.nFXIndex, 0, self:GetParent():GetOrigin() )
|
||||
ParticleManager:SetParticleControl( proj.nFXIndex, 1, vDirection * self.pulse_speed )
|
||||
ParticleManager:SetParticleControl( proj.nFXIndex, 2, Vector( self.pulse_width, self.pulse_width, 0 ) )
|
||||
ParticleManager:SetParticleControl( proj.nFXIndex, 4, Vector( self.pulse_distance / self.pulse_speed + 1, 0, 0 ) )
|
||||
|
||||
table.insert( self:GetAbility().Projectiles, proj )
|
||||
EmitSoundOn( "SandKing.Epicenter.Pulse", self:GetParent() )
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -0,0 +1,154 @@
|
||||
modifier_sand_king_boss_passive = class({})
|
||||
|
||||
-----------------------------------------------------------------------------------------
|
||||
|
||||
function modifier_sand_king_boss_passive:IsHidden()
|
||||
return true
|
||||
end
|
||||
|
||||
-----------------------------------------------------------------------------------------
|
||||
|
||||
function modifier_sand_king_boss_passive:IsPurgable()
|
||||
return false
|
||||
end
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
function modifier_sand_king_boss_passive:GetPriority()
|
||||
return MODIFIER_PRIORITY_ULTRA
|
||||
end
|
||||
|
||||
-----------------------------------------------------------------------------------------
|
||||
|
||||
function modifier_sand_king_boss_passive:OnCreated( kv )
|
||||
if IsServer() then
|
||||
self:GetCaster().bInSandStorm = false
|
||||
end
|
||||
end
|
||||
|
||||
-----------------------------------------------------------------------------------------
|
||||
|
||||
function modifier_sand_king_boss_passive:CheckState()
|
||||
local state =
|
||||
{
|
||||
[MODIFIER_STATE_HEXED] = false,
|
||||
[MODIFIER_STATE_ROOTED] = false,
|
||||
[MODIFIER_STATE_SILENCED] = false,
|
||||
[MODIFIER_STATE_STUNNED] = false,
|
||||
[MODIFIER_STATE_NO_HEALTH_BAR] = true,
|
||||
[MODIFIER_STATE_FLYING_FOR_PATHING_PURPOSES_ONLY] = true,
|
||||
}
|
||||
|
||||
if IsServer() then
|
||||
state[MODIFIER_STATE_CANNOT_MISS] = self.bCannotMiss
|
||||
state[MODIFIER_STATE_INVISIBLE] = false
|
||||
state[MODIFIER_STATE_UNSELECTABLE] = self:GetCaster().bInSandStorm
|
||||
end
|
||||
return state
|
||||
end
|
||||
|
||||
-----------------------------------------------------------------------------------------
|
||||
|
||||
function modifier_sand_king_boss_passive:DeclareFunctions()
|
||||
local funcs =
|
||||
{
|
||||
MODIFIER_PROPERTY_ATTACKSPEED_REDUCTION_PERCENTAGE,
|
||||
MODIFIER_PROPERTY_MOVESPEED_REDUCTION_PERCENTAGE,
|
||||
MODIFIER_PROPERTY_ATTACK_RANGE_BONUS,
|
||||
MODIFIER_EVENT_ON_ATTACK_START,
|
||||
MODIFIER_EVENT_ON_ATTACK_LANDED,
|
||||
MODIFIER_PROPERTY_EVASION_CONSTANT,
|
||||
MODIFIER_EVENT_ON_TAKEDAMAGE,
|
||||
}
|
||||
return funcs
|
||||
end
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
function modifier_sand_king_boss_passive:GetModifierAttackSpeedReductionPercentage( params )
|
||||
return 0
|
||||
end
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
function modifier_sand_king_boss_passive:GetModifierMoveSpeedReductionPercentage( params )
|
||||
return 20
|
||||
end
|
||||
|
||||
-----------------------------------------------------------------------------------------
|
||||
|
||||
function modifier_sand_king_boss_passive:GetModifierAttackRangeBonus( params )
|
||||
if IsServer() then
|
||||
if self.bInAttack == true then
|
||||
return 200
|
||||
else
|
||||
return 0
|
||||
end
|
||||
end
|
||||
return 0
|
||||
end
|
||||
|
||||
-----------------------------------------------------------------------------------------
|
||||
|
||||
function modifier_sand_king_boss_passive:OnAttackStart( params )
|
||||
if IsServer() then
|
||||
if self:GetParent() == params.attacker then
|
||||
self.bInAttack = true
|
||||
if RollPercentage( self:GetAbility():GetSpecialValueFor( "accuracy_pct" ) ) then
|
||||
self.bCannotMiss = true
|
||||
else
|
||||
self.bCannotMiss = false
|
||||
end
|
||||
end
|
||||
end
|
||||
return 0
|
||||
end
|
||||
|
||||
-----------------------------------------------------------------------------------------
|
||||
|
||||
function modifier_sand_king_boss_passive:OnAttackLanded( params )
|
||||
if IsServer() then
|
||||
if self:GetParent() == params.attacker then
|
||||
self.bInAttack = false
|
||||
|
||||
local Target = params.target
|
||||
if Target ~= nil then
|
||||
local caustic_duration = self:GetAbility():GetSpecialValueFor( "caustic_duration" )
|
||||
local hCausticBuff = Target:FindModifierByName( "modifier_sand_king_boss_caustic_finale" )
|
||||
if hCausticBuff == nil then
|
||||
hCausticBuff = Target:AddNewModifier( self:GetParent(), self:GetAbility(), "modifier_sand_king_boss_caustic_finale", { duration = caustic_duration } )
|
||||
if hCausticBuff ~= nil then
|
||||
hCausticBuff:SetStackCount( 0 )
|
||||
end
|
||||
end
|
||||
if hCausticBuff ~= nil then
|
||||
hCausticBuff:SetStackCount( hCausticBuff:GetStackCount() + 1 )
|
||||
hCausticBuff:SetDuration( caustic_duration, true )
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
return 0
|
||||
end
|
||||
|
||||
-----------------------------------------------------------------------------------------
|
||||
|
||||
function modifier_sand_king_boss_passive:GetModifierEvasion_Constant( params )
|
||||
return 33
|
||||
end
|
||||
|
||||
-----------------------------------------------------------------------------------------
|
||||
|
||||
function modifier_sand_king_boss_passive:OnTakeDamage( params )
|
||||
if IsServer() then
|
||||
local hAttacker = params.attacker
|
||||
local hVictim = params.unit
|
||||
if hAttacker ~= nil and hVictim ~= nil and hVictim == self:GetParent() then
|
||||
if hVictim:FindModifierByName( "modifier_provide_vision" ) == nil then
|
||||
--printf( "Provide Vision" )
|
||||
hVictim:AddNewModifier( hAttacker, self:GetAbility(), "modifier_provide_vision", { duration = -1 } )
|
||||
end
|
||||
end
|
||||
end
|
||||
return 0
|
||||
end
|
||||
@@ -0,0 +1,130 @@
|
||||
modifier_sand_king_boss_sandstorm = class({})
|
||||
|
||||
-----------------------------------------------------------------------------------------
|
||||
|
||||
function modifier_sand_king_boss_sandstorm:IsHidden()
|
||||
return true
|
||||
end
|
||||
|
||||
-----------------------------------------------------------------------------------------
|
||||
|
||||
function modifier_sand_king_boss_sandstorm:IsPurgable()
|
||||
return false
|
||||
end
|
||||
|
||||
-----------------------------------------------------------------------------------------
|
||||
|
||||
function modifier_sand_king_boss_sandstorm:IsAura()
|
||||
return true
|
||||
end
|
||||
|
||||
-----------------------------------------------------------------------------------------
|
||||
|
||||
function modifier_sand_king_boss_sandstorm:GetModifierAura()
|
||||
return "modifier_sand_king_boss_sandstorm_effect"
|
||||
end
|
||||
|
||||
-----------------------------------------------------------------------------------------
|
||||
|
||||
function modifier_sand_king_boss_sandstorm:GetAuraRadius()
|
||||
return self.sand_storm_radius
|
||||
end
|
||||
|
||||
-----------------------------------------------------------------------------------------
|
||||
|
||||
function modifier_sand_king_boss_sandstorm:GetAuraSearchTeam()
|
||||
return DOTA_UNIT_TARGET_TEAM_ENEMY
|
||||
end
|
||||
|
||||
-----------------------------------------------------------------------------------------
|
||||
|
||||
function modifier_sand_king_boss_sandstorm:GetAuraSearchType()
|
||||
return DOTA_UNIT_TARGET_HERO
|
||||
end
|
||||
|
||||
-----------------------------------------------------------------------------------------
|
||||
|
||||
function modifier_sand_king_boss_sandstorm:OnCreated( kv )
|
||||
if IsServer() then
|
||||
if self:ApplyHorizontalMotionController() == false then
|
||||
self:Destroy()
|
||||
return
|
||||
end
|
||||
|
||||
self.nProjHandle = self:GetParent().nProjHandle
|
||||
self.sand_storm_radius = self:GetAbility():GetSpecialValueFor( "sand_storm_radius" )
|
||||
self.damage = self:GetAbility():GetSpecialValueFor( "damage" )
|
||||
self.storm_move_speed = self:GetAbility():GetSpecialValueFor( "storm_move_speed" )
|
||||
self.storm_decreased_turn_rate = self:GetAbility():GetSpecialValueFor( "storm_decreased_turn_rate" )
|
||||
|
||||
EmitSoundOn( "SandKingBoss.SandStorm.loop", self:GetParent() )
|
||||
end
|
||||
end
|
||||
|
||||
-----------------------------------------------------------------------------------------
|
||||
|
||||
function modifier_sand_king_boss_sandstorm:OnDestroy()
|
||||
if IsServer() then
|
||||
self:GetParent():RemoveHorizontalMotionController( self )
|
||||
StopSoundOn( "SandKingBoss.SandStorm.loop", self:GetParent() )
|
||||
if self.nProjHandle ~= nil then
|
||||
ProjectileManager:DestroyLinearProjectile( self.nProjHandle )
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
-----------------------------------------------------------------------------------------
|
||||
|
||||
function modifier_sand_king_boss_sandstorm:CheckState()
|
||||
local state =
|
||||
{
|
||||
[MODIFIER_STATE_NO_HEALTH_BAR] = true,
|
||||
[MODIFIER_STATE_FLYING_FOR_PATHING_PURPOSES_ONLY] = true,
|
||||
[MODIFIER_STATE_INVULNERABLE] = true,
|
||||
}
|
||||
return state
|
||||
end
|
||||
|
||||
-----------------------------------------------------------------------------------------
|
||||
|
||||
function modifier_sand_king_boss_sandstorm:DeclareFunctions()
|
||||
local funcs =
|
||||
{
|
||||
--MODIFIER_PROPERTY_MOVESPEED_ABSOLUTE,
|
||||
MODIFIER_PROPERTY_TURN_RATE_PERCENTAGE,
|
||||
}
|
||||
return funcs
|
||||
end
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
function modifier_sand_king_boss_sandstorm:GetModifierTurnRate_Percentage( params )
|
||||
return -self.storm_decreased_turn_rate
|
||||
end
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
function modifier_sand_king_boss_sandstorm:UpdateHorizontalMotion( me, dt )
|
||||
if IsServer() then
|
||||
if self.nProjHandle == nil then
|
||||
local vForward = self:GetParent():GetForwardVector()
|
||||
local vNewPos = self:GetParent():GetOrigin() + vForward * dt * self:GetParent().storm_speed
|
||||
me:SetOrigin( vNewPos )
|
||||
else
|
||||
local vNewPos = ProjectileManager:GetLinearProjectileLocation( self.nProjHandle )
|
||||
me:SetOrigin( vNewPos )
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
function modifier_sand_king_boss_sandstorm:OnHorizontalMotionInterrupted()
|
||||
if IsServer() then
|
||||
self:Destroy()
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,12 @@
|
||||
modifier_sand_king_boss_sandstorm_blind = class({})
|
||||
|
||||
-----------------------------------------------------------------------------------------
|
||||
|
||||
function modifier_sand_king_boss_sandstorm_blind:CheckState()
|
||||
local state =
|
||||
{
|
||||
[MODIFIER_STATE_BLIND] = true,
|
||||
}
|
||||
return state
|
||||
end
|
||||
|
||||
@@ -0,0 +1,65 @@
|
||||
modifier_sand_king_boss_sandstorm_effect = class({})
|
||||
|
||||
-----------------------------------------------------------------------------------------
|
||||
|
||||
function modifier_sand_king_boss_sandstorm_effect:OnCreated( kv )
|
||||
self.movespeed_pct = self:GetAbility():GetSpecialValueFor( "movespeed_pct" )
|
||||
self.damage = self:GetAbility():GetSpecialValueFor( "damage" )
|
||||
self.blind_duration = self:GetAbility():GetSpecialValueFor( "blind_duration" )
|
||||
if IsServer() then
|
||||
self:StartIntervalThink( 0.5 )
|
||||
end
|
||||
end
|
||||
|
||||
-----------------------------------------------------------------------------------------
|
||||
|
||||
function modifier_sand_king_boss_sandstorm_effect:DeclareFunctions()
|
||||
local funcs =
|
||||
{
|
||||
MODIFIER_PROPERTY_MOVESPEED_BONUS_PERCENTAGE,
|
||||
}
|
||||
return funcs
|
||||
end
|
||||
|
||||
-----------------------------------------------------------------------------------------
|
||||
|
||||
function modifier_sand_king_boss_sandstorm_effect:CheckState()
|
||||
local state =
|
||||
{
|
||||
}
|
||||
return state
|
||||
end
|
||||
|
||||
-----------------------------------------------------------------------------------------
|
||||
|
||||
function modifier_sand_king_boss_sandstorm_effect:GetModifierMoveSpeedBonus_Percentage( params )
|
||||
return -self.movespeed_pct
|
||||
end
|
||||
|
||||
-----------------------------------------------------------------------------------------
|
||||
|
||||
function modifier_sand_king_boss_sandstorm_effect:OnIntervalThink()
|
||||
if IsServer() then
|
||||
if self:GetParent() and self:GetParent():IsInvulnerable() == false then
|
||||
|
||||
local damageInfo =
|
||||
{
|
||||
victim = self:GetParent(),
|
||||
attacker = self:GetCaster(),
|
||||
damage = self.damage / 2,
|
||||
damage_type = DAMAGE_TYPE_MAGICAL,
|
||||
ability = self:GetAbility()
|
||||
}
|
||||
|
||||
ApplyDamage( damageInfo )
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
-----------------------------------------------------------------------------------------
|
||||
|
||||
function modifier_sand_king_boss_sandstorm_effect:OnDestroy()
|
||||
if IsServer() then
|
||||
--self:GetParent():AddNewModifier( self:GetCaster(), self:GetAbility(), "modifier_sand_king_boss_sandstorm_blind", { duration = self.blind_duration } )
|
||||
end
|
||||
end
|
||||
@@ -0,0 +1,158 @@
|
||||
modifier_sand_king_claw_attack = class ({})
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
function modifier_sand_king_claw_attack:IsHidden()
|
||||
return true
|
||||
end
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
function modifier_sand_king_claw_attack:IsPurgable()
|
||||
return false
|
||||
end
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
function modifier_sand_king_claw_attack:OnCreated( kv )
|
||||
if IsServer() then
|
||||
self.damage_radius = self:GetAbility():GetSpecialValueFor( "damage_radius" )
|
||||
self.damage = self:GetAbility():GetSpecialValueFor( "damage" )
|
||||
self.forward_movement = self:GetAbility():GetSpecialValueFor( "forward_movement" )
|
||||
self.hHitTargets = {}
|
||||
|
||||
self:StartIntervalThink( kv["initial_delay"] )
|
||||
end
|
||||
end
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
function modifier_sand_king_claw_attack:OnIntervalThink()
|
||||
if IsServer() then
|
||||
self:StartIntervalThink( 0.01 )
|
||||
local vForward = self:GetParent():GetForwardVector()
|
||||
self:GetParent():SetOrigin( self:GetParent():GetOrigin() + vForward * self.forward_movement )
|
||||
|
||||
local szSequenceName = self:GetParent():GetSequence()
|
||||
local attachAttack1 = nil
|
||||
local attachAttack2 = nil
|
||||
local vLocation1 = nil
|
||||
local vLocation2 = nil
|
||||
if szSequenceName == "sand_king_attack3_anim" or szSequenceName == "sand_king_attack_anim" then
|
||||
attachAttack1 = self:GetParent():ScriptLookupAttachment( "attach_attack1" )
|
||||
vLocation1 = self:GetParent():GetAttachmentOrigin( attachAttack1 )
|
||||
|
||||
end
|
||||
if szSequenceName == "sand_king_attack3_anim" or szSequenceName == "sand_king_attack2_anim" then
|
||||
attachAttack2 = self:GetParent():ScriptLookupAttachment( "attach_attack2" )
|
||||
vLocation2 = self:GetParent():GetAttachmentOrigin( attachAttack2 )
|
||||
end
|
||||
|
||||
if attachAttack1 ~= nil then
|
||||
--DebugDrawCircle( vLocation1, Vector( 0, 255, 0 ), 255, self.damage_radius, false, 1.0 )
|
||||
local enemies1 = FindUnitsInRadius( self:GetParent():GetTeamNumber(), vLocation1, self:GetCaster(), self.damage_radius, DOTA_UNIT_TARGET_TEAM_ENEMY, DOTA_UNIT_TARGET_HERO + DOTA_UNIT_TARGET_BASIC, DOTA_UNIT_TARGET_FLAG_MAGIC_IMMUNE_ENEMIES, 0, false )
|
||||
if #enemies1 > 0 then
|
||||
for _,enemy in pairs( enemies1 ) do
|
||||
if enemy ~= nil and enemy:IsInvulnerable() == false and self:HasHitTarget( enemy ) == false then
|
||||
self:AddHitTarget( enemy )
|
||||
local damageInfo =
|
||||
{
|
||||
victim = enemy,
|
||||
attacker = self:GetParent(),
|
||||
damage = self.damage,
|
||||
damage_type = DAMAGE_TYPE_PHYSICAL,
|
||||
ability = self,
|
||||
}
|
||||
|
||||
ApplyDamage( damageInfo )
|
||||
--enemy:AddNewModifier( self:GetParent(), self:GetAbility(), "modifier_bloodseeker_rupture", { duration = self:GetAbility():GetSpecialValueFor( "duration" ) } )
|
||||
EmitSoundOn( "DOTA_Item.Maim", enemy )
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
if attachAttack2 ~= nil then
|
||||
--DebugDrawCircle( vLocation2, Vector( 0, 0, 255 ), 255, self.damage_radius, false, 1.0 )
|
||||
local enemies2 = FindUnitsInRadius( self:GetParent():GetTeamNumber(), vLocation2, self:GetCaster(), self.damage_radius, DOTA_UNIT_TARGET_TEAM_ENEMY, DOTA_UNIT_TARGET_HERO + DOTA_UNIT_TARGET_BASIC, DOTA_UNIT_TARGET_FLAG_MAGIC_IMMUNE_ENEMIES, 0, false )
|
||||
if #enemies2 > 0 then
|
||||
for _,enemy in pairs( enemies2 ) do
|
||||
if enemy ~= nil and enemy:IsInvulnerable() == false and self:HasHitTarget( enemy ) == false then
|
||||
self:AddHitTarget( enemy )
|
||||
local damageInfo =
|
||||
{
|
||||
victim = enemy,
|
||||
attacker = self:GetParent(),
|
||||
damage = self.damage,
|
||||
damage_type = DAMAGE_TYPE_PHYSICAL,
|
||||
ability = self,
|
||||
}
|
||||
|
||||
ApplyDamage( damageInfo )
|
||||
--enemy:AddNewModifier( self:GetParent(), self:GetAbility(), "modifier_bloodseeker_rupture", { duration = self:GetAbility():GetSpecialValueFor( "duration" ) } )
|
||||
EmitSoundOn( "DOTA_Item.Maim", enemy )
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
--DebugDrawCircle( self:GetParent():GetOrigin(), Vector( 0, 0, 255 ), 255, self.damage_radius, false, 1.0 )
|
||||
local enemies3 = FindUnitsInRadius( self:GetParent():GetTeamNumber(), self:GetParent():GetOrigin(), self:GetCaster(), self.damage_radius, DOTA_UNIT_TARGET_TEAM_ENEMY, DOTA_UNIT_TARGET_HERO + DOTA_UNIT_TARGET_BASIC, DOTA_UNIT_TARGET_FLAG_MAGIC_IMMUNE_ENEMIES, 0, false )
|
||||
if #enemies3 > 0 then
|
||||
for _,enemy in pairs( enemies3 ) do
|
||||
if enemy ~= nil and enemy:IsInvulnerable() == false and self:HasHitTarget( enemy ) == false then
|
||||
self:AddHitTarget( enemy )
|
||||
local damageInfo =
|
||||
{
|
||||
victim = enemy,
|
||||
attacker = self:GetParent(),
|
||||
damage = self.damage,
|
||||
damage_type = DAMAGE_TYPE_PHYSICAL,
|
||||
ability = self,
|
||||
}
|
||||
|
||||
ApplyDamage( damageInfo )
|
||||
--enemy:AddNewModifier( self:GetParent(), self:GetAbility(), "modifier_bloodseeker_rupture", { duration = self:GetAbility():GetSpecialValueFor( "duration" ) } )
|
||||
EmitSoundOn( "DOTA_Item.Maim", enemy )
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
FindClearSpaceForUnit( self:GetParent(), self:GetParent():GetOrigin(), false )
|
||||
end
|
||||
end
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
function modifier_sand_king_claw_attack:DeclareFunctions()
|
||||
local funcs =
|
||||
{
|
||||
MODIFIER_PROPERTY_DISABLE_TURNING,
|
||||
}
|
||||
return funcs
|
||||
end
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
function modifier_sand_king_claw_attack:GetModifierDisableTurning( params )
|
||||
return 1
|
||||
end
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
function modifier_sand_king_claw_attack:HasHitTarget( hTarget )
|
||||
for _, target in pairs( self.hHitTargets ) do
|
||||
if target == hTarget then
|
||||
return true
|
||||
end
|
||||
end
|
||||
|
||||
return false
|
||||
end
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
function modifier_sand_king_claw_attack:AddHitTarget( hTarget )
|
||||
table.insert( self.hHitTargets, hTarget )
|
||||
end
|
||||
|
||||
@@ -0,0 +1,178 @@
|
||||
modifier_sand_king_tail_swipe = class ({})
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
function modifier_sand_king_tail_swipe:IsHidden()
|
||||
return true
|
||||
end
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
function modifier_sand_king_tail_swipe:IsPurgable()
|
||||
return false
|
||||
end
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
function modifier_sand_king_tail_swipe:OnCreated( kv )
|
||||
if IsServer() then
|
||||
self.nPreviewFX = ParticleManager:CreateParticle( "particles/units/heroes/hero_sandking/sandking_epicenter_tell.vpcf", PATTACH_CUSTOMORIGIN, self:GetCaster() )
|
||||
ParticleManager:SetParticleControlEnt( self.nPreviewFX, 0, self:GetCaster(), PATTACH_POINT_FOLLOW, "attach_tail", self:GetCaster():GetOrigin(), true )
|
||||
|
||||
self.damage_radius = self:GetAbility():GetSpecialValueFor( "damage_radius" )
|
||||
self.damage = self:GetAbility():GetSpecialValueFor( "damage" )
|
||||
self.stun_duration = self:GetAbility():GetSpecialValueFor( "stun_duration" )
|
||||
self.knockback_distance = self:GetAbility():GetSpecialValueFor( "knockback_distance" )
|
||||
self.knockback_height = self:GetAbility():GetSpecialValueFor( "knockback_height" )
|
||||
self.damage = self:GetAbility():GetSpecialValueFor( "damage" )
|
||||
self.slow_duration = self:GetAbility():GetSpecialValueFor( "slow_duration" )
|
||||
|
||||
|
||||
self.hHitTargets = {}
|
||||
|
||||
self:StartIntervalThink( kv["initial_delay"] )
|
||||
end
|
||||
end
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
function modifier_sand_king_tail_swipe:OnIntervalThink()
|
||||
if IsServer() then
|
||||
local tail1 = self:GetParent():ScriptLookupAttachment( "attach_tail" )
|
||||
local tail2 = self:GetParent():ScriptLookupAttachment( "attach_tail2" )
|
||||
local tail3 = self:GetParent():ScriptLookupAttachment( "attach_tail3" )
|
||||
local tail4 = self:GetParent():ScriptLookupAttachment( "attach_tail4" )
|
||||
local vLocation1 = self:GetParent():GetAttachmentOrigin( tail1 )
|
||||
local vLocation2 = self:GetParent():GetAttachmentOrigin( tail2 )
|
||||
local vLocation3 = self:GetParent():GetAttachmentOrigin( tail3 )
|
||||
local vLocation4 = self:GetParent():GetAttachmentOrigin( tail4 )
|
||||
local Locations = {}
|
||||
table.insert( Locations, vLocation1 )
|
||||
table.insert( Locations, vLocation2 )
|
||||
table.insert( Locations, vLocation3 )
|
||||
table.insert( Locations, vLocation4 )
|
||||
|
||||
if self:GetParent():FindModifierByName( "modifier_sand_king_boss_burrow" ) ~= nil then
|
||||
for _,vPos in pairs ( Locations ) do
|
||||
local nFXIndex = ParticleManager:CreateParticle( "particles/creatures/ogre/ogre_melee_smash.vpcf", PATTACH_WORLDORIGIN, self:GetCaster() )
|
||||
ParticleManager:SetParticleControl( nFXIndex, 0, vPos )
|
||||
ParticleManager:SetParticleControl( nFXIndex, 1, Vector( self.damage_radius, self.damage_radius, self.damage_radius ) )
|
||||
ParticleManager:ReleaseParticleIndex( nFXIndex )
|
||||
|
||||
local enemies = FindUnitsInRadius( self:GetParent():GetTeamNumber(), vPos, self:GetParent(), self.damage_radius, DOTA_UNIT_TARGET_TEAM_ENEMY, DOTA_UNIT_TARGET_HERO + DOTA_UNIT_TARGET_BASIC, DOTA_UNIT_TARGET_FLAG_MAGIC_IMMUNE_ENEMIES, 0, false )
|
||||
for _,enemy in pairs( enemies ) do
|
||||
if enemy ~= nil and enemy:IsInvulnerable() == false and self:HasHitTarget( enemy ) == false then
|
||||
self:AddHitTarget( enemy )
|
||||
|
||||
local passive = self:GetCaster():FindAbilityByName( "sand_king_boss_passive" )
|
||||
local caustic_duration = passive:GetSpecialValueFor( "caustic_duration" )
|
||||
local hCausticBuff = enemy:FindModifierByName( "modifier_sand_king_boss_caustic_finale" )
|
||||
if hCausticBuff == nil then
|
||||
hCausticBuff = enemy:AddNewModifier( self:GetCaster(), passive, "modifier_sand_king_boss_caustic_finale", { duration = caustic_duration } )
|
||||
hCausticBuff:SetStackCount( 0 )
|
||||
end
|
||||
hCausticBuff:SetStackCount( hCausticBuff:GetStackCount() + 1 )
|
||||
hCausticBuff:SetDuration( caustic_duration, true )
|
||||
|
||||
local damageInfo =
|
||||
{
|
||||
victim = enemy,
|
||||
attacker = self:GetCaster(),
|
||||
damage = self.damage,
|
||||
damage_type = DAMAGE_TYPE_PHYSICAL,
|
||||
ability = self,
|
||||
}
|
||||
|
||||
ApplyDamage( damageInfo )
|
||||
enemy:AddNewModifier( self:GetCaster(), self:GetAbility(), "modifier_stunned", { duration = self.stun_duration } )
|
||||
enemy:AddNewModifier( self:GetCaster(), self:GetAbility(), "modifier_polar_furbolg_ursa_warrior_thunder_clap", { duration = self.slow_duration } )
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
EmitSoundOnLocationWithCaster( vLocation4, "OgreTank.GroundSmash", self:GetCaster() )
|
||||
self:StartIntervalThink( -1 )
|
||||
else
|
||||
self:StartIntervalThink( 0.01 )
|
||||
for _,vPos in pairs( Locations ) do
|
||||
--DebugDrawCircle( vPos, Vector( 0, 255, 0 ), 255, self.damage_radius, false, 1.0 )
|
||||
local enemies = FindUnitsInRadius( self:GetParent():GetTeamNumber(), vPos, self:GetParent(), self.damage_radius, DOTA_UNIT_TARGET_TEAM_ENEMY, DOTA_UNIT_TARGET_HERO + DOTA_UNIT_TARGET_BASIC, DOTA_UNIT_TARGET_FLAG_MAGIC_IMMUNE_ENEMIES, 0, false )
|
||||
for _,enemy in pairs( enemies ) do
|
||||
if enemy ~= nil and enemy:IsInvulnerable() == false and self:HasHitTarget( enemy ) == false then
|
||||
self:AddHitTarget( enemy )
|
||||
|
||||
local passive = self:GetCaster():FindAbilityByName( "sand_king_boss_passive" )
|
||||
local caustic_duration = passive:GetSpecialValueFor( "caustic_duration" )
|
||||
local hCausticBuff = enemy:FindModifierByName( "modifier_sand_king_boss_caustic_finale" )
|
||||
if hCausticBuff == nil then
|
||||
hCausticBuff = enemy:AddNewModifier( self:GetCaster(), passive, "modifier_sand_king_boss_caustic_finale", { duration = caustic_duration } )
|
||||
hCausticBuff:SetStackCount( 0 )
|
||||
end
|
||||
hCausticBuff:SetStackCount( hCausticBuff:GetStackCount() + 1 )
|
||||
hCausticBuff:SetDuration( caustic_duration, true )
|
||||
|
||||
local damageInfo =
|
||||
{
|
||||
victim = enemy,
|
||||
attacker = self:GetParent(),
|
||||
damage = self.damage,
|
||||
damage_type = DAMAGE_TYPE_PHYSICAL,
|
||||
ability = self,
|
||||
}
|
||||
|
||||
ApplyDamage( damageInfo )
|
||||
local kv =
|
||||
{
|
||||
center_x = self:GetParent():GetOrigin().x,
|
||||
center_y = self:GetParent():GetOrigin().y,
|
||||
center_z = self:GetParent():GetOrigin().z,
|
||||
should_stun = true,
|
||||
duration = self.stun_duration,
|
||||
knockback_duration = self.stun_duration,
|
||||
knockback_distance = self.knockback_distance,
|
||||
knockback_height = self.knockback_height,
|
||||
}
|
||||
enemy:AddNewModifier( self:GetCaster(), self:GetAbility(), "modifier_knockback", kv )
|
||||
enemy:AddNewModifier( self:GetCaster(), self:GetAbility(), "modifier_polar_furbolg_ursa_warrior_thunder_clap", { duration = self.slow_duration } )
|
||||
EmitSoundOn( "DOTA_Item.Maim", enemy )
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
function modifier_sand_king_tail_swipe:DeclareFunctions()
|
||||
local funcs =
|
||||
{
|
||||
MODIFIER_PROPERTY_DISABLE_TURNING,
|
||||
}
|
||||
return funcs
|
||||
end
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
function modifier_sand_king_tail_swipe:GetModifierDisableTurning( params )
|
||||
return 1
|
||||
end
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
function modifier_sand_king_tail_swipe:HasHitTarget( hTarget )
|
||||
for _, target in pairs( self.hHitTargets ) do
|
||||
if target == hTarget then
|
||||
return true
|
||||
end
|
||||
end
|
||||
|
||||
return false
|
||||
end
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
function modifier_sand_king_tail_swipe:AddHitTarget( hTarget )
|
||||
table.insert( self.hHitTargets, hTarget )
|
||||
end
|
||||
|
||||
@@ -0,0 +1,97 @@
|
||||
|
||||
modifier_scarab_priest_summon_mound = class({})
|
||||
|
||||
--------------------------------------------------------------
|
||||
|
||||
function modifier_scarab_priest_summon_mound:IsHidden()
|
||||
return true
|
||||
end
|
||||
|
||||
--------------------------------------------------------------
|
||||
|
||||
function modifier_scarab_priest_summon_mound:IsPurgable()
|
||||
return false
|
||||
end
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
function modifier_scarab_priest_summon_mound:OnCreated( kv )
|
||||
if IsServer() then
|
||||
self.szSummonedUnitName = kv.summoned_unit
|
||||
|
||||
local nSmokeFX = ParticleManager:CreateParticle( "particles/units/heroes/hero_nyx_assassin/nyx_assassin_burrow_exit.vpcf", PATTACH_CUSTOMORIGIN, nil )
|
||||
ParticleManager:SetParticleControl( nSmokeFX, 0, self:GetParent():GetAbsOrigin() )
|
||||
ParticleManager:ReleaseParticleIndex( nSmokeFX )
|
||||
|
||||
self:StartIntervalThink( self:GetDuration() - 0.5 )
|
||||
end
|
||||
end
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
function modifier_scarab_priest_summon_mound:DeclareFunctions()
|
||||
local funcs =
|
||||
{
|
||||
MODIFIER_EVENT_ON_DEATH,
|
||||
}
|
||||
|
||||
return funcs
|
||||
end
|
||||
|
||||
-----------------------------------------------------------------------------------------
|
||||
|
||||
function modifier_scarab_priest_summon_mound:OnIntervalThink()
|
||||
|
||||
local nUnburrowFX = ParticleManager:CreateParticle( "particles/units/heroes/hero_nyx_assassin/nyx_assassin_burrow_exit.vpcf", PATTACH_CUSTOMORIGIN, nil )
|
||||
ParticleManager:SetParticleControl( nUnburrowFX, 0, self:GetParent():GetAbsOrigin() )
|
||||
ParticleManager:ReleaseParticleIndex( nUnburrowFX )
|
||||
|
||||
EmitSoundOn( "Creature.Burrow.Out", self:GetParent() )
|
||||
self:StartIntervalThink( -1 )
|
||||
|
||||
end
|
||||
|
||||
-------------------------------------------------------------------
|
||||
|
||||
function modifier_scarab_priest_summon_mound:OnDestroy()
|
||||
if not IsServer() then
|
||||
return
|
||||
end
|
||||
|
||||
if self:GetParent():IsAlive() then
|
||||
|
||||
self.bSpawned = true
|
||||
local hMinion = CreateUnitByName( self.szSummonedUnitName, self:GetParent():GetAbsOrigin(), true, self:GetCaster(), self:GetCaster(), self:GetCaster():GetTeamNumber() )
|
||||
if hMinion ~= nil then
|
||||
|
||||
local nFXIndex = ParticleManager:CreateParticle( "particles/units/heroes/hero_visage/visage_summon_familiars.vpcf", PATTACH_CUSTOMORIGIN, self:GetCaster() )
|
||||
ParticleManager:SetParticleControl( nFXIndex, 0, self:GetParent():GetAbsOrigin() )
|
||||
ParticleManager:ReleaseParticleIndex( nFXIndex )
|
||||
|
||||
end
|
||||
|
||||
self:GetParent():ForceKill( false )
|
||||
|
||||
end
|
||||
|
||||
UTIL_Remove( self:GetParent() )
|
||||
|
||||
end
|
||||
|
||||
-------------------------------------------------------------------
|
||||
|
||||
function modifier_scarab_priest_summon_mound:OnDeath( params )
|
||||
if not IsServer() or params.unit ~= self:GetParent() or self.bSpawned == true then
|
||||
return
|
||||
end
|
||||
|
||||
EmitSoundOn( "Burrower.HealExplosion", self:GetParent() )
|
||||
|
||||
local nFXIndex2 = ParticleManager:CreateParticle( "particles/nyx_swarm_explosion/nyx_swarm_explosion.vpcf", PATTACH_CUSTOMORIGIN, nil )
|
||||
ParticleManager:SetParticleControlEnt( nFXIndex2, 0, self:GetParent(), PATTACH_ABSORIGIN_FOLLOW, nil, self:GetParent():GetOrigin(), true )
|
||||
ParticleManager:SetParticleControlEnt( nFXIndex2, 1, self:GetParent(), PATTACH_ABSORIGIN_FOLLOW, nil, self:GetParent():GetOrigin(), true )
|
||||
ParticleManager:SetParticleControl( nFXIndex2, 2, Vector( 300, 300, 300 ) )
|
||||
ParticleManager:ReleaseParticleIndex( nFXIndex2 )
|
||||
|
||||
end
|
||||
|
||||
@@ -0,0 +1,81 @@
|
||||
|
||||
modifier_shroomling_enrage = class({})
|
||||
|
||||
-----------------------------------------------------------------------------------------
|
||||
|
||||
function modifier_shroomling_enrage:IsPurgable()
|
||||
return false
|
||||
end
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
function modifier_shroomling_enrage:OnCreated( kv )
|
||||
self.enrage_movespeed_bonus = 400
|
||||
self.enrage_attack_speed_bonus = 50
|
||||
self.enrage_model_scale_bonus = 40
|
||||
self.enrage_lifesteal_bonus_pct = 50
|
||||
|
||||
if IsServer() then
|
||||
EmitSoundOn( "DOTA_Item.MaskOfMadness.Activate", self:GetParent() )
|
||||
end
|
||||
end
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
function modifier_shroomling_enrage:GetEffectName()
|
||||
return "particles/items2_fx/mask_of_madness.vpcf"
|
||||
end
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
function modifier_shroomling_enrage:DeclareFunctions()
|
||||
local funcs =
|
||||
{
|
||||
MODIFIER_PROPERTY_MOVESPEED_BONUS_CONSTANT,
|
||||
MODIFIER_PROPERTY_ATTACKSPEED_BONUS_CONSTANT,
|
||||
MODIFIER_PROPERTY_MODEL_SCALE,
|
||||
MODIFIER_EVENT_ON_ATTACKED,
|
||||
}
|
||||
|
||||
return funcs
|
||||
end
|
||||
|
||||
-----------------------------------------------------------------------------------------
|
||||
|
||||
function modifier_shroomling_enrage:GetModifierMoveSpeedBonus_Constant( params )
|
||||
return self.enrage_movespeed_bonus
|
||||
end
|
||||
|
||||
-----------------------------------------------------------------------------------------
|
||||
|
||||
function modifier_shroomling_enrage:GetModifierAttackSpeedBonus_Constant( params )
|
||||
return self.enrage_attack_speed_bonus
|
||||
end
|
||||
|
||||
-----------------------------------------------------------------------------------------
|
||||
|
||||
function modifier_shroomling_enrage:GetModifierModelScale( params )
|
||||
return self.enrage_model_scale_bonus
|
||||
end
|
||||
|
||||
-----------------------------------------------------------------------------------------
|
||||
|
||||
function modifier_shroomling_enrage:OnAttacked( params )
|
||||
if IsServer() then
|
||||
|
||||
--print( 'modifier_shroomling_enrage:OnAttacked' )
|
||||
|
||||
if self:GetParent():PassivesDisabled() then
|
||||
return 1
|
||||
end
|
||||
|
||||
if params.attacker ~= nil and params.attacker == self:GetParent() and params.target ~= nil then
|
||||
local heal = ( params.damage * self.enrage_lifesteal_bonus_pct / 100 )
|
||||
--print( 'modifier_shroomling_enrage healing for ' .. heal )
|
||||
self:GetParent():Heal( heal, nil )
|
||||
ParticleManager:ReleaseParticleIndex( ParticleManager:CreateParticle( "particles/generic_gameplay/generic_lifesteal.vpcf", PATTACH_ABSORIGIN_FOLLOW, self:GetParent() ) )
|
||||
end
|
||||
end
|
||||
|
||||
return 1
|
||||
end
|
||||
@@ -0,0 +1,141 @@
|
||||
|
||||
modifier_shroomling_sleep = class({})
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
function modifier_shroomling_sleep:IsHidden()
|
||||
return false
|
||||
end
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
function modifier_shroomling_sleep:CanParentBeAutoAttacked()
|
||||
return false
|
||||
end
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
function modifier_shroomling_sleep:OnCreated( kv )
|
||||
if IsServer() then
|
||||
--print( 'modifier_shroomling_sleep:OnCreated()' )
|
||||
self.nWakeRange = 200
|
||||
self:StartIntervalThink( 1 )
|
||||
end
|
||||
end
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
function modifier_shroomling_sleep:CheckState()
|
||||
local state = {}
|
||||
if IsServer() then
|
||||
state[MODIFIER_STATE_ROOTED] = true
|
||||
state[MODIFIER_STATE_BLIND] = true
|
||||
state[MODIFIER_STATE_STUNNED] = true
|
||||
state[MODIFIER_STATE_SILENCED] = true
|
||||
end
|
||||
|
||||
return state
|
||||
end
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
function modifier_shroomling_sleep:DeclareFunctions()
|
||||
local funcs = {
|
||||
MODIFIER_EVENT_ON_ATTACKED,
|
||||
MODIFIER_EVENT_ON_TAKEDAMAGE,
|
||||
}
|
||||
return funcs
|
||||
end
|
||||
|
||||
-----------------------------------------------------------------------
|
||||
|
||||
function modifier_shroomling_sleep:GetEffectName()
|
||||
return "particles/generic_gameplay/generic_sleep.vpcf"
|
||||
end
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
function modifier_shroomling_sleep:GetEffectAttachType()
|
||||
return PATTACH_OVERHEAD_FOLLOW
|
||||
end
|
||||
|
||||
-----------------------------------------------------------------------------
|
||||
|
||||
function modifier_shroomling_sleep:OnDurationExpired( params )
|
||||
--print( 'modifier_shroomling_sleep:OnDurationExpired' )
|
||||
if IsServer() then
|
||||
self:GetParent():AddNewModifier( self:GetParent(), nil, "modifier_shroomling_weakened", { duration = -1.0 } )
|
||||
end
|
||||
|
||||
return 0
|
||||
end
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
--[[
|
||||
function modifier_shroomling_sleep:OnDestroy()
|
||||
if IsServer() then
|
||||
end
|
||||
end
|
||||
--]]
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
function modifier_shroomling_sleep:OnAttacked( params )
|
||||
if IsServer() then
|
||||
if params.target == self:GetParent() then
|
||||
self:Destroy()
|
||||
self:GetParent():AddNewModifier( self:GetParent(), nil, "modifier_shroomling_enrage", { duration = -1.0 } )
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
function modifier_shroomling_sleep:OnTakeDamage( params )
|
||||
if IsServer() then
|
||||
if params.unit == self:GetParent() then
|
||||
self:Destroy()
|
||||
self:GetParent():AddNewModifier( self:GetParent(), nil, "modifier_shroomling_enrage", { duration = -1.0 } )
|
||||
end
|
||||
end
|
||||
|
||||
return 0
|
||||
end
|
||||
|
||||
-----------------------------------------------------------------------------
|
||||
|
||||
function modifier_shroomling_sleep:OnIntervalThink()
|
||||
if IsServer() then
|
||||
-- don't wake up while we are still invulnerable
|
||||
local hInvulnBuff = self:GetParent():FindModifierByName( "modifier_invulnerable" )
|
||||
if hInvulnBuff ~= nil then
|
||||
--print( 'modifier_shroomling_sleep:OnIntervalThink() - shroom is currently invulnerable - skipping wakeup check!' )
|
||||
return
|
||||
end
|
||||
|
||||
local hEnemies = FindUnitsInRadius( self:GetParent():GetTeamNumber(), self:GetParent():GetOrigin(), nil, self.nWakeRange, DOTA_UNIT_TARGET_TEAM_ENEMY, DOTA_UNIT_TARGET_HERO + DOTA_UNIT_TARGET_CREEP, DOTA_UNIT_TARGET_FLAG_MAGIC_IMMUNE_ENEMIES, FIND_CLOSEST, false )
|
||||
--print( 'modifier_shroomling_sleep:OnIntervalThink() found enemies = ' .. #hEnemies )
|
||||
if #hEnemies > 0 then
|
||||
self:Destroy()
|
||||
self:GetParent():AddNewModifier( self:GetParent(), nil, "modifier_shroomling_enrage", { duration = -1.0 } )
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
--[[
|
||||
function modifier_shroomling_sleep:OnDestroy()
|
||||
if not IsServer() then
|
||||
return
|
||||
end
|
||||
|
||||
local hAllies = FindUnitsInRadius( self:GetParent():GetTeamNumber(), self:GetParent():GetOrigin(), nil, FIND_UNITS_EVERYWHERE, DOTA_UNIT_TARGET_TEAM_FRIENDLY, DOTA_UNIT_TARGET_ALL, DOTA_UNIT_TARGET_FLAG_MAGIC_IMMUNE_ENEMIES, FIND_CLOSEST, false )
|
||||
for _, hAlly in pairs( hAllies ) do
|
||||
if hAlly:HasModifier( "modifier_shroomling_sleep" ) then
|
||||
hAlly:RemoveModifierByName( "modifier_shroomling_sleep" )
|
||||
end
|
||||
end
|
||||
end
|
||||
--]]
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
@@ -0,0 +1,44 @@
|
||||
|
||||
modifier_shroomling_weakened = class({})
|
||||
|
||||
-----------------------------------------------------------------------------------------
|
||||
|
||||
function modifier_shroomling_weakened:IsPurgable()
|
||||
return false
|
||||
end
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
function modifier_shroomling_weakened:OnCreated( kv )
|
||||
self.enrage_model_scale_bonus = -20
|
||||
end
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
function modifier_shroomling_weakened:DeclareFunctions()
|
||||
local funcs =
|
||||
{
|
||||
MODIFIER_PROPERTY_MODEL_SCALE,
|
||||
MODIFIER_PROPERTY_EXTRA_HEALTH_PERCENTAGE,
|
||||
}
|
||||
|
||||
return funcs
|
||||
end
|
||||
|
||||
-----------------------------------------------------------------------------------------
|
||||
|
||||
function modifier_shroomling_weakened:GetModifierModelScale( params )
|
||||
return self.enrage_model_scale_bonus
|
||||
end
|
||||
|
||||
-----------------------------------------------------------------------------------------
|
||||
|
||||
function modifier_shroomling_weakened:GetModifierExtraHealthPercentage( params )
|
||||
if self:GetCaster() == nil or self:GetCaster():PassivesDisabled() then
|
||||
return 0
|
||||
end
|
||||
|
||||
-- How is this number intended to work? It seems to have regressed.
|
||||
return -200 --8.0 --self.bonus_hp_multiplier
|
||||
end
|
||||
|
||||
@@ -0,0 +1,29 @@
|
||||
modifier_skeleton_king_boss_run = class({})
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
function modifier_skeleton_king_boss_run:IsHidden()
|
||||
return true
|
||||
end
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
function modifier_skeleton_king_boss_run:IsPurgable()
|
||||
return false
|
||||
end
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
function modifier_skeleton_king_boss_run:DeclareFunctions()
|
||||
local funcs =
|
||||
{
|
||||
MODIFIER_PROPERTY_TRANSLATE_ACTIVITY_MODIFIERS,
|
||||
}
|
||||
return funcs
|
||||
end
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
function modifier_skeleton_king_boss_run:GetActivityTranslationModifiers( params )
|
||||
return "run"
|
||||
end
|
||||
@@ -0,0 +1,42 @@
|
||||
|
||||
modifier_slark_sleep = class({})
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
function modifier_slark_sleep:IsHidden()
|
||||
return false
|
||||
end
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
function modifier_slark_sleep:CanParentBeAutoAttacked()
|
||||
return false
|
||||
end
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
function modifier_slark_sleep:CheckState()
|
||||
local state = {}
|
||||
if IsServer() then
|
||||
state[MODIFIER_STATE_ROOTED] = true
|
||||
state[MODIFIER_STATE_BLIND] = true
|
||||
state[MODIFIER_STATE_STUNNED] = true
|
||||
state[MODIFIER_STATE_SILENCED] = true
|
||||
end
|
||||
|
||||
return state
|
||||
end
|
||||
|
||||
-----------------------------------------------------------------------
|
||||
|
||||
function modifier_slark_sleep:GetEffectName()
|
||||
return "particles/generic_gameplay/generic_sleep.vpcf"
|
||||
end
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
function modifier_slark_sleep:GetEffectAttachType()
|
||||
return PATTACH_OVERHEAD_FOLLOW
|
||||
end
|
||||
|
||||
-----------------------------------------------------------------------------
|
||||
@@ -0,0 +1,141 @@
|
||||
|
||||
modifier_spider_egg_sack = class({})
|
||||
|
||||
-------------------------------------------------------------------
|
||||
|
||||
function modifier_spider_egg_sack:IsHidden()
|
||||
return true
|
||||
end
|
||||
|
||||
-------------------------------------------------------------------
|
||||
|
||||
function modifier_spider_egg_sack:CheckState()
|
||||
local state =
|
||||
{
|
||||
[MODIFIER_STATE_NO_HEALTH_BAR] = true,
|
||||
[MODIFIER_STATE_NO_UNIT_COLLISION] = false,
|
||||
[MODIFIER_STATE_INVULNERABLE] = true,
|
||||
}
|
||||
return state
|
||||
end
|
||||
|
||||
-------------------------------------------------------------------
|
||||
|
||||
function modifier_spider_egg_sack:OnCreated( kv )
|
||||
if IsServer() then
|
||||
self.spider_min = self:GetAbility():GetSpecialValueFor( "spider_min" )
|
||||
self.spider_max = self:GetAbility():GetSpecialValueFor( "spider_max" )
|
||||
self.trigger_radius = self:GetAbility():GetSpecialValueFor( "trigger_radius" )
|
||||
self.radius = self:GetAbility():GetSpecialValueFor( "radius" )
|
||||
self.duration = self:GetAbility():GetSpecialValueFor( "duration" )
|
||||
|
||||
self.bBurst = false
|
||||
self.bTriggered = false
|
||||
self:StartIntervalThink( 0.25 )
|
||||
|
||||
end
|
||||
end
|
||||
|
||||
-------------------------------------------------------------------
|
||||
|
||||
function modifier_spider_egg_sack:DeclareFunctions()
|
||||
local funcs =
|
||||
{
|
||||
MODIFIER_EVENT_ON_DEATH,
|
||||
}
|
||||
|
||||
return funcs
|
||||
end
|
||||
|
||||
-------------------------------------------------------------------
|
||||
|
||||
function modifier_spider_egg_sack:OnDeath( params )
|
||||
if IsServer() then
|
||||
if params.unit == self:GetParent() then
|
||||
self:Burst( nil )
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
-------------------------------------------------------------------
|
||||
|
||||
function modifier_spider_egg_sack:OnIntervalThink()
|
||||
if IsServer() then
|
||||
if self.bTriggered == false then
|
||||
local enemies = FindUnitsInRadius( self:GetParent():GetTeamNumber(), self:GetParent():GetOrigin(), self:GetParent(), self.trigger_radius, DOTA_UNIT_TARGET_TEAM_ENEMY, DOTA_UNIT_TARGET_HERO + DOTA_UNIT_TARGET_BASIC, DOTA_UNIT_TARGET_FLAG_MAGIC_IMMUNE_ENEMIES, 0, false )
|
||||
if #enemies > 0 then
|
||||
self.bTriggered = true
|
||||
return
|
||||
end
|
||||
else
|
||||
self:Burst( nil )
|
||||
self:StartIntervalThink( -1 )
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
-------------------------------------------------------------------
|
||||
|
||||
function modifier_spider_egg_sack:Burst( hHero )
|
||||
if IsServer() then
|
||||
if self.bBurst == true then
|
||||
return
|
||||
end
|
||||
|
||||
local hTarget = hHero
|
||||
if hHero == nil then
|
||||
hTarget = self:GetParent()
|
||||
end
|
||||
|
||||
for i=0,RandomInt( self.spider_min, self.spider_max ) do
|
||||
local nMaxDistance = 25
|
||||
local vSpawnLoc = nil
|
||||
|
||||
local nMaxAttempts = 3
|
||||
local nAttempts = 0
|
||||
|
||||
repeat
|
||||
if nAttempts > nMaxAttempts then
|
||||
vSpawnLoc = nil
|
||||
printf( "WARNING - modifier_spider_egg_sack - failed to find valid spawn loc for newborn spider" )
|
||||
break
|
||||
end
|
||||
|
||||
local vPos = self:GetParent():GetAbsOrigin() + RandomVector( nMaxDistance )
|
||||
vSpawnLoc = FindPathablePositionNearby( vPos, 0, 50 )
|
||||
nAttempts = nAttempts + 1
|
||||
until ( GameRules.Aghanim:GetCurrentRoom():IsInRoomBounds( vSpawnLoc ) )
|
||||
|
||||
if vSpawnLoc == nil then
|
||||
vSpawnLoc = self:GetParent():GetOrigin()
|
||||
end
|
||||
|
||||
if vSpawnLoc ~= nil then
|
||||
CreateUnitByName( "npc_dota_creature_newborn_spider", vSpawnLoc, true, nil, nil, DOTA_TEAM_BADGUYS )
|
||||
else
|
||||
printf( "WARNING - modifier_spider_egg_sack: failed to spawn newborn spider" )
|
||||
end
|
||||
end
|
||||
|
||||
self.bBurst = true
|
||||
|
||||
local nFXIndex = ParticleManager:CreateParticle( "particles/units/heroes/hero_venomancer/venomancer_poison_nova.vpcf", PATTACH_CUSTOMORIGIN, nil )
|
||||
ParticleManager:SetParticleControl( nFXIndex, 0, self:GetParent():GetOrigin() )
|
||||
ParticleManager:SetParticleControl( nFXIndex, 1, Vector( self.radius / 2, 0.4, self.radius ) )
|
||||
ParticleManager:ReleaseParticleIndex( nFXIndex )
|
||||
|
||||
local enemies = FindUnitsInRadius( self:GetParent():GetTeamNumber(), self:GetParent():GetOrigin(), self:GetParent(), self.radius, DOTA_UNIT_TARGET_TEAM_ENEMY, DOTA_UNIT_TARGET_HERO + DOTA_UNIT_TARGET_BASIC, DOTA_UNIT_TARGET_FLAG_MAGIC_IMMUNE_ENEMIES, 0, false )
|
||||
for _,enemy in pairs ( enemies ) do
|
||||
if enemy ~= nil and enemy:IsInvulnerable() == false and enemy:IsMagicImmune() == false then
|
||||
--print( "Add modifier for " .. self.duration )
|
||||
enemy:AddNewModifier( self:GetParent(), self:GetAbility(), "modifier_venomancer_poison_nova", { duration = self.duration } )
|
||||
end
|
||||
end
|
||||
|
||||
EmitSoundOn( "Broodmother.LarvalParasite.Burst", self:GetParent() )
|
||||
EmitSoundOn( "EggSac.Burst", self:GetParent() )
|
||||
self:GetParent():AddEffects( EF_NODRAW )
|
||||
self:GetParent():ForceKill( false )
|
||||
end
|
||||
end
|
||||
|
||||
@@ -0,0 +1,146 @@
|
||||
|
||||
modifier_storegga_arm_slam = class ({})
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
function modifier_storegga_arm_slam:IsHidden()
|
||||
return true
|
||||
end
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
function modifier_storegga_arm_slam:IsPurgable()
|
||||
return false
|
||||
end
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
function modifier_storegga_arm_slam:OnCreated( kv )
|
||||
if IsServer() then
|
||||
self.damage_radius = self:GetAbility():GetSpecialValueFor( "damage_radius" )
|
||||
self.damage = self:GetAbility():GetSpecialValueFor( "damage" )
|
||||
self.stun_duration = self:GetAbility():GetSpecialValueFor( "stun_duration" )
|
||||
self.bAttackBegin = false
|
||||
self.hHitTargets = {}
|
||||
self:StartIntervalThink( kv["initial_delay"] / 2 )
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
function modifier_storegga_arm_slam:OnIntervalThink()
|
||||
if IsServer() then
|
||||
if self.bAttackBegin == false then
|
||||
self.bAttackBegin = true
|
||||
return
|
||||
end
|
||||
local attach1 = self:GetParent():ScriptLookupAttachment( "attach_attack1" )
|
||||
local attach2 = self:GetParent():ScriptLookupAttachment( "attach_attack1_2" )
|
||||
|
||||
local vLocation1 = self:GetParent():GetAttachmentOrigin( attach1 )
|
||||
vLocation1 = GetGroundPosition( vLocation1, self:GetParent() )
|
||||
local vLocation2 = self:GetParent():GetAttachmentOrigin( attach2 )
|
||||
vLocation2 = GetGroundPosition( vLocation2, self:GetParent() )
|
||||
local Locations = {}
|
||||
table.insert( Locations, vLocation1 )
|
||||
table.insert( Locations, vLocation2 )
|
||||
|
||||
for _,vPos in pairs ( Locations ) do
|
||||
local nFXIndex = ParticleManager:CreateParticle( "particles/creatures/ogre/ogre_melee_smash.vpcf", PATTACH_WORLDORIGIN, self:GetCaster() )
|
||||
ParticleManager:SetParticleControl( nFXIndex, 0, vPos )
|
||||
ParticleManager:SetParticleControl( nFXIndex, 1, Vector( self.damage_radius, self.damage_radius, self.damage_radius ) )
|
||||
ParticleManager:ReleaseParticleIndex( nFXIndex )
|
||||
|
||||
local enemies = FindUnitsInRadius( self:GetParent():GetTeamNumber(), vPos, self:GetParent(), self.damage_radius, DOTA_UNIT_TARGET_TEAM_ENEMY, DOTA_UNIT_TARGET_HERO + DOTA_UNIT_TARGET_BASIC, DOTA_UNIT_TARGET_FLAG_MAGIC_IMMUNE_ENEMIES, 0, false )
|
||||
for _,enemy in pairs( enemies ) do
|
||||
if enemy ~= nil and enemy:IsInvulnerable() == false and self:HasHitTarget( enemy ) == false then
|
||||
local damageInfo =
|
||||
{
|
||||
victim = enemy,
|
||||
attacker = self:GetCaster(),
|
||||
damage = self.damage,
|
||||
damage_type = DAMAGE_TYPE_PHYSICAL,
|
||||
ability = self,
|
||||
}
|
||||
|
||||
ApplyDamage( damageInfo )
|
||||
self:AddHitTarget( enemy )
|
||||
if enemy:IsAlive() == false then
|
||||
local nFXIndex = ParticleManager:CreateParticle( "particles/units/heroes/hero_phantom_assassin/phantom_assassin_crit_impact.vpcf", PATTACH_CUSTOMORIGIN, nil )
|
||||
ParticleManager:SetParticleControlEnt( nFXIndex, 0, enemy, PATTACH_POINT_FOLLOW, "attach_hitloc", enemy:GetOrigin(), true )
|
||||
ParticleManager:SetParticleControl( nFXIndex, 1, enemy:GetOrigin() )
|
||||
ParticleManager:SetParticleControlForward( nFXIndex, 1, -self:GetCaster():GetForwardVector() )
|
||||
ParticleManager:SetParticleControlEnt( nFXIndex, 10, enemy, PATTACH_ABSORIGIN_FOLLOW, nil, enemy:GetOrigin(), true )
|
||||
ParticleManager:ReleaseParticleIndex( nFXIndex )
|
||||
|
||||
EmitSoundOn( "Dungeon.BloodSplatterImpact", enemy )
|
||||
else
|
||||
enemy:AddNewModifier( self:GetCaster(), self:GetAbility(), "modifier_stunned", { duration = self.stun_duration } )
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
local hTiny = CreateUnitByName( "npc_dota_creature_small_storegga", vPos, true, self:GetParent(), self:GetParent():GetOwner(), self:GetParent():GetTeamNumber() )
|
||||
if hTiny ~= nil then
|
||||
hTiny:SetControllableByPlayer( self:GetParent():GetPlayerOwnerID(), false )
|
||||
hTiny:SetOwner( self:GetParent() )
|
||||
hTiny.bBossMinion = true
|
||||
if self:GetParent().Encounter then
|
||||
self:GetParent().Encounter:SuppressRewardsOnDeath( hTiny )
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
EmitSoundOnLocationWithCaster( vLocation1, "OgreTank.GroundSmash", self:GetCaster() )
|
||||
self:StartIntervalThink( -1 )
|
||||
end
|
||||
end
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
function modifier_storegga_arm_slam:DeclareFunctions()
|
||||
local funcs =
|
||||
{
|
||||
MODIFIER_PROPERTY_DISABLE_TURNING,
|
||||
MODIFIER_PROPERTY_TURN_RATE_PERCENTAGE,
|
||||
}
|
||||
|
||||
return funcs
|
||||
end
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
function modifier_storegga_arm_slam:GetModifierDisableTurning( params )
|
||||
if IsServer() then
|
||||
if self.bAttackBegin == true then
|
||||
return 1
|
||||
end
|
||||
end
|
||||
|
||||
return 0
|
||||
end
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
|
||||
function modifier_storegga_arm_slam:GetModifierTurnRate_Percentage( params )
|
||||
return -99
|
||||
end
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
function modifier_storegga_arm_slam:HasHitTarget( hTarget )
|
||||
for _, target in pairs( self.hHitTargets ) do
|
||||
if target == hTarget then
|
||||
return true
|
||||
end
|
||||
end
|
||||
|
||||
return false
|
||||
end
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
function modifier_storegga_arm_slam:AddHitTarget( hTarget )
|
||||
table.insert( self.hHitTargets, hTarget )
|
||||
end
|
||||
@@ -0,0 +1,127 @@
|
||||
|
||||
modifier_storegga_avalanche_thinker = class({})
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
function modifier_storegga_avalanche_thinker:IsHidden()
|
||||
return true
|
||||
end
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
function modifier_storegga_avalanche_thinker:IsPurgable()
|
||||
return false
|
||||
end
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
function modifier_storegga_avalanche_thinker:OnCreated( kv )
|
||||
if IsServer() then
|
||||
self.interval = self:GetAbility():GetSpecialValueFor( "interval" )
|
||||
self.slow_duration = self:GetAbility():GetSpecialValueFor( "slow_duration" )
|
||||
self.damage = self:GetAbility():GetSpecialValueFor( "damage" )
|
||||
self.radius = self:GetAbility():GetSpecialValueFor( "radius" )
|
||||
self.movement = self:GetAbility():GetSpecialValueFor( "movement" )
|
||||
|
||||
self.Avalanches = {}
|
||||
|
||||
local enemies = FindUnitsInRadius( self:GetCaster():GetTeamNumber(), self:GetParent():GetOrigin(), nil, FIND_UNITS_EVERYWHERE, DOTA_UNIT_TARGET_TEAM_ENEMY, DOTA_UNIT_TARGET_HERO, DOTA_UNIT_TARGET_FLAG_MAGIC_IMMUNE_ENEMIES, FIND_CLOSEST, false )
|
||||
self.hAvalancheTarget = enemies[RandomInt(1, #enemies)]
|
||||
|
||||
self:OnIntervalThink()
|
||||
self:StartIntervalThink( self.interval )
|
||||
end
|
||||
end
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
function modifier_storegga_avalanche_thinker:OnIntervalThink()
|
||||
if IsServer() then
|
||||
if self:GetCaster():IsNull() then
|
||||
self:Destroy()
|
||||
return
|
||||
end
|
||||
|
||||
local vNewAvalancheDir1 = RandomVector( 1 )
|
||||
local vNewAvalancheDir2 = RandomVector( 1 )
|
||||
if self.hAvalancheTarget ~= nil and self.hAvalancheTarget:IsAlive() then
|
||||
vNewAvalancheDir2 = self.hAvalancheTarget:GetOrigin() - self:GetCaster():GetOrigin()
|
||||
else
|
||||
local enemies = FindUnitsInRadius( self:GetCaster():GetTeamNumber(), self:GetParent():GetOrigin(), nil, FIND_UNITS_EVERYWHERE, DOTA_UNIT_TARGET_TEAM_ENEMY, DOTA_UNIT_TARGET_HERO, DOTA_UNIT_TARGET_FLAG_MAGIC_IMMUNE_ENEMIES, FIND_CLOSEST, false )
|
||||
self.hAvalancheTarget = enemies[RandomInt(1, #enemies)]
|
||||
if self.hAvalancheTarget ~= nil then
|
||||
vNewAvalancheDir2 = self.hAvalancheTarget:GetOrigin() - self:GetCaster():GetOrigin()
|
||||
end
|
||||
end
|
||||
|
||||
EmitSoundOnLocationWithCaster( self:GetParent():GetOrigin(), "Storegga.Avalanche", self:GetCaster() )
|
||||
|
||||
local hTiny = CreateUnitByName( "npc_dota_creature_small_storegga", self:GetParent():GetOrigin(), true, self:GetParent(), self:GetParent():GetOwner(), self:GetParent():GetTeamNumber() )
|
||||
if hTiny ~= nil then
|
||||
hTiny:SetControllableByPlayer( self:GetParent():GetPlayerOwnerID(), false )
|
||||
hTiny:SetOwner( self:GetParent() )
|
||||
hTiny.bBossMinion = true
|
||||
if self:GetParent().Encounter then
|
||||
self:GetParent().Encounter:SuppressRewardsOnDeath( hTiny )
|
||||
end
|
||||
end
|
||||
|
||||
vNewAvalancheDir1 = vNewAvalancheDir1:Normalized()
|
||||
vNewAvalancheDir2 = vNewAvalancheDir2:Normalized()
|
||||
|
||||
local vRadius = Vector( self.radius * .72, self.radius * .72, self.radius * .72 )
|
||||
local nFXIndex1 = ParticleManager:CreateParticle( "particles/creatures/storegga/storegga_avalanche.vpcf", PATTACH_CUSTOMORIGIN, nil )
|
||||
ParticleManager:SetParticleControl( nFXIndex1, 0, self:GetParent():GetOrigin() )
|
||||
ParticleManager:SetParticleControl( nFXIndex1, 1, vRadius )
|
||||
ParticleManager:SetParticleControlForward( nFXIndex1, 0, vNewAvalancheDir1 )
|
||||
self:AddParticle( nFXIndex1, false, false, -1, false, false )
|
||||
|
||||
local nFXIndex2 = ParticleManager:CreateParticle( "particles/creatures/storegga/storegga_avalanche.vpcf", PATTACH_CUSTOMORIGIN, nil )
|
||||
ParticleManager:SetParticleControl( nFXIndex2, 0, self:GetParent():GetOrigin() )
|
||||
ParticleManager:SetParticleControl( nFXIndex2, 1, vRadius )
|
||||
ParticleManager:SetParticleControlForward( nFXIndex2, 0, vNewAvalancheDir2 )
|
||||
self:AddParticle( nFXIndex2, false, false, -1, false, false )
|
||||
|
||||
local Avalanche1 =
|
||||
{
|
||||
vCurPos = self:GetCaster():GetOrigin(),
|
||||
vDir = vNewAvalancheDir1,
|
||||
nFX = nFXIndex1,
|
||||
}
|
||||
local Avalanche2 =
|
||||
{
|
||||
vCurPos = self:GetCaster():GetOrigin(),
|
||||
vDir = vNewAvalancheDir2,
|
||||
nFX = nFXIndex2,
|
||||
}
|
||||
|
||||
table.insert( self.Avalanches, Avalanche1 )
|
||||
table.insert( self.Avalanches, Avalanche2 )
|
||||
|
||||
for _,ava in pairs ( self.Avalanches ) do
|
||||
local vNewPos = ava.vCurPos + ava.vDir * self.movement
|
||||
vNewPos.z = GetGroundHeight( vNewPos, self:GetCaster() )
|
||||
ava.vCurPos = vNewPos
|
||||
|
||||
|
||||
ParticleManager:SetParticleControl( ava.nFX, 0, vNewPos )
|
||||
|
||||
|
||||
local enemies = FindUnitsInRadius( self:GetCaster():GetTeamNumber(), vNewPos, nil, self.radius, DOTA_UNIT_TARGET_TEAM_ENEMY, DOTA_UNIT_TARGET_HERO, DOTA_UNIT_TARGET_FLAG_MAGIC_IMMUNE_ENEMIES, FIND_CLOSEST, false )
|
||||
for _,enemy in pairs( enemies ) do
|
||||
if enemy ~= nil and enemy:IsInvulnerable() == false and enemy:IsMagicImmune() == false then
|
||||
local damageInfo =
|
||||
{
|
||||
victim = enemy,
|
||||
attacker = self:GetCaster(),
|
||||
damage = self.damage,
|
||||
damage_type = DAMAGE_TYPE_MAGICAL,
|
||||
ability = self:GetAbility(),
|
||||
}
|
||||
ApplyDamage( damageInfo )
|
||||
enemy:AddNewModifier( self:GetCaster(), self:GetAbility(), "modifier_polar_furbolg_ursa_warrior_thunder_clap", { duration = self.slow_duration } )
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -0,0 +1,54 @@
|
||||
|
||||
modifier_storegga_grab = class({})
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
function modifier_storegga_grab:IsHidden()
|
||||
return true
|
||||
end
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
function modifier_storegga_grab:IsPurgable()
|
||||
return false
|
||||
end
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
function modifier_storegga_grab:OnCreated( kv )
|
||||
if IsServer() then
|
||||
self.grab_radius = self:GetAbility():GetSpecialValueFor( "grab_radius" )
|
||||
self.min_hold_time = self:GetAbility():GetSpecialValueFor( "min_hold_time" )
|
||||
self.max_hold_time = self:GetAbility():GetSpecialValueFor( "max_hold_time" )
|
||||
|
||||
self:StartIntervalThink( kv["initial_delay"] )
|
||||
|
||||
local nFXIndex = ParticleManager:CreateParticle( "particles/test_particle/generic_attack_crit_blur.vpcf", PATTACH_CUSTOMORIGIN, self:GetParent() )
|
||||
ParticleManager:SetParticleControlEnt( nFXIndex, 0, self:GetParent(), PATTACH_POINT_FOLLOW, "attach_attack2", self:GetParent():GetOrigin(), true )
|
||||
ParticleManager:ReleaseParticleIndex( nFXIndex )
|
||||
end
|
||||
end
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
function modifier_storegga_grab:OnIntervalThink()
|
||||
if IsServer() then
|
||||
if self.hTarget == nil then
|
||||
return
|
||||
end
|
||||
|
||||
local flDist = ( self.hTarget:GetOrigin() - self:GetParent():GetOrigin() ):Length2D()
|
||||
if flDist > 700 then
|
||||
return
|
||||
end
|
||||
|
||||
local hBuff = self:GetCaster():AddNewModifier( self:GetCaster(), self:GetAbility(), "modifier_storegga_grabbed_buff", {} )
|
||||
if hBuff ~= nil then
|
||||
self:GetCaster().flThrowTimer = GameRules:GetGameTime() + RandomFloat( self.min_hold_time, self.max_hold_time )
|
||||
hBuff.hThrowObject = self.hTarget
|
||||
self.hTarget:AddNewModifier( self:GetCaster(), self:GetAbility(), "modifier_storegga_grabbed_debuff", {} )
|
||||
end
|
||||
self:Destroy()
|
||||
return
|
||||
end
|
||||
end
|
||||
@@ -0,0 +1,37 @@
|
||||
|
||||
modifier_storegga_grabbed_buff = class({})
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
function modifier_storegga_grabbed_buff:IsHidden()
|
||||
return true
|
||||
end
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
function modifier_storegga_grabbed_buff:IsPurgable()
|
||||
return false
|
||||
end
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
function modifier_storegga_grabbed_buff:DeclareFunctions()
|
||||
local funcs =
|
||||
{
|
||||
MODIFIER_PROPERTY_TRANSLATE_ACTIVITY_MODIFIERS,
|
||||
MODIFIER_PROPERTY_TURN_RATE_PERCENTAGE,
|
||||
}
|
||||
return funcs
|
||||
end
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
function modifier_storegga_grabbed_buff:GetActivityTranslationModifiers( params )
|
||||
return "tree"
|
||||
end
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
function modifier_storegga_grabbed_buff:GetModifierTurnRate_Percentage( params )
|
||||
return -90
|
||||
end
|
||||
@@ -0,0 +1,135 @@
|
||||
|
||||
modifier_storegga_grabbed_debuff = class({})
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
function modifier_storegga_grabbed_debuff:GetAttributes()
|
||||
return MODIFIER_ATTRIBUTE_IGNORE_INVULNERABLE
|
||||
end
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
function modifier_storegga_grabbed_debuff:IsHidden()
|
||||
return true
|
||||
end
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
function modifier_storegga_grabbed_debuff:IsPurgable()
|
||||
return false
|
||||
end
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
function modifier_storegga_grabbed_debuff:OnCreated( kv )
|
||||
if IsServer() then
|
||||
if self:ApplyHorizontalMotionController() == false or self:ApplyVerticalMotionController() == false then
|
||||
self:Destroy()
|
||||
return
|
||||
end
|
||||
|
||||
self.nProjHandle = -1
|
||||
self.flTime = 0.0
|
||||
self.flHeight = 0.0
|
||||
end
|
||||
end
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
function modifier_storegga_grabbed_debuff:DeclareFunctions()
|
||||
local funcs =
|
||||
{
|
||||
MODIFIER_PROPERTY_OVERRIDE_ANIMATION,
|
||||
MODIFIER_EVENT_ON_DEATH,
|
||||
}
|
||||
return funcs
|
||||
end
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
function modifier_storegga_grabbed_debuff:CheckState()
|
||||
local state =
|
||||
{
|
||||
[MODIFIER_STATE_STUNNED] = true,
|
||||
[MODIFIER_STATE_INVULNERABLE] = true,
|
||||
[MODIFIER_STATE_OUT_OF_GAME] = true,
|
||||
}
|
||||
return state
|
||||
end
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
function modifier_storegga_grabbed_debuff:OnDestroy()
|
||||
if IsServer() then
|
||||
self:GetParent():RemoveHorizontalMotionController( self )
|
||||
self:GetParent():RemoveVerticalMotionController( self )
|
||||
end
|
||||
end
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
function modifier_storegga_grabbed_debuff:UpdateHorizontalMotion( me, dt )
|
||||
if IsServer() then
|
||||
local vLocation = nil
|
||||
if self.nProjHandle == -1 then
|
||||
local attach = self:GetCaster():ScriptLookupAttachment( "attach_attack2" )
|
||||
vLocation = self:GetCaster():GetAttachmentOrigin( attach )
|
||||
else
|
||||
vLocation = ProjectileManager:GetLinearProjectileLocation( self.nProjHandle )
|
||||
end
|
||||
vLocation.z = 0.0
|
||||
me:SetOrigin( vLocation )
|
||||
end
|
||||
end
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
function modifier_storegga_grabbed_debuff:UpdateVerticalMotion( me, dt )
|
||||
if IsServer() then
|
||||
local vMyPos = me:GetOrigin()
|
||||
if self.nProjHandle == -1 then
|
||||
local attach = self:GetCaster():ScriptLookupAttachment( "attach_attack2" )
|
||||
local vLocation = self:GetCaster():GetAttachmentOrigin( attach )
|
||||
vMyPos.z = vLocation.z
|
||||
else
|
||||
local flGroundHeight = GetGroundHeight( vMyPos, me )
|
||||
local flHeightChange = dt * self.flTime * self.flHeight * 1.3
|
||||
vMyPos.z = math.max( vMyPos.z - flHeightChange, flGroundHeight )
|
||||
end
|
||||
me:SetOrigin( vMyPos )
|
||||
end
|
||||
end
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
function modifier_storegga_grabbed_debuff:OnHorizontalMotionInterrupted()
|
||||
if IsServer() then
|
||||
self:Destroy()
|
||||
end
|
||||
end
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
function modifier_storegga_grabbed_debuff:OnVerticalMotionInterrupted()
|
||||
if IsServer() then
|
||||
self:Destroy()
|
||||
end
|
||||
end
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
function modifier_storegga_grabbed_debuff:GetOverrideAnimation( params )
|
||||
return ACT_DOTA_FLAIL
|
||||
end
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
function modifier_storegga_grabbed_debuff:OnDeath( params )
|
||||
if IsServer() then
|
||||
if params.unit == self:GetCaster() then
|
||||
self:Destroy()
|
||||
end
|
||||
end
|
||||
|
||||
return 0
|
||||
end
|
||||
@@ -0,0 +1,101 @@
|
||||
|
||||
modifier_storegga_ground_pound_thinker = class({})
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
function modifier_storegga_ground_pound_thinker:IsHidden()
|
||||
return true
|
||||
end
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
function modifier_storegga_ground_pound_thinker:IsPurgable()
|
||||
return false
|
||||
end
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
function modifier_storegga_ground_pound_thinker:OnCreated( kv )
|
||||
if IsServer() then
|
||||
self.pound_interval = self:GetAbility():GetSpecialValueFor( "pound_interval" )
|
||||
self.slow_duration = self:GetAbility():GetSpecialValueFor( "slow_duration" )
|
||||
self.damage = self:GetAbility():GetSpecialValueFor( "damage" )
|
||||
self.radius = self:GetAbility():GetSpecialValueFor( "radius" )
|
||||
self.movespeed_slow = self:GetAbility():GetSpecialValueFor( "movespeed_slow" )
|
||||
|
||||
self.fTimeStarted = GameRules:GetGameTime()
|
||||
|
||||
self:OnIntervalThink()
|
||||
self:StartIntervalThink( self.pound_interval )
|
||||
end
|
||||
end
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
function modifier_storegga_ground_pound_thinker:OnIntervalThink()
|
||||
if IsServer() then
|
||||
if self:GetCaster() == nil or self:GetCaster():IsNull() then
|
||||
self:Destroy()
|
||||
return
|
||||
end
|
||||
|
||||
--print( string.format( "OnIntervalThink - time is: %.2f", GameRules:GetGameTime() ) )
|
||||
|
||||
local vThinkerPos = self:GetParent():GetAbsOrigin()
|
||||
local hEnemies = FindUnitsInRadius( self:GetCaster():GetTeamNumber(), vThinkerPos, nil, self.radius, DOTA_UNIT_TARGET_TEAM_ENEMY, DOTA_UNIT_TARGET_HERO, DOTA_UNIT_TARGET_FLAG_MAGIC_IMMUNE_ENEMIES, FIND_CLOSEST, false )
|
||||
for _, hEnemy in pairs( hEnemies ) do
|
||||
if hEnemy ~= nil and hEnemy:IsInvulnerable() == false and hEnemy:IsMagicImmune() == false then
|
||||
local damageInfo =
|
||||
{
|
||||
victim = hEnemy,
|
||||
attacker = self:GetCaster(),
|
||||
damage = self.damage,
|
||||
damage_type = self:GetAbility():GetAbilityDamageType(),
|
||||
ability = self:GetAbility(),
|
||||
}
|
||||
ApplyDamage( damageInfo )
|
||||
|
||||
if hEnemy:IsAlive() == false then
|
||||
local nFXIndex = ParticleManager:CreateParticle( "particles/units/heroes/hero_phantom_assassin/phantom_assassin_crit_impact.vpcf", PATTACH_CUSTOMORIGIN, nil )
|
||||
ParticleManager:SetParticleControlEnt( nFXIndex, 0, hEnemy, PATTACH_POINT_FOLLOW, "attach_hitloc", hEnemy:GetOrigin(), true )
|
||||
ParticleManager:SetParticleControl( nFXIndex, 1, hEnemy:GetOrigin() )
|
||||
ParticleManager:SetParticleControlForward( nFXIndex, 1, -self:GetCaster():GetForwardVector() )
|
||||
ParticleManager:SetParticleControlEnt( nFXIndex, 10, hEnemy, PATTACH_ABSORIGIN_FOLLOW, nil, hEnemy:GetOrigin(), true )
|
||||
ParticleManager:ReleaseParticleIndex( nFXIndex )
|
||||
|
||||
EmitSoundOn( "BloodSplatterImpact", hEnemy )
|
||||
else
|
||||
local kv = {
|
||||
movespeed_slow = self.movespeed_slow,
|
||||
duration = self.slow_duration,
|
||||
}
|
||||
hEnemy:AddNewModifier( self:GetCaster(), self:GetAbility(), "modifier_polar_furbolg_ursa_warrior_thunder_clap", kv )
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
EmitSoundOnLocationWithCaster( self:GetParent():GetOrigin(), "OgreTank.GroundSmash", self:GetCaster() )
|
||||
|
||||
local nFXIndex = ParticleManager:CreateParticle( "particles/creatures/ogre/ogre_melee_smash.vpcf", PATTACH_WORLDORIGIN, self:GetCaster() )
|
||||
ParticleManager:SetParticleControl( nFXIndex, 0, self:GetParent():GetOrigin() )
|
||||
ParticleManager:SetParticleControl( nFXIndex, 1, Vector( self.radius, self.radius, self.radius ) )
|
||||
ParticleManager:SetParticleFoWProperties( nFXIndex, 0, -1, self.radius )
|
||||
ParticleManager:ReleaseParticleIndex( nFXIndex )
|
||||
|
||||
ScreenShake( self:GetParent():GetOrigin(), 10.0, 100.0, 0.5, 1300.0, 0, true )
|
||||
|
||||
for i=1,2 do
|
||||
local hTiny = CreateUnitByName( "npc_dota_creature_small_storegga", vThinkerPos, true, self:GetParent(), self:GetParent():GetOwner(), self:GetParent():GetTeamNumber() )
|
||||
if hTiny ~= nil then
|
||||
hTiny:SetControllableByPlayer( self:GetParent():GetPlayerOwnerID(), false )
|
||||
hTiny:SetOwner( self:GetParent() )
|
||||
hTiny.bBossMinion = true
|
||||
if self:GetParent().Encounter then
|
||||
self:GetParent().Encounter:SuppressRewardsOnDeath( hTiny )
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
@@ -0,0 +1,61 @@
|
||||
|
||||
modifier_storegga_passive = class({})
|
||||
|
||||
-----------------------------------------------------------------------------------------
|
||||
|
||||
function modifier_storegga_passive:IsHidden()
|
||||
return true
|
||||
end
|
||||
|
||||
-----------------------------------------------------------------------------------------
|
||||
|
||||
function modifier_storegga_passive:IsPurgable()
|
||||
return false
|
||||
end
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
function modifier_storegga_passive:GetPriority()
|
||||
return MODIFIER_PRIORITY_ULTRA + 10000
|
||||
end
|
||||
|
||||
-----------------------------------------------------------------------------------------
|
||||
|
||||
function modifier_storegga_passive:CheckState()
|
||||
local state =
|
||||
{
|
||||
[MODIFIER_STATE_HEXED] = false,
|
||||
[MODIFIER_STATE_ROOTED] = false,
|
||||
[MODIFIER_STATE_SILENCED] = false,
|
||||
[MODIFIER_STATE_STUNNED] = false,
|
||||
[MODIFIER_STATE_NO_HEALTH_BAR] = true,
|
||||
[MODIFIER_STATE_FROZEN] = false,
|
||||
[MODIFIER_STATE_FEARED] = false,
|
||||
[MODIFIER_STATE_CANNOT_BE_MOTION_CONTROLLED] = true,
|
||||
}
|
||||
return state
|
||||
end
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
function modifier_storegga_passive:OnCreated( kv )
|
||||
if IsServer() then
|
||||
self:GetParent().bAbsoluteNoCC = true
|
||||
end
|
||||
end
|
||||
|
||||
-----------------------------------------------------------------------------------------
|
||||
|
||||
function modifier_storegga_passive:DeclareFunctions()
|
||||
local funcs =
|
||||
{
|
||||
MODIFIER_PROPERTY_MOVESPEED_REDUCTION_PERCENTAGE,
|
||||
}
|
||||
return funcs
|
||||
end
|
||||
|
||||
-----------------------------------------------------------------------------------------
|
||||
|
||||
function modifier_storegga_passive:GetModifierMoveSpeedReductionPercentage( params )
|
||||
return 0
|
||||
end
|
||||
@@ -0,0 +1,175 @@
|
||||
|
||||
modifier_story_crystal = class({})
|
||||
|
||||
----------------------------------------
|
||||
|
||||
function modifier_story_crystal:OnCreated( kv )
|
||||
self.hPlayerEnt = nil
|
||||
|
||||
if IsServer() then
|
||||
self.Players = {}
|
||||
self.bInMotion = false
|
||||
self.flMinHeight = 100
|
||||
self.flMaxHeight = 150
|
||||
self.bAscending = true
|
||||
self.flOssiclateTime = 5.0
|
||||
self:StartIntervalThink( 0.1 )
|
||||
end
|
||||
end
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
function modifier_story_crystal:IsHidden()
|
||||
return true
|
||||
end
|
||||
|
||||
|
||||
---------------------------------------------------------------------------
|
||||
|
||||
function modifier_story_crystal:GetEffectName()
|
||||
return "particles/creatures/aghanim/aghanim_crystal_spellswap_ambient.vpcf"
|
||||
end
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
function modifier_story_crystal:IsPurgable()
|
||||
return false
|
||||
end
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
function modifier_story_crystal:CheckState()
|
||||
local state = {}
|
||||
if IsServer() then
|
||||
state[ MODIFIER_STATE_INVULNERABLE ] = true
|
||||
state[ MODIFIER_STATE_MAGIC_IMMUNE ] = true
|
||||
state[ MODIFIER_STATE_NO_HEALTH_BAR ] = true
|
||||
state[ MODIFIER_STATE_DISARMED ] = true
|
||||
state[ MODIFIER_STATE_ROOTED ] = false
|
||||
state[ MODIFIER_STATE_ATTACK_IMMUNE ] = true
|
||||
end
|
||||
|
||||
return state
|
||||
end
|
||||
|
||||
-----------------------------------------------------------------------
|
||||
|
||||
function modifier_story_crystal:DeclareFunctions()
|
||||
local funcs =
|
||||
{
|
||||
MODIFIER_EVENT_ON_ORDER,
|
||||
}
|
||||
return funcs
|
||||
end
|
||||
|
||||
-----------------------------------------------------------------------
|
||||
|
||||
function modifier_story_crystal:OnOrder( params )
|
||||
if IsServer() then
|
||||
local hOrderedUnit = params.unit
|
||||
local hTargetUnit = params.target
|
||||
local nOrderType = params.order_type
|
||||
if nOrderType ~= DOTA_UNIT_ORDER_MOVE_TO_TARGET and nOrderType ~= DOTA_UNIT_ORDER_ATTACK_TARGET then
|
||||
return
|
||||
end
|
||||
|
||||
if hTargetUnit == nil or hTargetUnit ~= self:GetParent() then
|
||||
return
|
||||
end
|
||||
|
||||
if hOrderedUnit ~= nil and hOrderedUnit:IsRealHero() and hOrderedUnit:GetTeamNumber() == DOTA_TEAM_GOODGUYS then
|
||||
self.hPlayerEnt = hOrderedUnit
|
||||
self:StartIntervalThink( 0.1 )
|
||||
return
|
||||
end
|
||||
|
||||
self:StartIntervalThink( -1 )
|
||||
end
|
||||
|
||||
return 0
|
||||
end
|
||||
|
||||
-----------------------------------------------------------------------
|
||||
|
||||
function modifier_story_crystal:OnIntervalThink()
|
||||
if IsServer() then
|
||||
if self.bInMotion == false then
|
||||
if self:ApplyVerticalMotionController() == false then
|
||||
self:Destroy()
|
||||
end
|
||||
self.bInMotion = true
|
||||
self:StartIntervalThink( -1 )
|
||||
return
|
||||
end
|
||||
|
||||
if self.hPlayerEnt ~= nil then
|
||||
local flTalkDistance = 250.0
|
||||
if flTalkDistance >= ( self.hPlayerEnt:GetOrigin() - self:GetParent():GetOrigin() ):Length2D() then
|
||||
local nPlayerID = self.hPlayerEnt:GetPlayerOwnerID()
|
||||
for _,nID in pairs ( self.Players ) do
|
||||
if nPlayerID == nID then
|
||||
return
|
||||
end
|
||||
end
|
||||
|
||||
if GameRules.Aghanim ~= nil then
|
||||
self.hPlayerEnt:Interrupt()
|
||||
local nCrystalID = 1 + #GameRules.Aghanim.PlayerCrystals[ nPlayerID ]
|
||||
local szLine = tostring( "announcer_aghanim_agh_story_time_" .. tostring( nCrystalID ) .. "_01" )
|
||||
print( "crystal .. " .. nCrystalID .. "spoken to by " .. self.hPlayerEnt:GetUnitName() .. ", speaking line " .. szLine )
|
||||
-- EmitSoundOn( "wisp_thanks", self:GetParent() )
|
||||
EmitSoundOnLocationForPlayer( szLine, self:GetParent():GetAbsOrigin(), nPlayerID )
|
||||
table.insert( self.Players, nPlayerID )
|
||||
table.insert( GameRules.Aghanim.PlayerCrystals[ nPlayerID ], nCrystalID )
|
||||
self:StartIntervalThink( -1 )
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
function modifier_story_crystal:OnDestroy()
|
||||
if IsServer() then
|
||||
self:GetParent():RemoveVerticalMotionController( self )
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
function modifier_story_crystal:UpdateVerticalMotion( me, dt )
|
||||
if IsServer() then
|
||||
local flGroundHeight = GetGroundHeight( self:GetParent():GetAbsOrigin(), self:GetParent() )
|
||||
local flCurHeight = self:GetParent():GetAbsOrigin().z - flGroundHeight
|
||||
local flChange = ( self.flMaxHeight - self.flMinHeight ) / self.flOssiclateTime * dt
|
||||
if self.bAscending == false then
|
||||
flChange = flChange * -1
|
||||
end
|
||||
|
||||
local vNewLocation = self:GetParent():GetAbsOrigin()
|
||||
vNewLocation.z = flGroundHeight + flCurHeight + flChange
|
||||
me:SetOrigin( vNewLocation )
|
||||
|
||||
if ( vNewLocation.z - flGroundHeight ) > self.flMaxHeight then
|
||||
self.bAscending = false
|
||||
end
|
||||
if ( vNewLocation.z - flGroundHeight ) < self.flMinHeight then
|
||||
self.bAscending = true
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
function modifier_story_crystal:OnVerticalMotionInterrupted()
|
||||
if IsServer() then
|
||||
print( "motion interrupted" )
|
||||
self:Destroy()
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,142 @@
|
||||
|
||||
modifier_temple_guardian_hammer_throw = class({})
|
||||
|
||||
-------------------------------------------------------------------
|
||||
|
||||
function modifier_temple_guardian_hammer_throw:IsHidden()
|
||||
return true
|
||||
end
|
||||
|
||||
-------------------------------------------------------------------
|
||||
|
||||
function modifier_temple_guardian_hammer_throw:IsPurgable()
|
||||
return false
|
||||
end
|
||||
|
||||
-------------------------------------------------------------------
|
||||
|
||||
function modifier_temple_guardian_hammer_throw:RemoveOnDeath()
|
||||
return false
|
||||
end
|
||||
|
||||
-------------------------------------------------------------------
|
||||
|
||||
function modifier_temple_guardian_hammer_throw:OnCreated( kv )
|
||||
if IsServer() then
|
||||
self.hammer_damage = self:GetAbility():GetSpecialValueFor( "hammer_damage" )
|
||||
self.throw_duration = self:GetAbility():GetSpecialValueFor( "throw_duration" )
|
||||
self.stun_duration = self:GetAbility():GetSpecialValueFor( "stun_duration" )
|
||||
self.radius = self:GetAbility():GetSpecialValueFor( "radius" )
|
||||
|
||||
self.hHitEntities = {}
|
||||
|
||||
self.hHammer = CreateUnitByName( "npc_dota_beastmaster_axe", self:GetParent():GetOrigin(), false, nil, nil, self:GetParent():GetTeamNumber() )
|
||||
if self.hHammer == nil then
|
||||
self:Destroy()
|
||||
return
|
||||
end
|
||||
|
||||
self.hHammer:AddEffects( EF_NODRAW )
|
||||
self.hHammer:AddNewModifier( self:GetCaster(), self:GetAbility(), "modifier_beastmaster_axe_invulnerable", kv )
|
||||
|
||||
self.vSourceLoc = self:GetCaster():GetOrigin()
|
||||
self.vSourceLoc.z = self.vSourceLoc.z + 180
|
||||
self.vTargetLoc = Vector( kv["x"], kv["y"], self.vSourceLoc.z )
|
||||
self.vToTarget = self.vTargetLoc - self.vSourceLoc
|
||||
self.vDir = self.vToTarget:Normalized()
|
||||
self.flDist = self.vToTarget:Length2D()
|
||||
|
||||
self.flDieTime = GameRules:GetGameTime() + self.throw_duration
|
||||
self.bReturning = false
|
||||
|
||||
self.nFXIndex = ParticleManager:CreateParticle( "particles/test_particle/omniknight_wildaxe.vpcf", PATTACH_CUSTOMORIGIN, nil )
|
||||
ParticleManager:SetParticleControlEnt( self.nFXIndex, 0, self.hHammer, PATTACH_ABSORIGIN_FOLLOW, nil, self.hHammer:GetOrigin(), true )
|
||||
|
||||
EmitSoundOn( "TempleGuardian.HammerThrow", self:GetCaster() )
|
||||
|
||||
self:StartIntervalThink( 0.05 )
|
||||
end
|
||||
end
|
||||
|
||||
-------------------------------------------------------------------
|
||||
|
||||
function modifier_temple_guardian_hammer_throw:OnIntervalThink()
|
||||
if IsServer() then
|
||||
local flPct = ( self.flDieTime - GameRules:GetGameTime() ) / self.throw_duration
|
||||
local t = 1.0 - flPct
|
||||
|
||||
local vPos = self.vSourceLoc + ( self.vDir * self.flDist * t * 2 )
|
||||
if self.bReturning == true then
|
||||
vPos = self.vTargetLoc - ( self.vDir * self.flDist * ( t - 0.5 ) * 2 )
|
||||
end
|
||||
|
||||
if FrameTime() > 0.0 then
|
||||
local vVel = vPos - self.hHammer:GetOrigin() / FrameTime()
|
||||
self.hHammer:SetVelocity( vVel )
|
||||
end
|
||||
|
||||
self.hHammer:SetOrigin( vPos )
|
||||
|
||||
local enemies = FindUnitsInRadius( self:GetParent():GetTeamNumber(), self.hHammer:GetOrigin(), self.hHammer, self.radius, DOTA_UNIT_TARGET_TEAM_ENEMY, DOTA_UNIT_TARGET_HERO + DOTA_UNIT_TARGET_BASIC, DOTA_UNIT_TARGET_FLAG_MAGIC_IMMUNE_ENEMIES, 0, false )
|
||||
for _,enemy in pairs( enemies ) do
|
||||
if enemy ~= nil and enemy:IsInvulnerable() == false and self:HasHitTarget( enemy ) == false then
|
||||
self:AddHitTarget( enemy )
|
||||
local damageInfo =
|
||||
{
|
||||
victim = enemy,
|
||||
attacker = self:GetCaster(),
|
||||
damage = self.hammer_damage,
|
||||
damage_type = DAMAGE_TYPE_MAGICAL,
|
||||
ability = self:GetAbility(),
|
||||
}
|
||||
ApplyDamage( damageInfo )
|
||||
enemy:AddNewModifier( self:GetCaster(), self:GetAbility(), "modifier_stunned", { duration = self.stun_duration } )
|
||||
EmitSoundOn( "TempleGuardian.HammerThrow.Damage", enemy )
|
||||
|
||||
local nFXIndex = ParticleManager:CreateParticle( "particles/units/heroes/hero_beastmaster/beastmaster_wildaxes_hit.vpcf", PATTACH_CUSTOMORIGIN, nil )
|
||||
ParticleManager:SetParticleControlEnt( nFXIndex, 0, enemy, PATTACH_POINT_FOLLOW, "attach_hitloc", enemy:GetOrigin(), true )
|
||||
ParticleManager:ReleaseParticleIndex( nFXIndex )
|
||||
end
|
||||
end
|
||||
|
||||
if t >= 0.5 then
|
||||
self.bReturning = true
|
||||
end
|
||||
|
||||
if t >= 0.95 then
|
||||
self:Destroy()
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
-------------------------------------------------------------------
|
||||
|
||||
function modifier_temple_guardian_hammer_throw:OnDestroy()
|
||||
if IsServer() then
|
||||
UTIL_Remove( self.hHammer )
|
||||
ParticleManager:DestroyParticle( self.nFXIndex, true )
|
||||
end
|
||||
end
|
||||
|
||||
-------------------------------------------------------------------
|
||||
|
||||
function modifier_temple_guardian_hammer_throw:HasHitTarget( enemy )
|
||||
if IsServer() then
|
||||
for _,hitEnemy in pairs( self.hHitEntities ) do
|
||||
if hitEnemy == enemy then
|
||||
return true
|
||||
end
|
||||
end
|
||||
return false
|
||||
end
|
||||
end
|
||||
|
||||
-------------------------------------------------------------------
|
||||
|
||||
function modifier_temple_guardian_hammer_throw:AddHitTarget( enemy )
|
||||
if IsServer() then
|
||||
table.insert( self.hHitEntities, enemy )
|
||||
end
|
||||
end
|
||||
|
||||
-------------------------------------------------------------------
|
||||
@@ -0,0 +1,35 @@
|
||||
|
||||
modifier_temple_guardian_immunity = class({})
|
||||
|
||||
-----------------------------------------------------------------------------------------
|
||||
|
||||
function modifier_temple_guardian_immunity:IsHidden()
|
||||
return true
|
||||
end
|
||||
|
||||
-----------------------------------------------------------------------------------------
|
||||
|
||||
function modifier_temple_guardian_immunity:IsPurgable()
|
||||
return false
|
||||
end
|
||||
|
||||
-----------------------------------------------------------------------------------------
|
||||
|
||||
function modifier_temple_guardian_immunity:CheckState()
|
||||
local state = {}
|
||||
if IsServer() then
|
||||
state[MODIFIER_STATE_MAGIC_IMMUNE] = true
|
||||
state[MODIFIER_STATE_INVULNERABLE] = true
|
||||
state[MODIFIER_STATE_OUT_OF_GAME] = true
|
||||
end
|
||||
|
||||
return state
|
||||
end
|
||||
|
||||
-----------------------------------------------------------------------------------------
|
||||
|
||||
function modifier_temple_guardian_immunity:GetPriority()
|
||||
return MODIFIER_PRIORITY_SUPER_ULTRA
|
||||
end
|
||||
|
||||
-----------------------------------------------------------------------------------------
|
||||
@@ -0,0 +1,109 @@
|
||||
|
||||
modifier_temple_guardian_passive = class({})
|
||||
|
||||
-----------------------------------------------------------------------------------------
|
||||
|
||||
function modifier_temple_guardian_passive:IsHidden()
|
||||
return true
|
||||
end
|
||||
|
||||
-----------------------------------------------------------------------------------------
|
||||
|
||||
function modifier_temple_guardian_passive:IsPurgable()
|
||||
return false
|
||||
end
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
function modifier_temple_guardian_passive:GetPriority()
|
||||
return MODIFIER_PRIORITY_ULTRA + 10000
|
||||
end
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
function modifier_temple_guardian_passive:OnCreated( kv )
|
||||
if IsServer() then
|
||||
self.nonrage_status_resistance = self:GetAbility():GetSpecialValueFor( "nonrage_status_resistance" )
|
||||
self.rage_move_speed_bonus = self:GetAbility():GetSpecialValueFor( "rage_move_speed_bonus" )
|
||||
self.rage_model_scale_bonus = self:GetAbility():GetSpecialValueFor( "rage_model_scale_bonus" )
|
||||
self.rage_turn_rate_bonus_pct = self:GetAbility():GetSpecialValueFor( "rage_turn_rate_bonus_pct" )
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
-----------------------------------------------------------------------------------------
|
||||
|
||||
function modifier_temple_guardian_passive:CheckState()
|
||||
local state =
|
||||
{
|
||||
[ MODIFIER_STATE_FEARED ] = false,
|
||||
[ MODIFIER_STATE_CANNOT_BE_MOTION_CONTROLLED ] = true,
|
||||
[ MODIFIER_STATE_UNSLOWABLE ] = true,
|
||||
}
|
||||
|
||||
return state
|
||||
end
|
||||
|
||||
-----------------------------------------------------------------------------------------
|
||||
|
||||
function modifier_temple_guardian_passive:DeclareFunctions()
|
||||
local funcs =
|
||||
{
|
||||
MODIFIER_PROPERTY_STATUS_RESISTANCE_STACKING,
|
||||
MODIFIER_PROPERTY_MOVESPEED_BONUS_CONSTANT,
|
||||
MODIFIER_PROPERTY_MODEL_SCALE,
|
||||
MODIFIER_PROPERTY_TURN_RATE_PERCENTAGE,
|
||||
}
|
||||
|
||||
return funcs
|
||||
end
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
function modifier_temple_guardian_passive:GetModifierStatusResistanceStacking( params )
|
||||
if IsServer() then
|
||||
if self:GetParent().bIsEnraged == true then
|
||||
return 100
|
||||
end
|
||||
end
|
||||
|
||||
return self.nonrage_status_resistance
|
||||
end
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
function modifier_temple_guardian_passive:GetModifierMoveSpeedBonus_Constant( params )
|
||||
if IsServer() then
|
||||
if self:GetParent().bIsEnraged == true then
|
||||
return self.rage_move_speed_bonus
|
||||
end
|
||||
end
|
||||
|
||||
return 0
|
||||
end
|
||||
|
||||
-----------------------------------------------------------------------------------------
|
||||
|
||||
function modifier_temple_guardian_passive:GetModifierModelScale( params )
|
||||
if IsServer() then
|
||||
if self:GetParent().bIsEnraged == true then
|
||||
return self.rage_model_scale_bonus
|
||||
end
|
||||
end
|
||||
|
||||
return 0
|
||||
end
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
function modifier_temple_guardian_passive:GetModifierTurnRate_Percentage( params )
|
||||
if IsServer() then
|
||||
if self:GetParent().bIsEnraged == true then
|
||||
return self.rage_turn_rate_bonus_pct
|
||||
end
|
||||
end
|
||||
|
||||
return 0
|
||||
end
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
@@ -0,0 +1,42 @@
|
||||
|
||||
modifier_temple_guardian_statue = class({})
|
||||
|
||||
-----------------------------------------------------------------------------
|
||||
|
||||
function modifier_temple_guardian_statue:IsHidden()
|
||||
return true
|
||||
end
|
||||
|
||||
-------------------------------------------------------------------
|
||||
|
||||
function modifier_temple_guardian_statue:CheckState()
|
||||
local state =
|
||||
{
|
||||
[MODIFIER_STATE_NO_HEALTH_BAR] = true,
|
||||
[MODIFIER_STATE_STUNNED] = true,
|
||||
[MODIFIER_STATE_INVULNERABLE] = true,
|
||||
[MODIFIER_STATE_UNSELECTABLE] = true,
|
||||
[MODIFIER_STATE_NOT_ON_MINIMAP] = true,
|
||||
}
|
||||
|
||||
return state
|
||||
end
|
||||
|
||||
-------------------------------------------------------------------
|
||||
|
||||
function modifier_temple_guardian_statue:OnCreated( kv )
|
||||
if IsServer() then
|
||||
local vAngles = self:GetParent():GetAnglesAsVector()
|
||||
self:GetParent():SetAngles( vAngles.x, vAngles.y - 90.0, vAngles.z )
|
||||
self:GetParent():StartGesture( ACT_DOTA_CAST_ABILITY_7 )
|
||||
end
|
||||
end
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
function modifier_temple_guardian_statue:OnDestroy()
|
||||
if IsServer() then
|
||||
end
|
||||
end
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
@@ -0,0 +1,69 @@
|
||||
|
||||
modifier_temple_guardian_wrath_thinker = class({})
|
||||
|
||||
-----------------------------------------------------------------------------
|
||||
|
||||
function modifier_temple_guardian_wrath_thinker:OnCreated( kv )
|
||||
if IsServer() then
|
||||
self.delay = self:GetAbility():GetSpecialValueFor( "delay" )
|
||||
self.radius = self:GetAbility():GetSpecialValueFor( "radius" )
|
||||
self.radius = self.radius + kv[ "extra_radius" ]
|
||||
self.blast_damage = self:GetAbility():GetSpecialValueFor( "blast_damage" )
|
||||
|
||||
self:StartIntervalThink( self.delay )
|
||||
|
||||
local nFXIndex = ParticleManager:CreateParticle( "particles/test_particle/dungeon_generic_blast_pre.vpcf", PATTACH_CUSTOMORIGIN, nil )
|
||||
ParticleManager:SetParticleControl( nFXIndex, 0, self:GetParent():GetOrigin() )
|
||||
ParticleManager:SetParticleControl( nFXIndex, 1, Vector( self.radius, self.delay, 1.0 ) )
|
||||
ParticleManager:SetParticleControl( nFXIndex, 15, Vector( 175, 238, 238 ) )
|
||||
ParticleManager:SetParticleControl( nFXIndex, 16, Vector( 1, 0, 0 ) )
|
||||
ParticleManager:ReleaseParticleIndex( nFXIndex )
|
||||
end
|
||||
end
|
||||
|
||||
-----------------------------------------------------------------------------
|
||||
|
||||
function modifier_temple_guardian_wrath_thinker:OnIntervalThink()
|
||||
if IsServer() then
|
||||
local nFXIndex = ParticleManager:CreateParticle( "particles/test_particle/dungeon_generic_blast.vpcf", PATTACH_CUSTOMORIGIN, nil )
|
||||
ParticleManager:SetParticleControl( nFXIndex, 0, self:GetParent():GetOrigin() )
|
||||
ParticleManager:SetParticleControl( nFXIndex, 1, Vector ( self.radius, self.radius, self.radius ) )
|
||||
ParticleManager:SetParticleControl( nFXIndex, 15, Vector( 175, 238, 238 ) )
|
||||
ParticleManager:SetParticleControl( nFXIndex, 16, Vector( 1, 0, 0 ) )
|
||||
ParticleManager:ReleaseParticleIndex( nFXIndex )
|
||||
|
||||
EmitSoundOn( "TempleGuardian.Wrath.Explosion", self:GetParent() )
|
||||
local enemies = FindUnitsInRadius( self:GetParent():GetTeamNumber(), self:GetParent():GetOrigin(), nil, self.radius, DOTA_UNIT_TARGET_TEAM_ENEMY, DOTA_UNIT_TARGET_HERO, DOTA_UNIT_TARGET_FLAG_MAGIC_IMMUNE_ENEMIES + DOTA_UNIT_TARGET_FLAG_FOW_VISIBLE, FIND_CLOSEST, false )
|
||||
for _,enemy in pairs( enemies ) do
|
||||
if enemy ~= nil and enemy:IsInvulnerable() == false then
|
||||
local damageInfo =
|
||||
{
|
||||
victim = enemy,
|
||||
attacker = self:GetCaster(),
|
||||
damage = self.blast_damage,
|
||||
damage_type = self:GetAbility():GetAbilityDamageType(),
|
||||
ability = self:GetAbility(),
|
||||
}
|
||||
ApplyDamage( damageInfo )
|
||||
end
|
||||
end
|
||||
|
||||
if RollPercentage( 3 ) then
|
||||
local vLocation = self:GetParent():GetAbsOrigin()
|
||||
if GridNav:CanFindPath( self:GetCaster():GetAbsOrigin(), vLocation ) then
|
||||
local newItem = CreateItem( "item_mana_potion", nil, nil )
|
||||
newItem:SetPurchaseTime( 0 )
|
||||
if newItem:IsPermanent() and newItem:GetShareability() == ITEM_FULLY_SHAREABLE then
|
||||
item:SetStacksWithOtherOwners( true )
|
||||
end
|
||||
|
||||
local drop = CreateItemOnPositionSync( vLocation, newItem )
|
||||
newItem:LaunchLoot( true, 300, 0.75, vLocation )
|
||||
end
|
||||
end
|
||||
|
||||
UTIL_Remove( self:GetParent() )
|
||||
end
|
||||
end
|
||||
|
||||
-----------------------------------------------------------------------------
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user