Ebonfrost Crystal v1
3600
ID:
437
Family ID:
Author:
Ashbringer
Rarity:
unique
Element:
ice
Attack Type:
Elemental
Attack Range:
1000
Attack CD:
1.6
Damage:
1960-1960
Mana:
400
Mana regen:
0
Status:
Approved

Description:

A pristine crystal atop a pillar of black frost.
Shattering Barrage
Spends all mana to encase the target in ice, stunning it and increasing damage taken by 100% for up to [mana / 150] seconds. All icicles are then fired at the target. Duration is reduced by 75% on Bosses, to a minimum of 2 seconds.

Level Bonus:
-1 mana divisor

AC_TYPE_OFFENSIVE_UNIT
 300, 1000 range, 30s cooldown
Icicles
Attacks have a 15% chance and Icy Bombardments have a 5% chance to create an icicle on hit, which is stored and waits to be fired. Stored icicles passively increase attack damage by 5% and mana regen by 0.5 mana per second each. Maximum of 5 icicles. At maximum icicles, any more icicles created are instantly fired at the target. Each icicle deals 3000 Frostburn damage on hit and permanently increases the damage dealt by future icicles by this tower by 2%.

Level Bonus:
+0.4% chance on attack
+0.1% chance on Icy Bombardment
+80 damage
+1 max icicle every 5 levels
Icy Bombardment
Attacks have a 15% chance to fire a projectile at a random point within 150 range of the attacked creep that deals 25% of current attack damage as Frostburn damage in 200 AoE splash. Each additional projectile has a 30% chance to fire another, up to a maximum of 4 per attack.

Level Bonus:
+0.4% initial chance
+0.4% additional chance
+0.6% damage
Frostburn
This tower's attacks and abilities deal Frostburn damage. 50% of the damage is dealt immediately as attack damage. 100% of the remaining damage is dealt as spell damage over 5 seconds. If this effect is reapplied, any remaining damage will be added to the new duration.

Level Bonus:
+1% damage over time
Download

Toggle Triggers

Autocast

AUTOCAST_cooldown: 30 AUTOCAST_autoRange: 750 AUTOCAST_manacost: 300 AUTOCAST_range: 1000 AUTOCAST_targetType: 0 AUTOCAST_numBuffsBeforeIdle: 0 caster_art: target_art: AUTOCAST_autocastType: AC_TYPE_OFFENSIVE_UNIT AUTOCAST_buffType: 0 AUTOCAST_isExtended: true AUTOCAST_targetSelf: false
private function onAutocast takes Tower tower returns nothing
    local Creep target = Event.getTarget()
    local real towermana = GetUnitState( tower.getUnit(), UNIT_STATE_MANA)
    local real duration = towermana / (150 - tower.getLevel())
        
    if target.getSize()==SIZE_BOSS then 
        set duration = duration * 0.25
        if duration<2.0 then
            set duration = 2.0
        endif
    endif
    call ashbringer_shatter_buff.applyCustomTimed(tower, target, tower.getLevel(), duration)
    call tower.subtractMana(towermana, true)
endfunction

