Vol'jin the Witch Doctor v1
4600
ID:
114
Family ID:
Author:
SirCoqaLot.
Rarity:
unique
Element:
astral
Attack Type:
Elemental
Attack Range:
800
Attack CD:
2
Damage:
4756-4756
Mana:
40
Mana regen:
1.5
Status:
Approved

Description:

"Try out my Voodoo maaan."                              credits to der_kleine_Tomy
Specials:
+3% attackspeed/lvl
+8% damage/lvl
Maledict
Vol'jin jinxes all units in 800 range around him. Targets caught by the jinx are dealt 15% of the damage they received as spell damage after 8 seconds. Maledict stacks, with each stack adding 3.5% additional damage. If Maledict is purged it deals double damage. This ability is unaffected by Buff Duration. 

Level Bonus:
+0.14% damage per stack

AC_TYPE_OFFENSIVE_IMMEDIATE
 30, 800 range, 5s cooldown
Serpent Ward
Vol'jin has an 18% chance on attack to summon 1 of 2 Serpent Wards to assist him. Each ward lasts 6 seconds modified by this tower's buff duration, deals 20% of Vol'jins attack damage and has Vol'jins current attackspeed at cast. Each Ward attacks a random target in 800 range and has a 35% chance to stack 'Maledict' on attack. Wards can not be resummoned and their duration cannot be refreshed. 

Level Bonus:
+0.2% attackdamage
+0.1 seconds duration
+0.28% chance to summon a ward
+1 maximum ward at level 15 and 25
Purify
Whenever Vol ' jin deals damage he purges all buffs and debuffs from his target, increasing his damage dealt on that attack by 12% for each purged effect. This ability has a 4 second cooldown.

Level Bonus:
-0.04 seconds cooldown
+0.16% damage per purged effect
Download

Toggle Triggers

Autocast

AUTOCAST_cooldown: 5 AUTOCAST_autoRange: 800 AUTOCAST_manacost: 30 AUTOCAST_range: 800 AUTOCAST_targetType: 0 AUTOCAST_numBuffsBeforeIdle: 0 caster_art: target_art: AUTOCAST_autocastType: AC_TYPE_OFFENSIVE_IMMEDIATE AUTOCAST_buffType: 0 AUTOCAST_isExtended: true AUTOCAST_targetSelf: false
private function onAutocast takes Tower tower returns nothing
    local Iterate it = Iterate.overUnitsInRangeOfUnit(tower,TARGET_CREEPS,tower,800)
    local Unit u
    loop
        set u = it.next()
        exitwhen u == 0
        call ApplyMaledict(tower,u,true)
    endloop
endfunction

Header

    globals
        BuffType sir_voljin_debuff
        ProjectileType sir_voljin_projectile
        hashtable voljin_hashtable
        // 0 = Ward 1
        // 1 = Duration
        // 2/3 = Position(x/y)
        // 4 = Ward 2
        // ...
    endglobals
    
    function damageEvent takes Buff b returns nothing
        set b.userReal = b.userReal + Event.damage
    endfunction
    
    function expireEvent takes Buff b returns nothing
        call b.getCaster().doSpellDamage(b.getBuffedUnit(),(0.15+(0.035+0.0014*b.getCaster().getLevel())*b.getLevel())*R2I(b.userReal),b.getCaster().calcSpellCritNoBonus())
    endfunction
    
    function purgeEvent takes Buff b returns nothing
        call b.getCaster().doSpellDamage(b.getBuffedUnit(),(0.3+(0.07+0.0028*b.getCaster().getLevel())*b.getLevel())*R2I(b.userReal),b.getCaster().calcSpellCritNoBonus())
    endfunction
    
    function ApplyMaledict takes Tower caster, Unit target, boolean B returns nothing
        local Buff b = target.getBuffOfType(sir_voljin_debuff)
        local real duration = caster.getProp_BuffDuration()
        if B == true and b == 0 then
            set sir_voljin_debuff.applyAdvanced(caster, target,1, 0, 8.0/duration).userReal = 0.0
        elseif (b != 0 and B == false and caster.calcChance(0.35)) or (b != 0 and B == true) then
            call sir_voljin_debuff.applyAdvanced(caster, target, b.getLevel() + 1, 0, 8.0/duration)
        endif
    endfunction
    
    function voljin_hit takes Projectile p, Unit hit returns nothing
        local Tower tower = p.getCaster()
        call tower.doAttackDamage(hit,tower.getCurrentAttackDamageWithBonus() * (0.2+tower.getLevel()*0.002),tower.calcAttackMulticrit(0,0,0))
        call ApplyMaledict(tower,hit,false)
    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 voljin_hashtable = InitHashtable()
        
        set sir_voljin_debuff = BuffType.create(0,0,false)
        call sir_voljin_debuff.setBuffIcon('@@0@@')
        call sir_voljin_debuff.addEventOnDamaged(damageEvent,1,0)
        call sir_voljin_debuff.setEventOnExpire(expireEvent)
        call sir_voljin_debuff.setEventOnPurge(purgeEvent)
    
        set sir_voljin_projectile=ProjectileType.create("Abilities\\Weapons\\SerpentWardMissile\\SerpentWardMissile.mdl",10.0,1200.0)
        call sir_voljin_projectile.enableHoming(ProjectileTargetEvent.voljin_hit,0.0)
    endfunction

