Glaive Master v1
3600
ID:
435
Family ID:
Author:
Ashbringer
Rarity:
unique
Element:
iron
Attack Type:
Physical
Attack Range:
1000
Attack CD:
1.4
Damage:
1855-1855
Status:
Approved

Description:

Eviscerate them all, make them bleed.
Specials:
Bounce attack:
   2 targets
Glaivesaw:
Create a Glaivesaw at the target location. Glaivesaws deal 50% of attack damage as Lacerate damage to enemies within 150 range per second. Limit 3.

Level Bonus:
+1% damage
Glaive Storm
Hits have a 5% chance to throw an additional glaive at the target, dealing 50% of attack damage as Lacerate damage before returning to the tower. When the glaive returns, it bounces to a new random target within attack range. Maximum of 20 hits. 

Level Bonus:
+0.2% chance
+2% damage
Bounder
Attacks have a 15% chance to throw a glaive at one of your Glaivesaws. The glaive will bounce to another Glaivesaw, dealing 250% of attack damage as Lacerate damage to enemies it passes through.

Level Bonus:
+0.6% chance
+6% damage
Lacerate
This tower's attacks and abilities deal Lacerate damage. 50% of Lacerate damage is dealt immediately as Physical damage. 100% of the remaining damage is dealt as Decay damage over 5 seconds. If this effect is reapplied, any remaining damage will be added to the new duration. Damage over time is based on the target's movement speed, with faster movement increasing the damage dealt.

Level Bonus:
+1% damage over time
Download

Toggle Triggers