Header

    globals
        BuffType ashbringer_frostburn_buff
        BuffType ashbringer_shatter_buff
        ProjectileType ashbringer_breath_missile
        BuffType ashbringer_icicle_buff
        ProjectileType ashbringer_icicle_prop
        ProjectileType ashbringer_icicle_missile
    endglobals
    
    struct Icicles
        Projectile array p[10]
        Effect array e[10]
        boolean array t[10]
        real array x[10]
        real array y[10]
    endstruct
    
    function ashbringer_icicles_setup  takes Tower tower returns nothing
        local Icicles ic = Icicles.create()
        local integer count = 0
        set tower.userInt = 0
        set tower.userInt2 = 5 //starting max
        set tower.userReal = 0
        set tower.userReal2 = I2R(tower.getUID())
        
        loop
            set ic.e[count] = 0
            set ic.t[count] = false
            set count = count + 1
            exitwhen count==10
        endloop
        set tower.userInt3 = ic
    endfunction
    
    function ashbringer_icicle_fire takes Tower tower, Creep target returns nothing
        call Projectile.createFromPointToUnit(ashbringer_icicle_missile, tower, 0, 0, tower.getX(), tower.getY(), 200, target, true, false, false).setScale(0.7)
        set tower.userReal = tower.userReal + 1
    endfunction
    
    function ashbringer_icicle_store takes Tower tower returns nothing
        local integer num = tower.userInt
        local real tower_x
        local real tower_y
        local real angle
        local real target_x
        local real target_y
        local Projectile p
        local Icicles ic = tower.userInt3
        
        //safeguard against remnant icicles, find open icicle slot
        if ic.t[num]==true then
            set num = 0
            loop
                set num = num + 1
                exitwhen num==tower.userInt2 or ic.t[num-1]!=true
            endloop
        endif
        if num<tower.userInt2 then
            set angle = 360 / tower.userInt2 * num
            set tower_x = tower.getX()
            set tower_y = tower.getY()
            set target_x = tower_x + 100 * Cos(Deg2Rad(angle))
            set target_y = tower_y + 100 * Sin(Deg2Rad(angle))
            set p = Projectile.createLinearInterpolationFromPointToPoint(ashbringer_icicle_prop, tower, 1.0, 0.0, tower_x, tower_y, 200, target_x, target_y, 200, 0.0)
            call p.setScale(0.7)
            set p.userReal = target_x
            set p.userReal2 = target_y
            set p.userReal3 = angle
            set p.userInt = num
            set ic.p[num] = p
            set ic.x[num] = p.userReal
            set ic.y[num] = p.userReal2
            set ic.t[num] = true
            set tower.userInt = tower.userInt + 1
            call ashbringer_icicle_buff.apply(tower, tower, tower.userInt)
        endif
    endfunction
    
    function ashbringer_icicle_effect takes Projectile p, Unit target returns nothing
        local Tower tower = p.getCaster()
        local Icicles ic = tower.userInt3
        
        if ic.e[p.userInt]!=0 then
            call ic.e[p.userInt].destroy()
        endif
        if ic.t[p.userInt]==true and tower.getUID()!=0 and tower.getUID()==R2I(tower.userReal2) then
            set ic.e[p.userInt] = Effect.createScaled("Abilities\\Spells\\Other\\FrostBolt\\FrostBoltMissile.mdl", p.userReal, p.userReal2, 200, p.userReal3, 0.7)
            call ic.e[p.userInt].noDeathAnimation()
        endif
    endfunction
    
    function ashbringer_icicle_create takes Tower tower, Creep target returns nothing
        if tower.userInt<tower.userInt2 then
            call ashbringer_icicle_store(tower) //stores the icicle
        else
            call ashbringer_icicle_fire(tower, target) //fires on immediately
        endif
    endfunction
    
    function ashbringer_frostburn_damage takes Tower tower, Creep target, real damage returns nothing
        local Buff b
        local real damage_stack
        local real dot_inc = 1.0 + (tower.getLevel() * 0.01)
        local integer limit = 25 + tower.getLevel()
        
        call tower.doAttackDamage(target, damage * 0.5, tower.calcAttackMulticrit(0, 0, 0))
        set b = target.getBuffOfType(ashbringer_frostburn_buff)
        if b != 0 then
            set damage_stack = b.userReal + (damage * 0.5 * dot_inc)
            set ashbringer_frostburn_buff.apply(tower, target, 0).userReal = damage_stack
        else
            set ashbringer_frostburn_buff.apply(tower, target, 0).userReal = (damage * 0.5 * dot_inc)
        endif
    endfunction
    
    function ashbringer_frostburn_dot takes Buff b returns nothing
        local Tower tower = b.getCaster()
        local Creep target = b.getBuffedUnit()
        local real remaining = b.getRemainingDuration()
        local real damage_tick = b.userReal / remaining
        
        if remaining<1 then
            set damage_tick = b.userReal
        endif
        if damage_tick>0 then
            set b.userReal = b.userReal - damage_tick
            call tower.doSpellDamage(target, damage_tick, tower.calcSpellCritNoBonus())
        endif
    endfunction
    
    public function ashbringer_icicle_hit takes Projectile p, Creep target returns nothing 
        local Tower tower = p.getCaster()

        call ashbringer_frostburn_damage(tower, target, (3000 + (tower.getLevel() * 80)) * (1.0 + (tower.userReal * 0.02)))
    endfunction
    
    public function ashbringer_icicle_fireall takes Tower tower, Creep target returns nothing
        local Icicles ic = tower.userInt3
        local integer count = tower.userInt2
        local Projectile icicle
        local Buff b
        
        set tower.userInt = tower.userInt2 //set to max so any created during this time are fired instantly
        loop
            set count = count - 1
            if ic.t[count]==true then
                set icicle = Projectile.createFromPointToUnit(ashbringer_icicle_missile, tower, 0, 0, ic.x[count], ic.y[count], 200, target, true, false, false)
                set icicle.speed = 1400 - (count * 70)
                call icicle.setScale(0.7)
                set tower.userReal = tower.userReal + 1
                set ic.t[count] = false
            endif
            call ic.p[count].destroy()
            if ic.e[count]!=0 then
                call ic.e[count].destroy()
            endif
            set ic.p[count] = 0
            set ic.e[count] = 0
            exitwhen count==0
        endloop
        set tower.userInt = 0
        set b = tower.getBuffOfType(ashbringer_icicle_buff)
        if b != 0 then
            call b.removeBuff()
        endif
    endfunction
    
    function ashbringer_breath_barrage takes Tower tower, real chance, Creep target returns nothing
        local integer shots = 0
        local real target_x = target.getX()
        local real target_y = target.getY()
        local integer UID = target.getUID()
        local Projectile p
        local real random_angle
        local real random_distance
        local real launch_x
        local real launch_y
        
        loop
            set random_angle = GetRandomReal(0, 360)
            set random_distance = GetRandomReal(0, 150)
            set launch_x = target_x + random_distance * Cos(Deg2Rad(random_angle))
            set launch_y = target_y + random_distance * Sin(Deg2Rad(random_angle))
            set p = Projectile.createLinearInterpolationFromPointToPoint(ashbringer_breath_missile, tower, 0, 0, tower.getX(), tower.getY(), 200, launch_x, launch_y, 0, 0.2)
            set p.userReal = launch_x
            set p.userReal2 = launch_y
            set shots = shots + 1
            exitwhen tower.calcChance(chance) == false or shots>=4
        endloop
    endfunction
    
    function ashbringer_breath_hit takes Projectile p returns nothing
        local Tower tower = p.getCaster()
        local Iterate i = Iterate.overUnitsInRange(tower, TARGET_TYPE_CREEPS, p.userReal, p.userReal2, 200)
        local Creep next = i.next()
        local real damage = tower.getCurrentAttackDamageWithBonus() * (0.25 + (tower.getLevel() * 0.006))
        local real icicle_chance = 0.05 + (tower.getLevel() * 0.001)
        
        loop
            exitwhen next == 0
            call ashbringer_frostburn_damage(tower, next, damage)
            if tower.calcChance(icicle_chance) then
                call ashbringer_icicle_create(tower, next)
            endif
            set next = i.next()
        endloop
    endfunction
    
    function ashbringer_shatter_oncreate takes Buff b returns nothing
        local Tower tower = b.getCaster()
        local Creep target = b.getBuffedUnit()
        
        call cb_stun.applyOnlyTimed(tower, target, b.getRemainingDuration())
        call ashbringer_icicle_fireall(tower, target)
    endfunction
    
    //Do not remove or rename this function!
    //Put your initialization tasks here, this function will be called on map init
    private function init takes nothing returns nothing
        local Modifier ashbringer_icicle_modifier = Modifier.create()
        local Modifier ashbringer_shatter_modifier = Modifier.create()
        
        set  ashbringer_frostburn_buff = BuffType.create(5, 0, false)
        call ashbringer_frostburn_buff.setBuffIcon('@@0@@')
        call ashbringer_frostburn_buff.addPeriodicEvent(ashbringer_frostburn_dot, 1.0)
        
        set  ashbringer_shatter_buff = BuffType.create(5, 0, false)
        call ashbringer_shatter_buff.setBuffIcon('@@1@@')
        call ashbringer_shatter_modifier.addModification(MOD_ATK_DAMAGE_RECEIVED, 0, 1.0)
        call ashbringer_shatter_modifier.addModification(MOD_SPELL_DAMAGE_RECEIVED, 0, 1.0)
        call ashbringer_shatter_buff.setBuffModifier(ashbringer_shatter_modifier)
        call ashbringer_shatter_buff.addEventOnCreate(ashbringer_shatter_oncreate)
        
        set ashbringer_icicle_buff = BuffType.create(-1.0, 0, true)
        call ashbringer_icicle_buff.setBuffIcon('@@2@@')
        call ashbringer_icicle_modifier.addModification(MOD_DAMAGE_ADD_PERC, 0.0, 0.05)
        call ashbringer_icicle_modifier.addModification(MOD_MANA_REGEN, 0.0, 0.5)
        call ashbringer_icicle_buff.setBuffModifier(ashbringer_icicle_modifier)
        
        set ashbringer_breath_missile = ProjectileType.create("Abilities\\Weapons\\FrostWyrmMissile\\FrostWyrmMissile.mdl", 5, 1650) 
        call ashbringer_breath_missile.setEventOnCleanup(ProjectileEvent.ashbringer_breath_hit)
        
        set ashbringer_icicle_prop = ProjectileType.createInterpolate("Abilities\\Spells\\Other\\FrostBolt\\FrostBoltMissile.mdl", 200)
        call ashbringer_icicle_prop.setEventOnInterpolationFinished(ashbringer_icicle_effect)
        call ashbringer_icicle_prop.disableExplodeOnExpiration()
        
        set ashbringer_icicle_missile = ProjectileType.create("Abilities\\Spells\\Other\\FrostBolt\\FrostBoltMissile.mdl", 5, 1400)
        call ashbringer_icicle_missile.enableHoming(ProjectileTargetEvent.ashbringer_icicle_hit, 0)
    endfunction

