Forest Ranger v1
1100
ID:
602
Family ID:
Author:
Boekie
Rarity:
rare
Element:
nature
Attack Type:
Essence
Attack Range:
850
Attack CD:
2.2
Damage:
1194-1199
Status:
Approved

Description:

An archer that has been granted a gift from the forest.
Multishot:
Attacks up to 3 targets at the same time.

Level Bonus:
+1 target at level 15
Gift of the Forest
The magical powers of the forest grant this archer enchanted arrows. These arrows have a 6% chance to stun for 1.75 seconds. If they don't stun there is a 15% chance to slow by 15% for 8.5 seconds. 

Level Bonus
+0.1% chance to stun
+0.05 seconds stun duration
+0.1% chance to slow
+0.2 seconds slow duration
Download

Toggle Triggers

Header

    globals   
    //@import
    BuffType CyonyPoison
    endglobals 
    
    //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 
    endfunction

On Damage

ONDAMAGE_chance: 1.0 ONDAMAGE_chanceLevelAdd: 0.0
function onDamage takes Tower tower returns nothing
local integer level = tower.getLevel()
local Unit creep = Event.getTarget()

if tower.calcChance(0.06 + level*0.001) then
    call cb_stun.applyOnlyTimed(tower, creep, 1.75 + level*0.05)
  elseif tower.calcChance(0.15 + level*0.001) then
    call CyonyPoison.apply(tower,creep,10+level*2) 
  endif
endfunction

On Level Up

function onLevelUp takes Tower tower returns nothing
    if tower.getLevel() == 15 then
        call UnitRemoveAbility(tower.getUnit(),'@@1@@')
        call UnitAddAbility(tower.getUnit(),'@@0@@')
    endif
endfunction

On Tower Creation

function onCreate takes Tower tower returns nothing
    if tower.getLevel() >= 15 then
        call UnitRemoveAbility(tower.getUnit(),'@@1@@')
        call UnitAddAbility(tower.getUnit(),'@@0@@')
    endif
endfunction
Tree Group v1
1100
ID:
636
Family ID:
Author:
Monolith
Rarity:
common
Element:
nature
Attack Type:
Physical
Attack Range:
950
Attack CD:
0.8
Damage:
264-269
Status:
Approved

Description:

Strong nature tower with the ability to attack multiple targets.
Multishot:
Attacks up to 5 targets at the same time.
Download
Elegant Flashing Cenotaph v1
1120
ID:
670
Family ID:
Author:
Natac
Rarity:
common
Element:
storm
Attack Type:
Energy
Attack Range:
2000
Attack CD:
1
Damage:
604-606
Status:
Approved

Description:

A common cenotaph of a mighty fallen storm warrior, whose wrath outlasts its death and still seeks for revenge.
Specials:
+10% dmg to magical (+1%/lvl)
Wrath of the Storm - Aura
The enormous wrath of the dead warrior flows out of this tower undirected. So the tower only hits a random target in range each attack.
Download

Toggle Triggers

Header

    globals
        //@import
        BuffType natac_flashingGraveRandomTarget_BuffType
    endglobals
            
    //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
    endfunction

Tower Aura

AURA_auraEffect: natac_flashingGraveRandomTarget_BuffType AURA_power: 1 AURA_level: 1 AURA_auraRange: 0 AURA_targetType: TARGET_TYPE_PLAYER_TOWERS + TARGET_TYPE_ELEMENT_STORM AURA_levelAdd: 0 AURA_powerAdd: 0 AURA_targetSelf: true
Bug Nest v1
1150
ID:
25
Family ID:
Author:
Majildian
Rarity:
uncommon
Element:
darkness
Attack Type:
Physical
Attack Range:
725
Attack CD:
1.5
Damage:
1433-1532
Status:
Approved

Description:

A colony of bugs.
Swarm of Bugs
On kill, produces bugs that increase the base damage of this tower by 12. The damage gain decreases by 1 for every 10 productions, down to a minimum of 1.

Number of produced bugs is retained through upgrade and applied with the upgrade's values. Replacing a tower from a different family will produce bugs from 60% of its total kills.
Download

Toggle Triggers

On Kill

function onKill takes Tower tower returns nothing
    call tower.modifyProperty(MOD_DAMAGE_BASE,IMaxBJ(12 - tower.userInt/10,1))
    set tower.userInt = tower.userInt+1
endfunction