Header

    globals
        BuffType ashbringer_lacerate_buff
        ProjectileType ashbringer_storm_missile
        ProjectileType ashbringer_bounder_missile
    endglobals
    
    struct Machinations
        integer max
        Effect array e[3]
        boolean array b[3]
        real array x[3]
        real array y[3]
        integer array c[3]
    endstruct
    
    function ashbringer_machinations_setup  takes Tower tower returns nothing
        local Machinations ma = Machinations.create()
        local integer count = 0
        
        set tower.userInt = 0
        set tower.userReal2 = I2R(tower.getUID())
        set ma.max = 3 + 1
        
        loop
            set ma.e[count] = 0
            set ma.b[count] = false
            set ma.c[count] = 3 + 1
            set count = count + 1
            exitwhen count==3
        endloop
        set tower.userInt3 = ma
    endfunction
    
    function ashbringer_lacerate_damage takes Tower tower, Creep target, real damage, real crit returns nothing
        local Buff b
        local real damage_stack
        local real dot_inc = 1.0 + (tower.getLevel() * 0.01)
        local real dot_damage = damage * crit
        
        call tower.doAttackDamage(target, damage * 0.5, crit)
        set b = target.getBuffOfType(ashbringer_lacerate_buff)
        if b != 0 then
            set damage_stack = b.userReal + (dot_damage * 0.5 * dot_inc)
            set ashbringer_lacerate_buff.apply(tower, target, 0).userReal = damage_stack
        else
            set ashbringer_lacerate_buff.apply(tower, target, 0).userReal = (dot_damage * 0.5 * dot_inc)
        endif
    endfunction
    
    function ashbringer_lacerate_dot takes Buff b returns nothing
        local Tower tower = b.getCaster()
        local Creep target = b.getBuffedUnit()
        local real remaining = b.getRemainingDuration()
        local real damage = b.userReal / remaining
        local real damage_tick = damage
        local real movement_relative = GetUnitMoveSpeed(target.getUnit()) / 261
        
        if target.isStunned() then
            set damage_tick = 0
        else
            if remaining<1 then
                set damage = b.userReal
                set damage_tick = damage
            endif
        endif
        
        if damage_tick>0 then
            set b.userReal = b.userReal - damage
            call tower.doCustomAttackDamage(target, damage_tick, 1.0, AttackType.DECAY)
        endif
    endfunction
    
    function ashbringer_bounder_throw takes Tower tower returns nothing
        local Machinations ma = tower.userInt3
        local real damage = tower.getCurrentAttackDamageWithBonus() * (2.5 + (tower.getLevel() * 0.06))
        local integer random = GetRandomInt(0, ma.max)
        local integer bounces = 1
        local Projectile p
        
        if ma.max!=(3+1) then
            set p = Projectile.createLinearInterpolationFromPointToPoint(ashbringer_bounder_missile, tower, 0, 0, tower.getX(), tower.getY(), 110, ma.x[random], ma.y[random], 0, 0)
            set p.userInt = random
            set p.userInt2 = bounces
            set p.userReal = damage
        endif
    endfunction
    
    function ashbringer_bounder_bounce takes Projectile p, Creep target returns nothing
        local Tower tower = p.getCaster()
        local Machinations ma = tower.userInt3
        local Projectile n
        local integer closest = ma.c[p.userInt]
        
        if p.userInt2>0 and closest!=(3+1) then
            call p.avertDestruction()
            call p.startLinearInterpolationToPoint(ma.x[closest], ma.y[closest], 0, 0)
            set p.userInt = closest
            set p.userInt2 = p.userInt2-1
        endif
    endfunction
    
    function ashbringer_bounder_hit takes Projectile p, Unit target returns nothing
        local Tower tower = p.getCaster()
        call ashbringer_lacerate_damage(tower, target, p.userReal, tower.calcAttackMulticrit(0,0,0))
    endfunction
    
    function ashbringer_storm_throw takes Tower tower, Creep target returns nothing 
        local real damage = tower.getCurrentAttackDamageWithBonus() * (0.5 + (tower.getLevel() * 0.02))
        local Projectile p
        
        set p = Projectile.createBezierInterpolationFromUnitToUnit(ashbringer_storm_missile, tower, 1, 1, tower, target, 0, 0.3, 0.17, true)
        set p.userInt = 1
        set p.userInt2 = 20
        set p.userReal = damage
        set p.userReal2 = tower.getX()
        set p.userReal3 = tower.getY()
    endfunction
    
    function ashbringer_storm_bounce takes Projectile p, Creep target returns nothing 
        local Tower tower = p.getCaster()
        local Iterate i
        
        if p.userInt==1 then
            call p.avertDestruction()
            call ashbringer_lacerate_damage(tower, target, p.userReal, tower.calcAttackMulticrit(0,0,0))
            call p.startBezierInterpolationToPoint(p.userReal2, p.userReal3, 100, 0, 0.3, 0.17)
            set p.userInt = 0
        elseif p.userInt2>0 then
            set i = Iterate.overUnitsInRange(tower, TARGET_TYPE_CREEPS, p.userReal2, p.userReal3, 1000)
            set target = i.nextRandom()
            if target!=0 then
                call p.avertDestruction()
                call p.startBezierInterpolationToUnit(target, 0, 0.3, 0.17, true)
                set p.userInt = 1
                set p.userInt2 = p.userInt2 - 1
                call i.destroy()
            endif
        endif
    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
        set  ashbringer_lacerate_buff = BuffType.create(5, 0, false)
        call ashbringer_lacerate_buff.setBuffIcon('@@1@@')
        call ashbringer_lacerate_buff.addPeriodicEvent(ashbringer_lacerate_dot, 1.0)
        
        set ashbringer_storm_missile = ProjectileType.createInterpolate("Abilities\\Weapons\\SentinelMissile\\SentinelMissile.mdl", 900)
        call ashbringer_storm_missile.setEventOnInterpolationFinished(ProjectileTargetEvent.ashbringer_storm_bounce)
        
        set ashbringer_bounder_missile = ProjectileType.createInterpolate("Abilities\\Weapons\\GlaiveMissile\\GlaiveMissile.mdl", 2000)
        call ashbringer_bounder_missile.enableCollision(ProjectileTargetEvent.ashbringer_bounder_hit, 100, TARGET_TYPE_CREEPS, false)
        call ashbringer_bounder_missile.setEventOnInterpolationFinished(ProjectileTargetEvent.ashbringer_bounder_bounce)
    endfunction

On Attack

ONATTACK_chance: 1.0 ONATTACK_chanceLevelAdd: 0.0
function onAttack takes Tower tower returns nothing
    local real bounder_chance = 0.15 + (tower.getLevel() * 0.006)
    
    if tower.calcChance(bounder_chance) then
        call ashbringer_bounder_throw(tower)
    endif
endfunction

On Damage

ONDAMAGE_chance: 1.0 ONDAMAGE_chanceLevelAdd: 0
function onDamage takes Tower tower returns nothing
    local Creep target = Event.getTarget()
    local real storm_chance = 0.05 + (tower.getLevel() * 0.002)
    
    call ashbringer_lacerate_damage(tower, target, tower.getCurrentAttackDamageWithBonus(), tower.calcAttackMulticrit(0,0,0))
    set Event.damage = 0
    
    if tower.calcChance(storm_chance) then
        call ashbringer_storm_throw(tower, target)
    endif
endfunction

On Spell Cast