On Attack

ONATTACK_chance: 0.15 ONATTACK_chanceLevelAdd: 0.004
function onAttack takes Tower tower returns nothing
    call ashbringer_breath_barrage(tower, 0.3 + (tower.getLevel() * 0.004), Event.getTarget())
endfunction

On Damage

ONDAMAGE_chance: 1.0 ONDAMAGE_chanceLevelAdd: 0.0
function onDamage takes Tower tower returns nothing
    local Creep target = Event.getTarget()
    local real damage = Event.damage
    local real icicle_chance = 0.15 + (tower.getLevel() * 0.004)
    
    call ashbringer_frostburn_damage(tower, target, damage)
    set Event.damage = 0
    if tower.calcChance(icicle_chance) then
        call ashbringer_icicle_create(tower, Event.getTarget())
    endif
endfunction

On Level Up

function onLevelUp takes Tower tower returns nothing
    local integer prev_max = tower.userInt2
    local Icicles ic = tower.userInt3
    local Buff b
    local integer count = 0
    
    set tower.userInt2 = 5 + (tower.getLevel() / 5)
    
    //cleanup ones over the limit on delevel
    if tower.userInt2<prev_max then
        set count = tower.userInt2
        loop
            if ic.t[count]==true then
                call ic.p[count].destroy()
                if ic.e[count]!=0 then
                    call ic.e[count].destroy()
                endif
                set ic.t[count] = false
            endif
            set count = count + 1
            exitwhen count==10
        endloop
    endif
endfunction

On Tower Creation

function onCreate takes Tower tower returns nothing
    call ashbringer_icicles_setup(tower)
endfunction

On Tower Destruction

function onDestruct takes Tower tower returns nothing
    local Icicles ic = tower.userInt3
    local integer count = 0
    local Buff b
    
    loop
        if ic.t[count]==true then
            call ic.p[count].destroy()
            if ic.e[count]!=0 then
                call ic.e[count].destroy()
            endif
            set ic.t[count] = false
        endif
        set count = count + 1
        exitwhen count==10
    endloop
    call ic.destroy()
    set b = tower.getBuffOfType(ashbringer_icicle_buff)
    if b != 0 then
        call b.removeBuff()
    endif
endfunction