On Tower Creation

function onCreate takes Tower tower returns nothing
    local Tower prev = Event.getPrecedingTower()
    local integer N
    local integer mults
    if prev != 0 then
        if prev.getFamily() == tower.getFamily() then
            set tower.userInt  = prev.userInt
        else
            set tower.userInt  = R2I(prev.getKills()*0.6)
        endif
    
        //sadly, using inlined constants gives us things like 6-1 and 6+0.5 instead of 5 and 6.5
        set mults = tower.userInt /10 //full growth multiples in all kills
        if mults >= 12 then //mults until minimum of 1
            set mults = 12-1
        endif
        
        //Since the equation is linear:
        //[Average growth over N] * N + remaining growth * (total kills - N)
        set N = mults*10
        set N = R2I((12 + 0.5-mults/2.0)*N) + (tower.userInt-N)*(12-mults)
        call tower.modifyProperty(MOD_DAMAGE_BASE,N)
    else
        //if no predecessor, initialize with zeros
        set tower.userInt = 0 //counted kills
    endif
endfunction
Greater Elemental Ghost v1
1150
ID:
135
Family ID:
Author:
Der_kleine_Tomy
Rarity:
uncommon
Element:
fire
Attack Type:
Essence
Attack Range:
950
Attack CD:
2
Damage:
2001-2001
Status:
Approved

Description:

A mysterious Ghost, which deals different damage types.
Specials:
+0.7% trigger chances/lvl
Elemental Wrath
The Elemental Ghost has a 20% chance to unleash it's wrath on attack, increasing its trigger chance by 15% for 5 seconds. Cannot retrigger during Elemental Wrath.

Level Bonus:
+0.1 seconds duration
+0.7% trigger chance increase
Mimic
The Ghost's attacks are varied, and its damage type will either be good or bad against its target. Trigger chance adjusts the good/bad attacks to be better.
Download

Toggle Triggers

Header

    globals
        //@import
        BuffType tomy_ElementalWrath
    endglobals
    

    
    //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
    endfunction

On Attack

ONATTACK_chance: 0.20 ONATTACK_chanceLevelAdd: 0.0
function onAttack takes Tower tower returns nothing
    if tower.getBuffOfType(tomy_ElementalWrath) == 0 then
        call tomy_ElementalWrath.applyCustomTimed(tower, tower, 150 + tower.getLevel() * 7, 5.0 + 0.1 * tower.getLevel())
    endif
endfunction

On Damage

ONDAMAGE_chance: 1.0 ONDAMAGE_chanceLevelAdd: 0.0
function onDamage takes Tower tower returns nothing
 
    local Creep target = Event.getTarget()
    local boolean immune = target.isImmune()
    local boolean sif = target.getArmorType() == ARMOR_SIF
    local boolean zod = target.getArmorType() == ARMOR_ZOD
    local integer level = tower.getLevel()
    local real damageadd
    local real posDamageTypes = 3
  
    if immune then
        set posDamageTypes = 2
    endif
  
    if GetRandomInt(1, 100) > 50 then
        if sif or zod then
            set damageadd = 1.00
        elseif tower.calcChance(1.00/posDamageTypes) then
            set damageadd = 1.80
        elseif not immune and tower.calcChance(1.00/(posDamageTypes - 1)) then
            set damageadd = 1.50
        else
            set damageadd = 1.20
        endif
    else
        if zod then
            set damageadd = 0.90
        elseif sif then
            if not immune or (immune and tower.calcChance(0.50)) then
                set damageadd = 0.40
            else
                set damageadd = 0.00
            endif
        elseif tower.calcChance(1.00/(6.00-posDamageTypes)) then
            set damageadd = 1.00
        elseif tower.calcChance(1.00/(6.00-(posDamageTypes + 1))) then
            set damageadd = 0.90
        elseif not immune or (immune and tower.calcChance(1.00/(6.00-(posDamageTypes + 2)))) then
            set damageadd = 0.60
        else
            set damageadd = 0.00
        endif
    endif
  
    set Event.damage = Event.damage * damageadd
    if damageadd > 1.00 then
        call tower.getOwner().displaySmallFloatingText(formatFloat(damageadd,2), tower, 0, 255, 0, 40)
    elseif damageadd < 1.00 then
        call tower.getOwner().displaySmallFloatingText(formatFloat(damageadd,2), tower, 255, 0, 0, 40)
    else
        call tower.getOwner().displaySmallFloatingText(formatFloat(damageadd,2), tower, 255, 255, 255, 40)
    endif