On Attack

ONATTACK_chance: 0.18 ONATTACK_chanceLevelAdd: 0.0028
function onAttack takes Tower tower returns nothing
    local integer level = tower.getLevel()
    local unit towerUnit = tower.getUnit()
    local real attackspeed = tower.getCurrentAttackspeed()
    local PeriodicEvent periodicEvent = tower.userInt
    local real towerUnitZ = GetUnitFlyHeight(towerUnit)
    local integer counter = 0
    local integer maxWards = 2
    local Effect e
    local real duration
    local real x
    local real y
    
    if level == 25 then
        set maxWards = 4
    elseif level >= 15 then
        set maxWards = 3
    endif
    
    loop
        // Check whether all wards already exist, if not create one
        if not HaveSavedInteger(voljin_hashtable, tower, counter) then
            set x = LoadReal(voljin_hashtable, tower, counter + 2)
            set y = LoadReal(voljin_hashtable, tower, counter + 3)
            set e = Effect.createAnimated("units\\orc\\SerpentWard\\SerpentWard.mdl", x, y, towerUnitZ - 20, -(45.0 + 90.0 * (counter / 4)))
            call e.setScale(0.4)
            set duration = (6.0+tower.getLevel()*0.1) * tower.getProp_BuffDuration()
            
            call SaveInteger(voljin_hashtable, tower, counter, e) // Save the effect
            call SaveReal(voljin_hashtable, tower, counter + 1, duration) // Save the duration
            
            set tower.userInt2 = tower.userInt2 + 1 // Save the amount of wards
            // The first ward has been created => Start the Periodic Event
            if tower.userInt2 == 1 then
                call periodicEvent.enableAdvanced(attackspeed, false)
                set tower.userReal = attackspeed // Save the periodic interval
            endif
            
            exitwhen true // Exit
        endif
        set counter = counter + 4 // Move to the next ward
        exitwhen counter > (maxWards * 4 - 4)
    endloop
    
    
    set towerUnit = null
endfunction

On Damage

ONDAMAGE_chance: 1.0 ONDAMAGE_chanceLevelAdd: 0.0
function onDamage takes Tower tower returns nothing
    local Unit creep = Event.getTarget()
    local real damage = Event.damage
    local integer numPurgedBuffs = 0
    
    // Remove buffs (positive and negative buffs) and count them
    if tower.userInt3 <= Game.getGameTime() then
        set tower.userInt3 = Game.getGameTime()+100-tower.getLevel() // adding the cd
        loop
            exitwhen not (creep.purgeBuff(true) or creep.purgeBuff(false))
            set numPurgedBuffs = numPurgedBuffs + 1
        endloop
        
        set damage = damage*(1+numPurgedBuffs*(0.12+tower.getLevel()*0.0016)) // 12% damage 
        set Event.damage = damage
        if numPurgedBuffs != 0 then
            call tower.getOwner().displaySmallFloatingText(I2S(R2I(damage)),tower,255,150,255,0)
        endif
    endif
endfunction

On Tower Creation