function onSpellCast takes Tower tower returns nothing
    local Machinations ma = tower.userInt3
    local real target_x = GetSpellTargetX()
    local real target_y = GetSpellTargetY()
    local real dist1
    local real dist2 = 0
    local integer subcount
    local integer max_mach = 3
    local integer count = 0
    local integer sel = max_mach + 1
    local integer closest
    
    loop
        if ma.b[count]==false then
            set ma.b[count] = true
            set ma.e[count] = Effect.createAnimatedScaled("Abilities\\Weapons\\BloodElfSpellThiefMISSILE\\BloodElfSpellThiefMISSILE.mdl", target_x+20, target_y, 40.0, 0.0, 1.45)
            call ma.e[count].setAnimationSpeed(2.0)
            call ma.e[count].setScale(2.0)
            set ma.x[count] = target_x
            set ma.y[count] = target_y
            if count==0 then
                set ma.c[count] = sel
            elseif count==1 then
                set ma.c[count-1] = 1
                set ma.c[count] = 0
            else
                set ma.c[count] = sel
            endif
            set ma.max = count
            
            set sel = count
            set count = max_mach
        else
        endif
        set count = count + 1
        
        exitwhen count>=max_mach
    endloop
    
    if sel>max_mach then
        set count = 0
        call ma.e[0].destroy()
        loop
            if count<(max_mach-1) then
                set ma.b[count] = ma.b[count+1]
                set ma.e[count] = ma.e[count+1]
                set ma.x[count] = ma.x[count+1]
                set ma.y[count] = ma.y[count+1]
                set ma.c[count] = sel
            endif
            set count = count + 1
            
            exitwhen count==max_mach
        endloop
        
        set ma.b[max_mach-1] = true
        set ma.e[max_mach-1] = Effect.createAnimatedScaled("Abilities\\Weapons\\BloodElfSpellThiefMISSILE\\BloodElfSpellThiefMISSILE.mdl", target_x+20, target_y, 40.0, 0.0, 1.45)
        call ma.e[max_mach-1].setAnimationSpeed(2.0)
        call ma.e[max_mach-1].setScale(2.0)
        set ma.x[max_mach-1] = target_x
        set ma.y[max_mach-1] = target_y
        set ma.c[max_mach-1] = sel
        
        set sel = 0
    endif

    if ma.max>1 then
        set count = 0
        loop
            if ma.b[count]==true then
                set subcount = 0
                set closest = max_mach + 1
                set dist2 = 0
                loop
                    if ma.b[subcount]==true and count!=subcount then
                        set dist1 = SquareRoot(((ma.x[subcount]-ma.x[count]) * (ma.x[subcount]-ma.x[count])) + ((ma.y[subcount]-ma.y[count]) * (ma.y[subcount]-ma.y[count])))
                        
                        if dist2==0 then
                            set dist2 = dist1
                        endif
                        
                        if dist1<=dist2 and dist1>=50 then
                            set dist2 = dist1
                            set closest = subcount
                        endif
                    endif
                    set subcount = subcount + 1
                    
                    exitwhen subcount==max_mach
                endloop
                set ma.c[count] = closest
            endif
            set count = count + 1
            
            exitwhen count==max_mach
        endloop
    endif
    
    set tower.userInt3 = ma
endfunction

On Tower Creation

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

On Tower Destruction

function onDestruct takes Tower tower returns nothing
    local Machinations ma = tower.userInt3
    local integer max_mach = 3
    local integer count = max_mach
    
    loop
        set count = count - 1
        if ma.b[count] == true then
            call ma.e[count].destroy()
        endif
        
        exitwhen count==0
    endloop
endfunction

Periodic

PERIODIC_period: 1.0
function periodic takes Tower tower returns nothing
    local Machinations ma = tower.userInt3
    local Iterate i
    local integer count = 0
    local integer max_mach = 3
    local real damage = tower.getCurrentAttackDamageWithBonus() * (0.5 + (tower.getLevel() * 0.01))
    local Creep next
    
    loop
        if ma.b[count] == true then
            set i = Iterate.overUnitsInRange(tower, TARGET_TYPE_CREEPS, ma.x[count], ma.y[count], 150)
            set next = i.next()
            loop
                exitwhen next == 0
                call Effect.createSimpleOnUnit("Abilities\\Spells\\Other\\Stampede\\StampedeMissileDeath.mdl", next, "origin").setLifetime(2.0)
                call ashbringer_lacerate_damage(tower, next, damage, tower.calcAttackMulticrit(0,0,0))
                set next = i.next()
            endloop
            //call i.destroy()
        endif
        
        set count = count + 1
        exitwhen count==max_mach
    endloop
endfunction