endfunction
Devoted Zealot v1
1150
ID:
193
Family ID:
Author:
dzk87
Rarity:
rare
Element:
storm
Attack Type:
Physical
Attack Range:
875
Attack CD:
2
Damage:
2371-2554
Status:
Approved

Description:

Driven by zealotry, this unit is exceptionally good in physical combat.
Lightning Shield
As the zealot gets pumped up debuff durations are reduced by 6.5% with each stack of Zeal.
Zeal
Each attack works the Zealot into a greater frenzy, increasing his attack speed by 2% from each tower in 175 range. These towers have their attack speed slowed by 2%. Both effects stack up to 5 times and last 2.5 seconds. The attack speed amount reduces slightly with more towers.
Only towers that cost 460 gold or more are affected by this.

Level Bonus:
+1 max stack per 5 levels
Phase Blade
Each attack on the same creep penetrates deeper through its armor. Per attack 4% of this tower's attack damage won't be reduced by armor resistances. This effect stacks up to 5 times.

Level Bonus:
+0.16% damage per stack
Download

Toggle Triggers

Header

    globals
        //@import
        BuffType storm_zealot_fury
        //@import 
        BuffType storm_zealot_wound
        //@import
        BuffType storm_zealot_slow
        //@import
        BuffType storm_zealot_shield
    endglobals
    
    //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
    
    endfunction

On Attack

ONATTACK_chance: 1.0 ONATTACK_chanceLevelAdd: 0.0
function onAttack takes Tower tower returns nothing
    local Buff b
    local Tower u
    local Iterate it = Iterate.overUnitsInRangeOfCaster(tower, TARGET_TOWERS, 175.0)
    local integer leechCounter = 0
    local integer leechPower
    local integer maxStacks = 5 + tower.getLevel()/5
 
    loop 
        set u = it.next()
        exitwhen u == 0 
        if u != tower and u.getGoldcost() >= 460 then
            set leechCounter = leechCounter + 1
        endif 
    endloop
    
    if leechCounter == 0 then
        return
    endif
    
    set leechPower = 210 - 10*leechCounter //1% leech per tower with 1 tower, 0.65% per tower with 8 
 
    set it = Iterate.overUnitsInRangeOfCaster(tower, TARGET_TOWERS, 175.0)
    
    // Slows all towers in 175 range
    loop 
        set u = it.next()
        exitwhen u == 0 
        if u != tower and u.getGoldcost() >= 460 then
            set b = u.getBuffOfType(storm_zealot_slow)
            if b != 0 then
                set b.userInt = IMinBJ(b.userInt + 1, maxStacks)
                call storm_zealot_slow.applyCustomPower(tower, u, b.userInt, leechPower*b.userInt)
            else
                set storm_zealot_slow.applyCustomPower(tower, u, 1, leechPower).userInt = 1
            endif
        endif 
    endloop

    set leechPower = leechPower * leechCounter //in a way that's the per stack base
    set b = tower.getBuffOfType(storm_zealot_fury)
    
    //now apply zeal
    if b != 0 then
        call storm_zealot_fury.apply(tower, tower, IMinBJ(leechPower + b.getLevel(), leechPower * maxStacks))
    else
        call storm_zealot_fury.apply(tower, tower, leechPower) //used normal apply so power = level
    endif
    
    set b = tower.getBuffOfType(storm_zealot_shield)
    
    if b != 0 then
        if b.userInt < maxStacks then 
            set b.userInt = b.userInt + 1 
            if b.userInt == maxStacks then
                if b.userInt2 == 0 then
                    set b.userInt2 = Effect.createScaled("Abilities\\Spells\\Human\\ManaShield\\ManaShieldCaster.mdl", tower.getX(), tower.getY(), 115, 0, 0.67) 
                    call Effect(b.userInt2).noDeathAnimation()
                endif
            endif 
        endif
        
        call storm_zealot_shield.apply(tower, tower, 650 * b.userInt) 
    else 
        set b = storm_zealot_shield.apply(tower, tower, 650)
        set b.userInt = 1
        set b.userInt2 = 0
    endif 
endfunction

On Damage