function onCreate takes Tower tower returns nothing
    local real towerX = tower.getX()
    local real towerY = tower.getY()
    
    set tower.userInt = 0 // Contains the Periodic Event
    set tower.userInt2 = 0 // Stores the amount of wards
    set tower.userReal = 0 // Stores the periodic interval
    set tower.userInt3 = Game.getGameTime()-100 // stores the cooldown of purify
    // Ward 1
    call SaveReal(voljin_hashtable, tower,  2, towerX + 38)
    call SaveReal(voljin_hashtable, tower,  3, towerY - 53)
    // Ward 2
    call SaveReal(voljin_hashtable, tower,  6, towerX - 43)
    call SaveReal(voljin_hashtable, tower,  7, towerY - 45)
    // Ward 3
    call SaveReal(voljin_hashtable, tower,  10, towerX - 33)
    call SaveReal(voljin_hashtable, tower,  11, towerY + 38)
    // Ward 4
    call SaveReal(voljin_hashtable, tower, 14, towerX + 35)
    call SaveReal(voljin_hashtable, tower, 15, towerY + 38)
endfunction

On Tower Destruction

function onDestruct takes Tower tower returns nothing
    local integer counter = 0
    loop
        if HaveSavedInteger(voljin_hashtable, tower, counter) then
            call Effect(LoadInteger(voljin_hashtable, tower, counter)).destroy()
        endif
        set counter = counter + 4
        exitwhen counter > 12
    endloop
    call FlushChildHashtable(voljin_hashtable, tower)
endfunction

Periodic

PERIODIC_period: 0.1
function periodic takes Tower tower returns nothing
    local Effect e
    local Unit u
    local Projectile p
    local PeriodicEvent periodicEvent = tower.userInt
    local Iterate it
    local Unit array targets
    local integer numTargets = 0
    local integer counter = 0
    local real duration
    local real facing
    local real x
    local real y
    
    // If it's the first time this event fires
    if periodicEvent == 0 then
        set tower.userInt = Event.getCurrentPeriodicEvent() // Save the event
        call Event.getCurrentPeriodicEvent().disable() // Disable it
        return
    endif
 
    // Get all targets in range
    set it = Iterate.overUnitsInRangeOfCaster(tower,TARGET_CREEPS,800)
    loop
        set u = it.next()
        exitwhen u == 0
        set targets[numTargets] = u
        set numTargets = numTargets + 1
    endloop
    
    loop
        // Is there a ward ?
        if HaveSavedInteger(voljin_hashtable, tower, counter) then
            set e = LoadInteger(voljin_hashtable, tower, counter) // Load ward effect
            set u = targets[GetRandomInt(0, numTargets - 1)] // Get a random target
            set duration = LoadReal(voljin_hashtable, tower, counter + 1) - tower.userReal // Set duration to duration - periodic interval
            if duration > 0 then // Is there duration remaining?
                if u != 0 then // Is there are unit which can be attacked ?
                    // Load position
                    set x = LoadReal(voljin_hashtable, tower, counter + 2)
                    set y = LoadReal(voljin_hashtable, tower, counter + 3)
                    // Calculate the angle between the ward and the target
                    set facing = Atan2(GetUnitY(u.getUnit()) - y, GetUnitX(u.getUnit()) - x) * bj_RADTODEG
                    call e.setFacing(facing) // Set facing
                    call e.setAnimation("attack") // Play attack animation
                    // Shoot prohectile
                    set p = Projectile.createFromPointToUnit(sir_voljin_projectile, tower, 1.0, 1.0, x, y, 147.0, u, true, false, false)
                    call p.setScale(0.4)
                    call e.queueAnimation("stand") // Play the stand animation again
                endif
                // Save the remaining duration
                call SaveReal(voljin_hashtable, tower, counter + 1, duration)
            else // No more duration
                // Remove the ward effect from the hashtable
                call RemoveSavedInteger(voljin_hashtable, tower, counter)
                call e.destroy() // Destroy the ward
                set tower.userInt2 = tower.userInt2 - 1 // Decrease the ward counter
            endif
        endif
        set counter = counter + 4 // Next ward
        // Up to 4 wards with each taking 4 storage places in the hashtable starting at 0
        // => 4 wards * 4 places - 4
        exitwhen counter > (4 * 4 - 4)
    endloop
    // Disable the event
    call periodicEvent.disable()
    // Are there any wards?
    if tower.userInt2 > 0 then
        // Activate the event
        set tower.userReal = tower.getCurrentAttackspeed()
        call periodicEvent.enableAdvanced(tower.getCurrentAttackspeed() ,false)
    endif
endfunction
Eredar Diabolist v1
4600
ID:
133
Family ID:
Author:
SirCoqaLot.
Rarity:
unique
Element:
darkness
Attack Type:
Essence
Attack Range:
890
Attack CD:
3
Damage:
2880-2879
Status:
Approved

Description:

Daemonic entity that will stun allied towers and temporarily steal their damage for itself and will threaten nearby units by occasionalyl releasing shadowboltwaves. Also suppresses lifeforce killing too weak enemies instantly.
Siphon Essence
Casts a buff on a nearby tower, if that tower tries to attack in the next 5 seconds it will be stunned for 2.5 seconds and this tower will deal [stunned tower's DPS x 3] as essence damage to the target of the buffed tower. 

Level Bonus:
-0.02 seconds stun duration

AC_TYPE_ALWAYS_BUFF
 0, 400 range, 1.5s cooldown
Shadowbolt Wave
Every autocast of this tower has a 20% chance to release 12 shadowbolts. Every shadowbolt flies towards a random target in 1000 range and deals 1700 spell damage. This Spell has a 40% chance to trigger if the last autocast released a shadowboltwave. 

Level Bonus:
+34 spell damage
Slow Decay - Aura
Non Boss units in 750 range around the Eredar Diabolist with less then 5.5% of their healthpoints will be killed.

Level Bonus:
+0.06% healthpoints needed for instantkill
Download

Toggle Triggers

Autocast

AUTOCAST_cooldown: 1.5 AUTOCAST_autoRange: 400 AUTOCAST_manacost: 0 AUTOCAST_range: 400 AUTOCAST_targetType: TARGET_TYPE_TOWERS AUTOCAST_numBuffsBeforeIdle: 1 caster_art: target_art: AUTOCAST_autocastType: AC_TYPE_ALWAYS_BUFF AUTOCAST_buffType: 0 AUTOCAST_isExtended: true AUTOCAST_targetSelf: false
private function onAutocast takes Tower tower returns nothing
    local Tower target = Event.getTarget()
    call sir_eredar_buff.apply(tower,target,1)
    call rollForShadowWave(tower)
endfunction

Header

    globals
    //@import
    ProjectileType sir_eredar_attackProj
    //@import
    ProjectileType sir_eredar_waveProj
    //@import
    BuffType sir_eredar_buff
    BuffType sir_eredar_aura
    endglobals
    
    //@import
    function rollForShadowWave takes Tower t returns nothing
    endfunction
    
    public function sir_creepkillaura takes Buff b returns nothing
        if b.getBuffedUnit().getLifePercent() <= 0.055+b.getCaster().getLevel()*0.0006 and b.getBuffedUnit().getSize() < SIZE_BOSS then
            call b.getCaster().killInstantly(b.getBuffedUnit()) 
            call SFXAtUnit("Abilities\\Spells\\Undead\\DeathCoil\\DeathCoilSpecialArt.mdl",b.getBuffedUnit().getUnit()) 
        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 sir_eredar_aura = BuffType.createAuraEffectType(false)
        call sir_eredar_aura.setBuffIcon('@@0@@')
        call sir_eredar_aura.addPeriodicEvent(sir_creepkillaura,1.0)
   endfunction

On Tower Creation

function onCreate takes Tower tower returns nothing
    set tower.userInt = 0 // stores whether last autocast triggered shadowbolts
    set tower.userInt2 = 12 // stores num shadowbolts to release
    set tower.userReal = 1700 // stores base shadowbolt damage
endfunction

Tower Aura

AURA_powerAdd: 0 AURA_auraEffect: sir_eredar_aura AURA_levelAdd: 0 AURA_power: 0 AURA_targetType: TARGET_TYPE_CREEPS AURA_targetSelf: false AURA_level: 0 AURA_auraRange: 750
Crimson Wyrm v2
4800
ID:
139
Family ID:
Author:
SirCoqaLot.
Rarity:
unique
Element:
fire
Attack Type:
Elemental
Attack Range:
950
Attack CD:
2
Damage:
90-10099
Status:
Approved

Description:

Ancient and greedy Wyrm which takes away most of your goldgain.
Flaming Inferno
Every 7th-11th attack releases 3 fireballs that fly towards random targets in 950 range, dealing 3750 spelldamage in 250 AoE around the target on impact.

Level Bonus:
+150 spelldamage
-1 minimum and maximum attack needed at levels 15 and 25
+1 fireball at level 10
+5% bonus crit chance at levels 5 and 20
Dragon's Hoard
Whenever the Crimson Wyrm kills a creep it hoards 75% of the bounty. The hoard has a maximum capacity of 90000 gold and grants [gold hoarded / 50]% spelldamage and base attackdamage. 

Hint: This ability is modified by both the creep's and this tower's bounty ratios.
Download

Toggle Triggers

Header

                globals
        MultiboardValues sir_wyrm_bonus
        ProjectileType sir_wyrm_projectile
    endglobals
    
    // function being called whenever the hoard is updated
    function sir_update takes Tower tower, real value returns nothing
        call tower.modifyProperty(MOD_DAMAGE_BASE_PERC, -tower.userReal / 5000)
        call tower.modifyProperty(MOD_SPELL_DAMAGE_DEALT, -tower.userReal / 5000)
        set tower.userReal = tower.userReal + value
        call tower.modifyProperty(MOD_DAMAGE_BASE_PERC, tower.userReal / 5000)
        call tower.modifyProperty(MOD_SPELL_DAMAGE_DEALT, tower.userReal / 5000)
    endfunction
    
    private function sir_wyrm_hit takes Projectile p, Unit u returns nothing
        local Tower t = p.getCaster()
        local integer l = t.getLevel()
        local real critmod 
        
        if l >= 20 then 
            set critmod = 0.1
        elseif l >= 5 and l < 20 then
            set critmod = 0.05
        else 
            set critmod = 0
        endif
        
        call t.doSpellDamageAoE(p.x,p.y,250,3750+l*150,t.calcSpellCrit(critmod,0),0)
    endfunction
    
    function releaseFireballs takes Tower tower, integer balls returns nothing
        local integer level = tower.getLevel()
        local Iterate it = Iterate.overUnitsInRangeOfCaster(tower,TARGET_CREEPS,950)
        local Unit target
        local Unit last = 0
        loop
            set target = it.nextRandom()
            exitwhen target == 0
            call Projectile.createBezierInterpolationFromUnitToUnit(sir_wyrm_projectile,tower,1,1,tower,target,0,GetRandomReal(-0.35,0.35),GetRandomReal(0.17,0.4),true).setScale(2.0)// gives the fireballs a slightly random trajectory
            set balls = balls - 1
            set last = target
            exitwhen balls == 0
        endloop
        if target != 0 then
            //Targets remain, so all balls must've been fired.
            call it.destroy()
        elseif balls > 0 then
            if last != 0 then
                //Shoot remaining balls at last target. (This is ALRIGHT, because there is a max of 4 balls all up.
                //So worst case scenario, there are two creeps in range: one of them is hit with one fireball, and the other with three.)
                loop
                    call Projectile.createBezierInterpolationFromUnitToUnit(sir_wyrm_projectile,tower,1,1,tower,last,0,GetRandomReal(-0.35,0.35),GetRandomReal(0.17,0.4),true).setScale(2.0)// gives the fireballs a slightly random trajectory
                    set balls = balls - 1
                    exitwhen balls == 0
                endloop
            else
                set tower.userInt = 0 //(shoot all fireballs on next attack.)
            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 sir_wyrm_bonus = MultiboardValues.create(3)
        call sir_wyrm_bonus.setKey(0,"Gold Hoarded")
        call sir_wyrm_bonus.setKey(1,"Bonus Damage")
        call sir_wyrm_bonus.setKey(2,"Atks to Fireballs")
        set sir_wyrm_projectile = ProjectileType.createInterpolate("Abilities\\Weapons\\FireBallMissile\\FireBallMissile.mdl",700)
        call sir_wyrm_projectile.setEventOnInterpolationFinished(sir_wyrm_hit)
    endfunction
        

On Attack

ONATTACK_chance: 1.0 ONATTACK_chanceLevelAdd: 0.0
function onAttack takes Tower tower returns nothing
            
    local integer level = tower.getLevel()
    
    // check if 0 attacks remain till fireballs
    if tower.userInt > 0 then                  
        set tower.userInt = tower.userInt - 1
    else    
        // setting minimum number of attacks before next fireballs
        if level == 25 then
            set tower.userInt = 5
        elseif level >= 15 then
            set tower.userInt = 6
        else
            set tower.userInt = 7
        endif
        // set +0,+1 or +2 attacks and release bolts afterwards
        set tower.userInt = tower.userInt + GetRandomInt(0,4) 
        // setting the number of fireballs
        if level >= 10 then
            call releaseFireballs(tower, 4)
        else
            call releaseFireballs(tower, 3)
        endif
        
    endif
        
endfunction

On Kill

function onKill takes Tower tower returns nothing
            
    local Creep creep() = Event.getTarget()
    local integer level = tower.getLevel()
    local real value = 0.75*creep.getBaseBountyValue()*creep.getProp_BountyGranted()*tower.getProp_BountyReceived()
    local real hoardSize = 90000
    if tower.userReal >= hoardSize then
        set value = 0
    elseif tower.userReal + value > hoardSize then
        set value = hoardSize-tower.userReal
    endif
    if value != 0 then       
        call sir_update(tower,value)
        call tower.getOwner().giveGold(-value,tower.getUnit(), false, false)
        call SFXAtUnit("Abilities\\Spells\\Other\\Transmute\\PileofGold.mdl",tower.getUnit())
    endif
        
endfunction

On Tower Creation

function onCreate takes Tower tower returns nothing
            
    local Tower preceding = Event.getPrecedingTower()
    set tower.userReal = 0
    if preceding.getUnitType() == tower.getUnitType() then //This is kind of obsolete, but whatever; can't use family because no family
        call sir_update(tower,preceding.userReal)   //Somebody might replace this tower with this tower
    endif
    set tower.userInt = 9// mediocre cd for first wave of fireballs
        
endfunction

On Tower Details

goldcost: 0
function onTowerDetails takes Tower tower returns MultiboardValues
            
    call sir_wyrm_bonus.setValue(0,formatFloat(tower.userReal,0))
    call sir_wyrm_bonus.setValue(1,formatFloat(tower.userReal/100,0)+"%")
    call sir_wyrm_bonus.setValue(2,I2S(tower.userInt))
    return sir_wyrm_bonus
        
endfunction
Dutchman's Grave v1
5000
ID:
414
Family ID:
Author:
cedi
Rarity:
unique
Element:
darkness
Attack Type:
Physical
Attack Range:
2000
Attack CD:
2.5
Damage:
7138-7138
Status:
Approved

Description:

An inscription is written on the grave: "The admiral defeated the Dutchman and its crew near this island."
Soul Storm
When this spell is activated 2 souls will be released every 0.3 seconds. When a soul collides with a creep it deals 14000 spell damage. When a soul damages a creep, its damage is reduced by 50%.

AC_TYPE_NOAC_IMMEDIATE
 0, 600.00 range, 5.00s cooldown
Cannon
The Dutchman attacks a random creep in 800 range, dealing the tower's attack damage in 250 AoE around the target on hit. Uses the tower's attackspeed.
Soul Attack
Every 5 seconds the Dutchman attacks a random creep in 1200 range with a collected soul. Deals 14000 spell damage to the target.

Level Bonus:
+1400 spell damage
Panic
Whenever the Dutchman kills a creep, it collects its soul. All creeps in a range of 300 around the killed creep start to panic. They have only one thing in mind: RUN!. They don ' t care about their defense and their armor is reduced by 25, but they run 20% faster. This effect lasts 10 seconds.

Level Bonus:
-1 armor
-0.2% movement speed
Download

Toggle Triggers

Autocast

AUTOCAST_cooldown: 5.00 AUTOCAST_autoRange: 600.00 AUTOCAST_manacost: 0 AUTOCAST_range: 600.00 AUTOCAST_targetType: 0 AUTOCAST_numBuffsBeforeIdle: 0 caster_art: target_art: AUTOCAST_autocastType: AC_TYPE_NOAC_IMMEDIATE AUTOCAST_buffType: 0 AUTOCAST_isExtended: false AUTOCAST_targetSelf: true
private function onAutocast takes Tower tower returns nothing
    set Dutchman(tower.userInt).soulstorm = true
endfunction

Header

    globals
        ProjectileType Proj
        ProjectileType Soul
        ProjectileType NAttack
        Cast SAttack
        BuffType Panic
        MultiboardValues mbvals
    endglobals
    
    struct Dutchman
        Projectile p = 0
        integer uid = 0
        integer souls = 0
        real nattack = 2.00
        real sattack = 5.00
        real reorder = 2.00
        real soultime = 0.30
        Unit target = 0
        boolean soulstorm = false
        
        method onDestroy takes nothing returns nothing
            call .p.destroy()
        endmethod
        
        static method create takes Projectile p, Unit target returns thistype
            local thistype this = thistype.allocate()
            set .p = p
            set .target = target
            set .uid = target.getUID()
            
            set .nattack = p.getCaster().getCurrentAttackspeed()
            return this
        endmethod
        
    endstruct
    
    function Storm takes Projectile p, Dutchman d, Unit tower returns nothing
        local Projectile p2
        if d.souls >= 2 then
            set d.souls = d.souls - 2
            set p2 = Projectile.create( Soul, tower, 1.00, tower.calcSpellCritNoBonus(), p.x, p.y, p.z, 0.00 )
            set p2.userReal = 14000.00
            set p2 = Projectile.create( Soul, tower, 1.00, tower.calcSpellCritNoBonus(), p.x, p.y, p.z, 180.00 )
            set p2.userReal = 14000.00
        else
            set d.soulstorm = false
        endif
    endfunction
    
    function NAttackHit takes Projectile p, Unit target returns nothing
        local Tower T = p.getCaster()
        call T.doAttackDamageAoEUnit(target, 250, T.getCurrentAttackDamageWithBonus(), T.calcAttackMulticrit(0,0,0),0)
    endfunction
    
    function NAttackFunc takes Projectile p, Unit tower returns nothing
        local Iterate I = Iterate.overUnitsInRange( tower, TARGET_CREEPS, p.x, p.y, 800.00 )
        local Unit U = I.nextRandom()
        if U != 0 then
            call I.destroy()
            call Projectile.createLinearInterpolationFromPointToUnit(NAttack,tower,1,1,p.x,p.y,p.z,U,0.4,true)
        endif
    endfunction
    
    function SAttackFunc takes Projectile p, Dutchman d, Unit tower returns nothing
        local Iterate I
        local Unit U
        if d.souls >= 1 then
            set I = Iterate.overUnitsInRange( tower, TARGET_CREEPS, p.x, p.y, 1200.00 )
            loop
                set U = I.nextRandom()
                exitwhen U == 0
                if not U.isImmune() then
                    set d.souls = d.souls - 1
                    call SAttack.targetCastFromPoint( tower, U, p.x, p.y, 14000.00 + I2R( tower.getLevel() ) * 1400.00, tower.calcSpellCritNoBonus())
                    call I.destroy()
                    return
                endif
            endloop
        endif
    endfunction
    
    function Periodic takes Projectile p returns nothing
        local Unit tower = p.getCaster()
        local Dutchman d = p.userInt
        if IsUnitType( d.target.getUnit(), UNIT_TYPE_DEAD ) or d.target == 0 or d.target.getUID() != d.uid then
            call p.setHomingTarget( tower )
            set d.target = tower
            set d.uid = tower.getUID()
        endif
        set d.nattack = d.nattack - 0.1
        if d.nattack <= 0.00 then
            set d.nattack = d.nattack + tower.getCurrentAttackspeed()
            call NAttackFunc( p, tower )
        endif
        set d.sattack = d.sattack - 0.1
        if d.sattack <= 0.00 then
            set d.sattack = 5.00
            call SAttackFunc( p, d, tower )
        endif
        set d.reorder = d.reorder - 0.1
        if d.reorder <= 0.00 then
            set d.reorder = 2.00
            call p.setHomingTarget( d.target )
        endif
        if d.soulstorm then
            set d.soultime = d.soultime - 0.1
            if d.soultime <= 0.00 then
                set d.soultime = 0.3
                call Storm( p, d, tower )
            endif
        endif
    endfunction
    
    function Hit takes Projectile p, Unit target returns nothing
        call p.avertDestruction()
    endfunction
    
    function SoulHit takes Projectile p, Unit target returns nothing
        call SFXOnUnit( "Abilities\\Spells\\Undead\\DeathCoil\\DeathCoilSpecialArt.mdl", target.getUnit(), "chest" )
        call p.doSpellDamage( target, p.userReal )
        set p.userReal = p.userReal * 0.5
    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 m = Modifier.create()
        set Proj = ProjectileType.create( "units\\creeps\\UndeadDestroyerShip\\UndeadDestroyerShip.mdl", 999999.00, 550.00 )
        call Proj.enablePeriodic( Periodic, 0.10 )
        call Proj.enableHoming( Hit, 4.00 )
        set SAttack = Cast.create( '@@0@@', "acidbomb", 5.00 )
        set Panic = BuffType.create( 10.00, 0.00, false )
        call Panic.setBuffIcon( '@@2@@' )
        call m.addModification( MOD_ARMOR, -25.00, -1.00 )
        call m.addModification( MOD_MOVESPEED, 0.20, -0.002 )
        call Panic.setBuffModifier( m )
        set NAttack = ProjectileType.createInterpolate("Abilities\\Weapons\\BoatMissile\\BoatMissile.mdl", 900.00 ) 
        call NAttack.setEventOnInterpolationFinished(NAttackHit)
        set Soul = ProjectileType.create( "Abilities\\Spells\\Undead\\Possession\\PossessionMissile.mdl", 6.00, 300.00 )
        call Soul.setAcceleration( 10.00 )
        call Soul.enableCollision( SoulHit, 100.00, TARGET_CREEPS, false )
        call Soul.setStartRotation( 6.00 )
        set mbvals = MultiboardValues.create( 1 )
        call mbvals.setKey( 0, "Souls" )
    endfunction

On Attack

ONATTACK_chance: 1.0 ONATTACK_chanceLevelAdd: 0.0
function onAttack takes Tower tower returns nothing
    local Dutchman d = tower.userInt
    set d.target = Event.getTarget()
    set d.uid = d.target.getUID()
    call d.p.setHomingTarget( d.target )
endfunction

On Damage

ONDAMAGE_chance: 1.0 ONDAMAGE_chanceLevelAdd: 0.0
function onDamage takes Tower tower returns nothing
    set Event.damage = 0
endfunction

On Kill

function onKill takes Tower tower returns nothing
    local Iterate I = Iterate.overUnitsInRangeOfUnit( tower, TARGET_CREEPS, Event.getTarget(), 300.00 )
    local Unit U
    local integer lvl = tower.getLevel()
    local Dutchman d = tower.userInt
    set d.souls = d.souls + 1
    call SFXAtUnit( "Abilities\\Spells\\Items\\AIso\\AIsoTarget.mdl", Event.getTarget().getUnit() )
    loop
        set U = I.next()
        exitwhen U == 0
        call Panic.apply( tower, U, lvl )
    endloop
endfunction

On Tower Creation

function onCreate takes Tower tower returns nothing
    local Projectile p = Projectile.createFromUnitToUnit( Proj, tower, 1.00, tower.calcSpellCritNoBonus(), tower, tower, true, true, false )
    local Dutchman d = Dutchman.create( p, tower )
    call p.color( 100, 100, 100, 180 )
    call p.setScale( 1.00 )
    set tower.userInt = d
    set p.userInt = d
endfunction

On Tower Destruction

function onDestruct takes Tower tower returns nothing
    call Dutchman(tower.userInt).destroy()
endfunction

On Tower Details

function onTowerDetails takes Tower tower returns MultiboardValues
    call mbvals.setValue(0, I2S(Dutchman(tower.userInt).souls))
    return mbvals
endfunction