ONDAMAGE_chance: 1.0 ONDAMAGE_chanceLevelAdd: 0.0
function onDamage takes Tower tower returns nothing
    local Creep target = Event.getTarget()
    local Buff phaseWound = target.getBuffOfType(storm_zealot_wound) 
    local real damageBase = Event.damage
    local real totalArmorPierce
    local real temp = AttackType.PHYSICAL.getDamageAgainst(target.getArmorType()) 

    if Event.isSpellDamage() or not Event.isMainTarget() then
        return
    endif

    //first check+upgrade the wound level
    if phaseWound == 0 then
        set phaseWound = storm_zealot_wound.apply(tower, target, 1)
        set phaseWound.userInt = 1 //stack counter
        set phaseWound.userInt2 = tower.getUID()
    else
        //multiple zealots + family member check. If another zealot attacks, no armor pierce for him
        //only the guy who put the first wound gets armor pierce
        //perfection would need hashtables storing wound level for every tower,creep pair. Not worth it i think.
        if phaseWound.userInt2 != tower.getUID() then
            return
        endif
        set phaseWound.userInt = IMinBJ(5, phaseWound.userInt + 1)
        call phaseWound.refreshDuration()
    endif
        
    if temp > 0.001 and temp < 1. then //ignoring armor type "resistance" not weakness :P 
        set damageBase = damageBase / temp 
    endif 
    
    set temp = 1 - target.getCurrentArmorDamageReduction()
    
     if temp > 0.001 and temp < 1. then 
        set damageBase = damageBase / temp 
    endif 
    
    set totalArmorPierce = (0.04 + 0.0016*tower.getLevel()) * phaseWound.userInt
    
    if Event.damage < damageBase then 
        set Event.damage = damageBase*totalArmorPierce + Event.damage*(1.-totalArmorPierce) 
    endif 
endfunction
Necromantic Shrine v1
1200
ID:
7
Family ID:
Author:
Boekie
Rarity:
uncommon
Element:
darkness
Attack Type:
Decay
Attack Range:
875
Attack CD:
1.6
Damage:
1146-1146
Mana:
30
Mana regen:
2
Status:
Approved

Description:

This shrine is haunted by lost souls.
Soul Revenge
Hits 3 random creeps in 875 range, the first one suffers 800 spelldamage, the second one suffers 1600 spelldamage and the third one suffers 2400 spelldamage.

Level Bonus:
+48/96/192 spelldamage

AC_TYPE_OFFENSIVE_IMMEDIATE
 20, 875 range, 1s cooldown
Download

Toggle Triggers

Autocast

caster_art: AUTOCAST_cooldown: 1 AUTOCAST_numBuffsBeforeIdle: 0 AUTOCAST_isExtended: false AUTOCAST_autocastType: AC_TYPE_OFFENSIVE_IMMEDIATE AUTOCAST_manacost: 20 AUTOCAST_range: 875 AUTOCAST_buffType: 0 AUTOCAST_targetSelf: false AUTOCAST_targetType: 0 target_art: Abilities\Spells\Undead\Curse\CurseTarget.mdl AUTOCAST_autoRange: 875
private function onAutocast takes Tower tower returns nothing
    local integer  lvl = tower.getLevel()
    local Iterate inRange = Iterate.overUnitsInRangeOfCaster(tower,TARGET_TYPE_CREEPS,875) //Can set this at the start.
    local Unit next //Used as next during the iterate and the unit to affect during the other loop.
    local integer indexCounter = 0
    local integer loopCounter = 3
    local integer counter = 1

    loop
        set next=inRange.next()
        exitwhen next==0
        set resultArray[indexCounter] = next
        set indexCounter = indexCounter+1
    endloop
   
    if(indexCounter > 0) then //Commented lines here are for setting the period to a low time when no creeps are around,
                              //remove them if you don't want this to happen. Also if these lines are used, the On Level
                              //Up code isn't needed.
        loop
            set loopCounter = loopCounter - 1
            set next = resultArray[GetRandomInt(0,indexCounter-1)]
            call tower.doSpellDamage(next,(800+lvl*48)*counter,tower.calcSpellCritNoBonus())
            call SFXAtUnit("Abilities\\Spells\\Items\\AIre\\AIreTarget.mdl",next.getUnit())
            set counter = counter + 1
            exitwhen loopCounter == 0
        endloop
    
    endif
    
endfunction

Header

    globals
    Unit array resultArray //Instead of numResults, use a resultArray so you only have to iterate once.
    endglobals
    
    //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
    endfunction