• 🏆 Texturing Contest #33 is OPEN! Contestants must re-texture a SD unit model found in-game (Warcraft 3 Classic), recreating the unit into a peaceful NPC version. 🔗Click here to enter!
  • It's time for the first HD Modeling Contest of 2024. Join the theme discussion for Hive's HD Modeling Contest #6! Click here to post your idea!

Zephyr Challenge #6 - AOE Summon

Status
Not open for further replies.
Level 5
Joined
Oct 26, 2009
Messages
161
I agree, not a lot of originality can be had here, but at the least spells should try to keep close to the examples given. I hadn't really noticed the similarity to pocket factory, either, but I think mine's sufficiently different enough to feel different.
 
Level 16
Joined
Feb 22, 2006
Messages
960
so... here WIP

things which are left:
- Better Test-Map instead of just hero + 3 units
- Documentation
- SpellTooltip

And one Bug with the Shield-Effect in the End... the effect disapears some time after the destruction was called...

basicaly this spell does:
- deals 10/20/30 dmg to all units in aoe
- summons lyrium spirit which gets attack bonus compareable to hostile units in radius of 250/300/350 (up to 12 units)
- deals each 1.5seconds 2/3/4 dmg to up to 12 units in range, the dealt damage is "stored" AND
- when the lyrium spirit dies it releases the stored energy to protect the caster whith a shield which absorbs all physical damage until 15 seconds are passed or the stored "damage" is equal to zero

here the code:

JASS:
scope SpellScope initializer onInit
    globals
        private constant    integer     dummyId         =   'n001'
        private constant    integer     spellId         =   'A000'
        private constant    integer     dmgBuffId       =   'A001'
        private constant    integer     unitId          =   'n000'
        
        private constant    integer     unitCount       =   12
        private constant    integer     unitCountInc    =   0
        private constant    integer     damageBoost     =   2
        private constant    integer     damageBoostInc  =   1
        
        
        private constant    real        interval        =   0.03125
        private constant    real        duration        =   20.0
        private constant    real        durationInc     =   15.0
        private constant    real        shieldDur       =   15.0
        private constant    real        shieldDurInc    =   0.0
        private constant    real        coilDuration    =   0.50
        private constant    real        summonTime      =   coilDuration*2
        private constant    real        missileDuration =   1.5
        private constant    real        damageInterval  =   1.5
        private constant    real        damageRadius    =   250.0
        private constant    real        damageRadiusInc =   50.0
        private constant    real        aoeDmg          =   2.0
        private constant    real        aoeDmgInc       =   1.0
        private constant    real        coilDamage      =   10.0
        private constant    real        coilDamageInc   =   10.0
        private constant    real        shieldFactor    =   2.0
        
        private constant    string      shieldEffect    =   "Abilities\\Spells\\Human\\ManaShield\\ManaShieldCaster.mdl"
        private constant    string      shieldSummonGFX =   "Abilities\\Spells\\Undead\\DeathPact\\DeathPactTarget.mdl"
        private constant    string      summonEffect    =   "Abilities\\Spells\\Undead\\Darksummoning\\DarkSummonTarget.mdl"
        private constant    string      coilEffect      =   "Abilities\\Spells\\Undead\\DeathCoil\\DeathCoilMissile.mdl"
        private constant    string      coilDeathEffect =   "Abilities\\Spells\\Undead\\DeathCoil\\DeathCoilSpecialArt.mdl"
        private constant    string      missileEffect   =   "Abilities\\Weapons\\AvengerMissile\\AvengerMissile.mdl"
        
        
        private             group       tmpG            =   null
        private             player      tmpP            =   null
        private             boolexpr    cond            =   null
    endglobals

    private function getDuration takes integer lvl returns real
        return (lvl-1)*durationInc+duration
    endfunction
    
    private function getShieldDuration takes integer lvl returns real
        return (lvl-1)*shieldDurInc+shieldDur
    endfunction
    
    private function getMaximumUnitCount takes integer lvl returns integer
        return (lvl-1)*unitCountInc+unitCount
    endfunction
    
    private function getDamageBoost takes integer lvl returns integer
        return (lvl-1)*damageBoostInc+damageBoost
    endfunction
    
    private function getAoeDmg takes integer lvl returns real
        return (lvl-1)*aoeDmgInc+aoeDmg
    endfunction
    
    private function getCoilDmg takes integer lvl returns real
        return (lvl-1)*coilDamageInc+coilDamage
    endfunction
    
    private function getDamageRadius takes integer lvl returns real
        return (lvl-1)*damageRadiusInc+damageRadius
    endfunction
    
    
    private function filter takes nothing returns boolean
        return IsUnitEnemy(GetFilterUnit(),tmpP) and (GetUnitState(GetFilterUnit(),UNIT_STATE_LIFE)>0) and IsUnitType(GetFilterUnit(),UNIT_TYPE_GROUND) and (GetUnitTypeId(GetFilterUnit())!=dummyId)
    endfunction
    
    private struct shieldStruct
        private unit target = null
        private effect gfx = null
        private real duration = 0.0
        private real absorb = 0.0
        
        private static HandleTable table
        private static timer tim
        private static integer total = 0
        private static integer array data       
        
        private static method callback takes nothing returns nothing
            local thistype this
            local integer i = 0
            loop
                exitwhen i >= thistype.total
                set this = thistype.data[i]
                set this.duration = this.duration - interval
                if this.duration <= 0 or this.absorb <= 0 or GetUnitState(this.target,UNIT_STATE_LIFE) <= 0.406 then
                    set this.total = this.total - 1
                    set this.data[i] = this.data[this.total]
                    set i = i - 1
                    call this.destroy()
                endif
                set i = i + 1
            endloop
            if thistype.total == 0 then
                call PauseTimer(thistype.tim)
            endif
        endmethod
        
        static method create takes unit target, real absorb, real duration returns thistype
            local thistype this = thistype.allocate()
            set this.target = target
            set this.absorb = absorb
            set this.duration = duration
            set this.table[target] = this
            set this.gfx = AddSpecialEffectTarget(shieldEffect,target,"origin")
            call DestroyEffect(AddSpecialEffectTarget(shieldSummonGFX,target,"origin"))
            if this.total == 0 then
                call TimerStart(this.tim,interval,true,function thistype.callback)
            endif
            set this.data[this.total] = this
            set this.total = this.total + 1
            return this
        endmethod
        
        private method onDestroy takes nothing returns nothing
            call DestroyEffect(this.gfx)
            set this.gfx = null
            call this.table.flush(this.target)
            set this.target = null
        endmethod
        
        private static method condition takes nothing returns boolean
            return GetTriggerDamageType() == DAMAGE_TYPE_ATTACK and thistype.table.exists(GetTriggerDamageTarget())
        endmethod
        
        private static method action takes nothing returns nothing
            local thistype this = thistype.table[GetTriggerDamageTarget()]
            local real life = GetUnitState(this.target,UNIT_STATE_LIFE)
            set this.absorb = this.absorb - GetTriggerDamage()
            call SetUnitState(this.target,UNIT_STATE_LIFE,life+GetTriggerDamage())
        endmethod
        
        private static method onInit takes nothing returns nothing
            local trigger trig = CreateTrigger()
            call TriggerAddCondition(trig,Condition(function thistype.condition))
            call TriggerAddAction(trig,function thistype.action)
            call TriggerRegisterDamageEvent(trig,0)
            set trig = null
            set thistype.table = HandleTable.create()
            set thistype.tim = CreateTimer()
        endmethod
    endstruct

    private struct missileStruct
        private unit missile = null
        private unit target = null
        private effect gfx = null   
        private real duration = 0.0
        private real damage = 0.0
        private static timer tim
        private static integer total = 0
        private static integer array data  
        
        private static method callback takes nothing returns nothing
            local thistype this
            local integer i = 0
            local real x1 = 0
            local real x2 = 0
            local real x3 = 0
            local real y1 = 0
            local real y2 = 0
            local real y3 = 0
            local real distance = 0
            local real angle = 0
            loop
                exitwhen i >= thistype.total
                set this = thistype.data[i]                               
                set x1 = GetUnitX(this.missile)
                set y1 = GetUnitY(this.missile)
                set x2 = GetUnitX(this.target)
                set y2 = GetUnitY(this.target)
                set distance = SquareRoot((x2-x1)*(x2-x1)+(y2-y1)*(y2-y1))/(this.duration/interval)
                set angle = Atan2(y2-y1,x2-x1)
                set x3 = x1 + distance * Cos(angle)
                set y3 = y1 + distance * Sin(angle)
                call SetUnitPosition(this.missile,x3,y3)
                if this.duration == 0 then
                    set this.total = this.total - 1
                    set this.data[i] = this.data[this.total]
                    set i = i - 1
                    call this.destroy()
                endif
                set this.duration = this.duration - interval 
                set i = i + 1
            endloop
            if thistype.total == 0 then
                call PauseTimer(thistype.tim)
            endif
        endmethod
        
        static method create takes player owner, string effectPath, real x1, real y1, unit target,real duration,real damage returns thistype
            local thistype this = thistype.allocate()
            set this.missile = CreateUnit(owner,dummyId,x1,y1,0)
            call AddSpecialEffectTarget(effectPath,this.missile,"origin")
            set this.target = target
            set this.duration = duration
            set this.damage = damage
            if this.total == 0 then
                call TimerStart(this.tim,interval,true,function thistype.callback)
            endif
            set this.data[this.total] = this
            set this.total = this.total + 1
            return this
        endmethod
        
        private method onDestroy takes nothing returns nothing
            call UnitDamageTargetEx(this.missile,this.target,this.damage,ATTACK_TYPE_NORMAL,DAMAGE_TYPE_SPELL,true)
            call RemoveUnit(this.missile)
            call DestroyEffect(this.gfx)
            call DestroyEffect(AddSpecialEffect(coilDeathEffect,GetUnitX(this.target),GetUnitY(this.target)))            
            set this.target = null
            set this.missile = null
            set this.gfx = null
        endmethod
        
        private static method onInit takes nothing returns nothing
            set thistype.tim = CreateTimer()
        endmethod
    endstruct

    private struct spiritStruct
        public unit caster = null        
        public real spellX = 0.0
        public real spellY = 0.0
        public integer unitsInRange = 0
        
        private unit summon = null 
        private unit summonRitual = null
        private effect ritualEffect = null
        private real timePassed = 0.0
        private real damageTime = 0.0
        private real damageDealt = 0.0
        private boolean isSummoned = false
        private boolean coilWave = false
        private static timer tim
        private static integer total = 0
        private static integer array data   

        private static method callback takes nothing returns nothing
            local thistype this
            local integer i = 0
            local integer j = 0
            local unit u = null
            loop
                exitwhen i >= thistype.total
                set this = thistype.data[i]
                set this.timePassed = this.timePassed + interval
                set this.damageTime = this.damageTime + interval                
                if this.timePassed >= summonTime and this.isSummoned != true then
                    set this.summon = CreateUnit(GetOwningPlayer(this.caster),unitId,this.spellX,this.spellY,0)
                    call RemoveUnit(this.summonRitual)
                    call DestroyEffect(this.ritualEffect)
                    call UnitApplyTimedLife(this.summon,'BTLF',getDuration(GetUnitAbilityLevel(this.caster,spellId)))  
                    call UnitAddAbility(this.summon,dmgBuffId)
                    call SetUnitAbilityLevel(this.summon,dmgBuffId,this.unitsInRange*getDamageBoost(GetUnitAbilityLevel(this.caster,spellId)))
                    set this.damageDealt = this.unitsInRange*getCoilDmg(GetUnitAbilityLevel(this.caster,spellId))
                    if this.unitsInRange == 0 then
                        call UnitRemoveAbility(this.summon,dmgBuffId)
                    endif
                    set this.isSummoned = true              
                elseif this.timePassed >= summonTime and this.damageTime >= damageInterval then 
                    set tmpP = GetOwningPlayer(this.caster)
                    call GroupEnumUnitsInRange(tmpG,GetUnitX(this.summon),GetUnitY(this.summon),getDamageRadius(GetUnitAbilityLevel(this.caster,spellId)),cond)
                    loop
                        set u = FirstOfGroup(tmpG)
                        exitwhen u == null or j >= getMaximumUnitCount(GetUnitAbilityLevel(this.caster,spellId))  
                        set j = j + 1
                        call missileStruct.create(GetOwningPlayer(this.caster),missileEffect,GetUnitX(this.summon),GetUnitY(this.summon),u,coilDuration,getAoeDmg(GetUnitAbilityLevel(this.caster,spellId)))
                        set this.damageDealt = this.damageDealt + getAoeDmg(GetUnitAbilityLevel(this.caster,spellId))
                        call GroupRemoveUnit(tmpG,u)
                    endloop                    
                    set this.damageTime = 0.0
                elseif this.timePassed >= coilDuration and this.coilWave != true then
                    set this.summonRitual = CreateUnit(GetOwningPlayer(this.caster),dummyId,this.spellX,this.spellY,0)
                    set this.ritualEffect = AddSpecialEffectTarget(summonEffect,this.summonRitual,"origin")
                    set tmpP = GetOwningPlayer(this.caster)
                    call GroupEnumUnitsInRange(tmpG,this.spellX,this.spellY,getDamageRadius(GetUnitAbilityLevel(this.caster,spellId)),cond)
                    loop
                        set u = FirstOfGroup(tmpG)
                        exitwhen u == null or j >= getMaximumUnitCount(GetUnitAbilityLevel(this.caster,spellId))  
                        set j = j + 1
                        call missileStruct.create(GetOwningPlayer(this.caster),coilEffect,GetUnitX(u),GetUnitY(u),this.summonRitual,coilDuration,0)
                        call GroupRemoveUnit(tmpG,u)
                    endloop  
                    set j = 0
                    set this.coilWave = true
                endif
                if this.timePassed >= summonTime and this.isSummoned == true then
                    set tmpP = GetOwningPlayer(this.caster)
                    call GroupEnumUnitsInRange(tmpG,GetUnitX(this.summon),GetUnitY(this.summon),getDamageRadius(GetUnitAbilityLevel(this.caster,spellId)),cond)
                    loop
                        set u = FirstOfGroup(tmpG)
                        exitwhen u == null or j >= getMaximumUnitCount(GetUnitAbilityLevel(this.caster,spellId))  
                        set j = j + 1
                        call GroupRemoveUnit(tmpG,u)
                    endloop  
                    if GetUnitAbilityLevel(this.summon,dmgBuffId) <= 0 then
                        call UnitAddAbility(this.summon,dmgBuffId)
                    endif
                    set this.unitsInRange = j
                    call SetUnitAbilityLevel(this.summon,dmgBuffId,this.unitsInRange*getDamageBoost(GetUnitAbilityLevel(this.caster,spellId)))
                    if this.unitsInRange == 0 then
                        call UnitRemoveAbility(this.summon,dmgBuffId)
                    endif  
                    set j = 0
                endif
                //Destroy this struct if following coditions are true
                if (this.timePassed >= getDuration(GetUnitAbilityLevel(this.caster,spellId)) or GetUnitState(this.summon,UNIT_STATE_LIFE) <= 0.406) and this.isSummoned == true then
                    set this.total = this.total - 1
                    set this.data[i] = this.data[this.total]
                    set i = i - 1
                    call shieldStruct.create(this.caster,this.damageDealt/shieldFactor,getShieldDuration(GetUnitAbilityLevel(this.caster,spellId)))
                    call this.destroy()
                endif
                set i = i + 1
            endloop
            if thistype.total == 0 then
                call PauseTimer(thistype.tim)
            endif
        endmethod
        
        static method create takes nothing returns thistype
            local thistype this = thistype.allocate()
            if this.total == 0 then
                call TimerStart(this.tim,interval,true,function thistype.callback)
            endif
            set this.data[this.total] = this
            set this.total = this.total + 1
            return this
        endmethod
        
        private method onDestroy takes nothing returns nothing
            set this.caster = null
            set this.summon = null
            set this.ritualEffect = null            
        endmethod
        
        private static method onInit takes nothing returns nothing
            set thistype.tim = CreateTimer()
        endmethod
    endstruct

    private function spellCond takes nothing returns boolean
        return GetSpellAbilityId() == spellId
    endfunction
    
    private function spellAction takes nothing returns nothing
        local spiritStruct this = spiritStruct.create()
        local integer i = 0
        local unit u = null
        set this.spellX = GetSpellTargetX()
        set this.spellY = GetSpellTargetY()
        set this.caster = GetTriggerUnit()
        set tmpP = GetOwningPlayer(this.caster)
        call GroupEnumUnitsInRange(tmpG,this.spellX,this.spellY,getDamageRadius(GetUnitAbilityLevel(this.caster,spellId)),cond)
        loop
            set u = FirstOfGroup(tmpG)
            exitwhen u == null or i >= getMaximumUnitCount(GetUnitAbilityLevel(this.caster,spellId))  
            set i = i + 1
            call missileStruct.create(GetOwningPlayer(this.caster),coilEffect,GetUnitX(this.caster),GetUnitY(this.caster),u,coilDuration,getCoilDmg(GetUnitAbilityLevel(this.caster,spellId)))
            call GroupRemoveUnit(tmpG,u)
        endloop
        set this.unitsInRange = i
    endfunction
    
    private function onInit takes nothing returns nothing
        local trigger trig = CreateTrigger()
        local unit dummy = null
        local integer index = 0
        loop
            call TriggerRegisterPlayerUnitEvent(trig, Player(index), EVENT_PLAYER_UNIT_SPELL_EFFECT, null)
            set index = index + 1
            exitwhen index == bj_MAX_PLAYER_SLOTS
        endloop
        call TriggerAddCondition(trig,Condition(function spellCond))
        call TriggerAddAction(trig, function spellAction)
        set trig = null        
        set tmpG = CreateGroup()
        set cond = Filter(function filter)
        
        //Preload-Part
        set dummy = CreateUnit(Player(14),dummyId,0,0,0)
        call UnitAddAbility(dummy,dmgBuffId)
        call RemoveUnit(dummy)
        set dummy = null
        
        call Preload(shieldEffect)
        call Preload(shieldSummonGFX)
        call Preload(summonEffect)
        call Preload(coilEffect)
        call Preload(coilDeathEffect)
        call Preload(missileEffect)
        call PreloadStart()
    endfunction
endscope

BTW. like I said....if someone finds the reason why the damn shield disapears later.... say it!!
 

Attachments

  • Zephyr Challenge #6 Entry.w3x
    46.9 KB · Views: 73
Level 23
Joined
Nov 29, 2006
Messages
2,482
Okay here is mine. I do realize that there are better submissions than mine, and could only hope for the best:p It doesn't really matter though, since my spell turned out to be a request anyway.


34fmnuc.png
Calls forth a goblin airstrike in the targeted area, dropping clusters of land mines
randomly on the ground. The land mines then explode dealing up to 40 damage
to nearby enemy ground units.
Level 1 - 5 drops, each spawning 3 clusters.
Level 2 - 5 drops, each spawning 5 clusters.
Level 3 - 5 drops, each spawning 7 clusters.
Level 4 - 5 drops, each spawning 9 clusters.

Credits to
*Vexorian
*Pitzermike
*MindWorX
*Volvox
*Mc !

The spell requires JNGP and uses xebasic and a small mapbounds library, both included in the map ofcourse.
 

Attachments

  • ZephyrCompetition6_Eccho.w3x
    134.4 KB · Views: 138
Dune Worm

icons_490_btn.jpg


Requires
All of the script requirements are included within the demo map.

Other Credits
  • Icon by JoelS
  • Model by Sephiroth_VII

18160676.png



EDIT: Level 3 on the screenshot is wrong. It's fixed in the demo map.
 

Attachments

  • Dune Worm.w3x
    209.9 KB · Views: 179
Last edited:
Level 20
Joined
Apr 22, 2007
Messages
1,960
Nevermind, I'm far too lazy to actually finish something up.

Well that was expected! Also, nice submissions TriggerHappy and Eccho. TriggerHappy, my concept initially was very similar to yours. I'm looking forward to seeing some of the other submissions in a compiled post because, of course, I'm far too lazy to sift through them all right now! :D
 
Level 8
Joined
Aug 4, 2006
Messages
357
Fuck... if only the deadline were a week later. Who knows; maybe I'll be able to make a legit spell in just one day (as well as go to class/do homework).

There's some really nice submissions so far; I don't know if it's worth my losing sleep to slap together of a spell if I don't even have a chance of winning :/
 
Level 13
Joined
Jun 22, 2004
Messages
783
Currently I am facing 2 issue, of which 1 is a pretty big one, they have to do with saving SFX's and removing them in MUI.

Basically the spell is done, but in order to make it graphically and data removal correct, I still got quite a bit figuring out to do.

Hopefully I can have it done tomorrow, but the odds are against me at the moment.
 
Level 17
Joined
Jun 28, 2008
Messages
776
This will be my final entry for the time being ( Just in case I don't get time later)

JASS:
library Appocalypse uses STDLIB

globals

        //! Constant Globals
    
    constant integer SummonUnitId = 'n000' // The summond unit's Rawcode
    constant integer DummyUnit    = 'n001' // The dummy unit
    constant integer FlameSpawn   = 'n002' // This is the summond units summond unit
    constant real SleepTime       = 0.25   // The interval time to check when the caster stops casting
    constant integer Ability      = 'A000' // The abilities raw code
    
        //! Index Globals
    
    FireBall array FBArray
    Summon array SMArray
    integer index  = 0
    integer key    = 0

    
endglobals

struct Summon

    unit array SummonUnits[9]
    
    real Damage = 0
    real DmgAoE = 0
    
    integer MaxUnit = 0
    
    real x = 0
    real y = 0
    real a = 0
    
    string Effect1 = ""

endstruct

 //This struct is used for the FireBall effect

struct FireBall

    real Damage = 10  //! Damage Dealt on impact
    real AccHig = 0.5 //! Hight at wich the ball is climing in hundred (AccHig * 100)
    real LifeSp = 10  //! The balls fife span
    real CrtAng = 0   //! The current angle of the ball
    real AoEDmg = 50  //! The Area in wich to damage
    
    real x = 0
    real y = 0
    
        //!Model of the unit
    string Effect1 = "Abilities\\Weapons\\RedDragonBreath\\RedDragonMissile.mdl"
    string Effect2 = "Abilities\\Weapons\\RedDragonBreath\\RedDragonMissile.mdl"
        //!Special effect on collision
        
    group HasDamage = CreateGroup()
    
    integer KeySummon
    
    unit ThisUnit  = null
    unit Caster    = null
    
    unit array SmnUnt[9] //! This is the summond units
    
    timer t = CreateTimer()
    
        //! This is the timer function
    
    static method MoveBall takes nothing returns nothing
    
        local timer t    = GetExpiredTimer()
        local integer i  = 0
        local integer ii = 0
        local location l = null
        local real x = 0
        local real y = 0
        local real d = GetRandomReal(50, 300)
        local real a = GetRandomReal(0 , 360)
        
        //This code is used to get the index of the Struct array
        
        loop
            
            set i = i + 1
            exitwhen i > index
            if GetHandleId(FBArray[i].t) == GetHandleId(t) then
                set ii = i
            endif
        
        endloop
        
        set FBArray[ii].CrtAng = FBArray[ii].CrtAng + 5
        set x = FBArray[ii].x + 400 * Cos(FBArray[ii].CrtAng * bj_DEGTORAD)
        set y = FBArray[ii].y + 400 * Sin(FBArray[ii].CrtAng * bj_DEGTORAD)
        
        call SetUnitPosition(FBArray[ii].ThisUnit, x, y)
    
            // Detects units and damage them
            
        if DetectUnit(FBArray[ii].ThisUnit, 50) == 1 then
        
            set l = GetUnitLoc(FBArray[ii].ThisUnit)
            call AoEDamage(FBArray[ii].ThisUnit, l, ATTACK_TYPE_MAGIC, ii)
            
        endif
        
            // Create Summoned units
            
    
            // Stops the timer and removes the unit if the unit is dead
            
        if GetUnitState(FBArray[ii].ThisUnit, UNIT_STATE_LIFE) <= 0 then
        
            call PauseTimer(FBArray[ii].t)
            call RemoveUnit(FBArray[ii].ThisUnit)
            call DestroyTimer(FBArray[ii].t)
            call DestroyGroup(FBArray[ii].HasDamage)
            call FBArray[ii].destroy()
        
        endif
        
        call RemoveLocation(l)
    
    endmethod
    
        //! This is the init function
    
    static method Create takes unit u, player p, location l, integer i returns nothing
    
        local real a     = 0
        local real x     = GetLocationX(l) + 400 * Cos(a * bj_DEGTORAD)
        local real y     = GetLocationY(l) + 400 * Sin(a * bj_DEGTORAD)
        local integer ii = 0
        
        set index = index + 1
        set FBArray[index] = FireBall.create()
        
        set FBArray[index].ThisUnit  = CreateUnit(p, DummyUnit, x, y, a)
        set FBArray[index].Caster    = u
        set FBArray[index].Damage    = 100
        set FBArray[index].x         = GetLocationX(l)
        set FBArray[index].y         = GetLocationY(l)
        set FBArray[index].LifeSp    = 8 + GetRandomInt(2, 6)
        set FBArray[index].Damage    = 2 * GetUnitAbilityLevel(u, Ability)
        set FBArray[index].KeySummon = i
        
        //! Creates the initial summond units for the spell
        
        call AddSpecialEffectTarget(FBArray[index].Effect1, FBArray[index].ThisUnit, "origin")
        call SetUnitFlyHeight(FBArray[index].ThisUnit, 800, (FBArray[index].AccHig * 100))
        call UnitApplyTimedLife(FBArray[index].ThisUnit, '0000', FBArray[index].LifeSp)
        
        call TimerStart(FBArray[index].t, 0.03, true, function FireBall.MoveBall)
    
        loop
        
            set ii = ii + 1
            if GetUnitState(SMArray[FBArray[index].KeySummon].SummonUnits[ii], UNIT_STATE_LIFE) <= 0 then
                set SMArray[FBArray[index].KeySummon].SummonUnits[ii] = CreateUnit(GetOwningPlayer(u), FlameSpawn, SMArray[FBArray[index].KeySummon].x, SMArray[FBArray[index].KeySummon].y, SMArray[FBArray[index].KeySummon].a)
                call UnitApplyTimedLife(SMArray[FBArray[index].KeySummon].SummonUnits[ii], 'BLTF', GetRandomReal(3, 8))
            endif
            exitwhen ii == SMArray[FBArray[index].KeySummon].MaxUnit
        
        endloop
    
    endmethod
    
endstruct


function Trig_Apocalips_Conditions takes nothing returns boolean

    if GetSpellAbilityId() == 'A000' then //Spell raw code
        return true
    else
        return false
    endif
        
endfunction

//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------

function Trig_Apocalips_Actions takes nothing returns nothing

    local location p  = GetSpellTargetLoc()
    local unit caster = GetTriggerUnit()
    local unit summon = CreateUnitAtLoc( GetOwningPlayer(caster), SummonUnitId, p, GetUnitFacing(caster))
    local integer i   = 0
    local real Damage = GetUnitAbilityLevel(caster, Ability) * 20
    local real d = GetRandomReal(50, 300)
    
    call SetUnitAnimation(summon, "Channel")
    set key = key + 1
    set SMArray[key] = Summon.create()
    set SMArray[key].MaxUnit = 3 * GetUnitAbilityLevel(caster, Ability)
    
    loop
    
        set i = i + 1
        set SMArray[key].a = GetRandomReal(1, 360)
        set SMArray[key].x = GetLocationX(p) + d * Cos( SMArray[key].a * bj_DEGTORAD)
        set SMArray[key].y = GetLocationY(p) + d * Sin( SMArray[key].a * bj_DEGTORAD)
        set SMArray[key].SummonUnits[i] = CreateUnit(GetOwningPlayer(caster), FlameSpawn, SMArray[key].x, SMArray[key].y, SMArray[key].a)
        call UnitApplyTimedLife(SMArray[key].SummonUnits[i], 'BLTF', GetRandomReal(3, 8))
        exitwhen i == 3 * GetUnitAbilityLevel(caster, Ability)
        
    endloop
    
    set i = key
    
    loop
    
        exitwhen GetUnitCurrentOrder(caster) != OrderId("channel")
        
        //Fire Ball Effect
        
        call FireBall.Create(caster, GetOwningPlayer(caster), p, i)
        
        //End Fire Effect
        
        call TriggerSleepAction(SleepTime)
    
    endloop
    
    call KillUnit(summon)
    call RemoveLocation(p)
    call SMArray[i].destroy()
    set summon = null
    set caster = null
    
endfunction

//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------

function InitTrig_Apocalyps takes nothing returns nothing
    set  gg_trg_Apocalyps = CreateTrigger(  )
    call TriggerRegisterAnyUnitEventBJ( gg_trg_Apocalyps, EVENT_PLAYER_UNIT_SPELL_EFFECT )
    call TriggerAddCondition( gg_trg_Apocalyps, Condition( function Trig_Apocalips_Conditions ) )
    call TriggerAddAction( gg_trg_Apocalyps, function Trig_Apocalips_Actions )
endfunction

endlibrary

It needs JNGP - Get it here

------------------------------------------------------------

Wow there are some pretty good spells so far

Good luck to all
 

Attachments

  • Zephyr - Summon Spell - Xiliger.w3x
    48.5 KB · Views: 90
Level 28
Joined
Jan 26, 2007
Messages
4,789
Woah, I just found out about this contest yesterday xD
Well, let's see what I can make out of this... it would be my first contest and I'm in a spell-mood today o_O

Mehh, I've got 3 hours left (still got to study for my exam tomorrow), I hope it'll be any good xD

The general idea I've got goes like this:
3 lava spawns fall out of the air, circling around the caster.
When they hit the ground, they will deal damage to everyone around and move away from the caster, after they reach a good destination, they'll fully spawn (unselectable, though) and will be able to attack everyone around.

I fear it won't be enough, but well... perhaps I can still be in the first half of the contestants :/

Edit: maybe I've got more time... if I can work on it tomorrow, that is, otherwise it ends in 3 hours for me :p

Edit 2: yay. already got some screenies of it (that was fast o_O)

firespell1.jpg


firespell2.jpg


firespell3.jpg


firespell4.jpg


I'm completely out of ideas right now, though... so this might as well be my final product :/ (unfortunately).
It's already completely MUI and you can buttonmash the spell without it being bugged, because Kingz likes it that way ^^
 
Last edited:
Level 25
Joined
Jun 5, 2008
Messages
2,572
I made the code a bit easier to read and adjusted some things, so here is the final entry, enjoy.


Summons several phoenixes onto the battlefield. The phoenixes will then fly to the battlefield, sunking to the ground to deliver powerful fire blasts to nearby enemies.The burning spirit of the phoenixes causes fire damage to nearby units, as well causes the death of the phoenixes to result in a devastating blast.Lasts 12 seconds.
Level 1 - 10 damage per second,20 impact damage,15% pure,50 death damage.
Level 2 - 20 damage per second,30 impact damage,25% pure,50 death damage.
Level 3 - 30 damage per second,40 impact damage,35% pure,50 death damage.
Mana cost: 100/135/170
Cooldown: 85





JASS:
//********************************************************************************
//* By Kingz:                                                                    *
//*                      Zephyr Entry:Flames of Ruin                             *
//*                             Requirements:                                    *
//*                            A point based spell                               *
//*                            The summoned unit                                 *
//*                       The passive immolation ability                         *
//*                            MathBasic library                                 *
//*                            JassNewGenPack v5d                                *
//********************************************************************************
 
//***********************************************
//* NOTE:                                       *
//* Doesn't have documentation on how to import *
//* since it is a challenge submision           *
//***********************************************
scope ZephyrEntry initializer InitZE
 
//**********************************************
//Settings - All of the spell settings are here*
//**********************************************
globals
    private constant integer unitID = 'h001' // unit id of the summoned unit
    private constant integer SpellID = 'A000' // spell ability ID
    private constant integer PassiveID = 'A001' // ID of the phoenixes passive immolation ability
    private constant integer UnitCount = 5 // number of units spawned
    private constant integer Count_inc = 0  // increase of summoned units per spell level
    private constant real Death_dmg = 50 // damage dealt per unit death to close enemies
    private constant real Dmg_AoE = 175 // AoE of the damage the unit deals upon coliding with the ground
    private constant real Impact_dmg = 20   // damage dealt to units in an AoE every time phoenix colides with the earth
    private constant real Dmg_inc = 10  // increase of impact damage per level
    private constant real Death_AoE = 250 // AoE of the damage the unit deals upon death
    private constant real Effect_AoE = 400 // AoE of the spell
    private constant real AoE_inc = 0   // increase of AoE per level of spell
    private constant real Minimal_offset = 300 // minimal offset from the center of the target location, used to avoid damage concentrated in 1 point
    private constant real Height = 40 // the height phoenixs reach
    private constant real Speed = 350 // the speed of phoenixes, value is in points per second
    private constant real Duration = 12 // duration of the phoenixs
    private constant real Dur_inc = 0   // duration increase per level
    private constant real Pure_dmg_per = 0.15   // this value is used for calculating the % of impact damage which is pure
    private constant real Pure_dmg_inc = 0.10   // increases the % of pure damage per level
    private constant attacktype ATT = ATTACK_TYPE_NORMAL    // no comment here
    private constant damagetype DMG_FIRE = DAMAGE_TYPE_FIRE // damage type
    private constant attacktype ATT_PURE = ATTACK_TYPE_CHAOS // used for pure damage dealing
    private constant string ExplodeEff = "Abilities\\Weapons\\PhoenixMissile\\Phoenix_Missile.mdl" // effect created at phoenixs colision with earth and their uprising
 
//***************************************************************************************
//Settings end - Do not modify anything below this if you don't know what you are doing!*
//***************************************************************************************
 
    private player TP = null // used for group actions
    private real array TR // used for group actions
    private unit TU // used for group actions
    private group GROUP = CreateGroup()
endglobals
 
// spells condition
private function Cond takes nothing returns boolean
    return GetSpellAbilityId() == SpellID
endfunction
 
// unit group filter, to avoid unproper damage dealing
private function GroupFilter takes nothing returns boolean
    return (IsUnitEnemy(GetFilterUnit(),TP) == true) and (IsUnitType(GetFilterUnit(),UNIT_TYPE_MECHANICAL) == false) and (GetWidgetLife(GetFilterUnit()) > 0.405) and (IsUnitType(GetFilterUnit(),UNIT_TYPE_MAGIC_IMMUNE)==false) and (IsUnitType(GetFilterUnit(),UNIT_TYPE_STRUCTURE)==false) and (IsUnitType(GetFilterUnit(),UNIT_TYPE_FLYING)==false)
endfunction
 
//*****************************************************
//Calculations used for getting reals/integers needed.*
//*****************************************************
 
// damage calculation
private function GetDmg takes integer lvl returns real
    return Impact_dmg + ((lvl -1)*Dmg_inc)
endfunction
 
// pure % calculation
private function GetPureFactor takes integer lvl returns real
    return Pure_dmg_per + ((lvl-1)*Pure_dmg_inc)
endfunction
 
// AoE calculation
private function GetAoE takes integer lvl returns real
    return Effect_AoE + ((lvl-1)*AoE_inc)
endfunction
 
// Duration calculation
private function GetDuration takes integer lvl returns real
    return Duration + ((lvl-1)*Dur_inc)
endfunction
 
// Unit number calculation
private function GetUnitCount takes integer lvl returns integer
    return UnitCount + ((lvl-1)*Count_inc)
endfunction
 
// used for dealing damage to units when the summoned unit dies
private function DeathDmg takes nothing returns nothing
    call UnitDamageTarget(TU,GetEnumUnit(),Death_dmg,true,false,ATT,DMG_FIRE,null)
endfunction
 
// used for dealing damage to units when the summoned unit colides with earth
private function ImpactDmg takes nothing returns nothing
    call UnitDamageTarget(TU,GetEnumUnit(),TR[1] - TR[2],true,false,ATT,DMG_FIRE,null)
    call UnitDamageTarget(TU,GetEnumUnit(),TR[2],true,true,ATT_PURE,DMG_FIRE,null)
endfunction
 
//spells struct
private struct Spell
 
    unit c      // used for damage source
    unit unit   // the spawned unit
    real rad    // angle of the unit movement in radians
    real dur    // duration
    real d      // used for maximum distance check and parabola
    real s      // speed of the missile
    real cd     // curent distance
    real basex  // used for summoned unit movement - stored X value of cast point
    real basey  // used for summoned unit movement - stored Y value of cast point
    integer lvl // used for storing the spell level to each summoned unit
 
    static Spell array ind
    static integer icr = 0  // icr = instances currently running
    static timer counter = CreateTimer()
 
    static method Motion takes nothing returns nothing
        local Spell dat
        local real x        // used for calculations further below
        local real y        // used for calculations further below
        local real tempx    // used for calculations further below
        local real tempy    // used for calculations further below
        local real dist     // used for calculations further below
        local real radian   // used for calculations further below
        local real uh       // height variable calculated via the parabola function
        local integer i = 0 // used for the loop
        loop
            exitwhen i >= Spell.icr
            set dat = Spell.ind[i]
 
            // if a phoenix gets off the map playable area, it is destroyed to prevent game crash
            if GetUnitX(dat.unit) > MaxX or GetUnitX(dat.unit) < MinX or GetUnitY(dat.unit) > MaxY or GetUnitX(dat.unit) < MinY then
                set dat.dur = 0
            endif
 
            //reduces the duration of the spell
            set dat.dur = dat.dur - 0.02
 
            // if the current distance of the summoned unit is less than the total distance, move the unit
            if dat.cd < dat.d then
                set x = GetUnitX(dat.unit) + dat.s * Cos(dat.rad)
                set y = GetUnitY(dat.unit) + dat.s * Sin(dat.rad)
                set dat.cd = dat.cd + dat.s
                call SetUnitX(dat.unit,x)
                call SetUnitY(dat.unit,y)
                call SetUnitFacing(dat.unit,dat.rad*bj_RADTODEG)
 
            else    // else set a new trajectory and deal damage to nearby units
 
                set x = GetUnitX(dat.unit)
                set y = GetUnitY(dat.unit)
                set TR[1] = GetDmg(dat.lvl)
                set TR[2] = TR[1] * GetPureFactor(dat.lvl)
                set TU = dat.c
                set TP = GetOwningPlayer(dat.c)
                call GroupEnumUnitsInRange(GROUP,x,y,Effect_AoE,Filter(function GroupFilter))
                call ForGroup(GROUP,function ImpactDmg)
                call GroupClear(GROUP)
                set radian = GetRandomReal(0,360) * bj_DEGTORAD
                set dist = GetRandomReal(Minimal_offset,Effect_AoE)
                set tempx = PPX(dat.basex,dist,radian)
                set tempy = PPY(dat.basey,dist,radian)
                set dat.rad = RBL(x,y,tempx,tempy)
                set dat.cd = 0
                set dat.d = dist
                call DestroyEffect(AddSpecialEffect(ExplodeEff,x,y))
                call SetUnitFacing(dat.unit,dat.rad*bj_RADTODEG)
                set TU = null
                set TP = null
            endif
 
            // uses the parabola to set the units height
            set uh = ParabolaZ(Height,dat.d,dat.cd)
            call SetUnitFlyHeight(dat.unit,uh,0)
 
            // if the duration is finished or the unit is dead, deal damage, remove unit,and do stuff :P
            if (dat.dur <= 0) or (GetWidgetLife(dat.unit) <= 0.405) then
                set TU = dat.c
                set TP = GetOwningPlayer(dat.c)
                set x = GetUnitX(dat.unit)
                set y = GetUnitY(dat.unit)
                call GroupEnumUnitsInRange(GROUP,x,y,Effect_AoE,Filter(function GroupFilter))
                call ForGroup(GROUP,function DeathDmg)
                call GroupClear(GROUP)
                call KillUnit(dat.unit)
                set TU = null
                set TP = null
                set dat.unit = null
                set dat.c = null
                call dat.destroy()
                set Spell.icr = Spell.icr - 1
                set Spell.ind[i] = Spell.ind[Spell.icr] 
            endif
 
            set i = i + 1
        endloop
 
        // if there are no active spell instances, pause the timer
        if Spell.icr == 0 then
            call PauseTimer(Spell.counter)
        endif
    endmethod
 
    // method use to insert the needed variables into the struct
    static method Insert takes unit c, unit u,integer lvl,real dur,real bx,real by,real s returns nothing
        local Spell dat = Spell.allocate()
        local real ux = GetUnitX(u)
        local real uy = GetUnitY(u)
        local real urad = GetRandomReal(0,360) * bj_DEGTORAD
        local real ud = GetRandomReal(Minimal_offset/2,Effect_AoE)
        local real tempx = PPX(bx,ud,urad)
        local real tempy = PPY(by,ud,urad)
        set dat.c = c
        set dat.rad = RBL(ux,uy,tempx,tempy)
        set dat.unit = u
        set dat.lvl = lvl
        set dat.d = DBL(ux,uy,tempx,tempy)
        set dat.s = s
        set dat.cd = 0
        set dat.basex = bx
        set dat.basey = by
        set dat.dur = dur
        call SetUnitFacing(dat.unit,dat.rad*bj_RADTODEG)
        if Spell.icr == 0 then
            call TimerStart(Spell.counter,0.02,true,function Spell.Motion)
        endif
        set Spell.ind[Spell.icr] = dat
        set Spell.icr = Spell.icr + 1
    endmethod
 
 
endstruct
 
    // trigger actions
private function Actions takes nothing returns nothing
    local unit c = GetTriggerUnit()
    local real x = GetUnitX(c)
    local real y = GetUnitY(c)
    local location sl = GetSpellTargetLoc()
    local real sx = GetLocationX(sl)
    local real sy = GetLocationY(sl)
    local integer lvl = GetUnitAbilityLevel(c,SpellID)
    local real dur = GetDuration(lvl)
    local integer i = GetUnitCount(lvl)
    local real s = (Speed * 0.02)
    local unit u
    loop
        exitwhen i == 0
            set u = CreateUnit(GetOwningPlayer(c),unitID,x,y,RBL(x,y,sx,sx)*bj_RADTODEG)
            call SetUnitAbilityLevel(u,PassiveID,lvl)
            call SetUnitPathing(u,false)
            call SetUnitPosition(u,x,y)
            call UnitAddAbility(u,'Amrf')
            call UnitRemoveAbility(u,'Amrf')
            call SetUnitFlyHeight(u,100,0)
            call Spell.Insert(c,u,lvl,dur,sx,sy,s)
        set i = i - 1
    endloop
    set u = null
    set c = null
    call RemoveLocation(sl)
    set sl = null
endfunction
 
    // creates a trigger,adds conditions, and preloads necesarry stuff
private function InitZE takes nothing returns nothing
    local trigger t = CreateTrigger()
    local filterfunc f = Filter(function dummyFilter)
    local conditionfunc c = Condition(function Cond)
    local integer i = 0
    loop
     call TriggerRegisterPlayerUnitEvent(t,Player(i),EVENT_PLAYER_UNIT_SPELL_EFFECT,f)
     set i = i + 1
     exitwhen i == bj_MAX_PLAYER_SLOTS
    endloop
    call TriggerAddCondition(t,c)
    call TriggerAddAction(t,function Actions)
    call Preload(ExplodeEff)
    call PreloadStart()
    call DestroyFilter(f)
    set f = null
endfunction
 
endscope
 

Attachments

  • Zephyr Entry Kingz.w3x
    93.6 KB · Views: 87
Level 37
Joined
Mar 6, 2006
Messages
9,240
Alright, I've managed to come up with something.


Contestant : Maker

Spell : NUDGE BALLS (working title)
The caster summons 3-5 wisps from the skies. You can then order the wisps to target enemies. When you do, you lose control of them, and they start accelerating towards the target. When they collide with the target, the target gets damaged and knocked back. The wisp begins accelerating away from the target, and soon returns for another attack.

You can also combine wisps to create larger, more powerful wisps.

The wisps have expiration time, and they explode doing AoE and knocking back units.

Nudgeballs_3.png

Summoning Nudgeballs

Nudgeballs_2_04.png

Nudgeballs in action

Nudgeballs_1.png

Nudgeballs exploding

Nudgeballs v0.5

Still lots and lots to do, the spell still bugs quite badly.
 
Level 7
Joined
Dec 18, 2008
Messages
400
White-Lion's Spell

Here's what will probally be my submission. . . :grin:
 

Attachments

  • Ability Test - Dark Ritual.w3x
    21.9 KB · Views: 80
Level 37
Joined
Mar 6, 2006
Messages
9,240
Thanks :)

Here's the current version, which might be my final submission, because I might not have enough time to organize and optimize code, improve tooltips, create terrain and make the spell more customizeable. But I'll try.

I managed to get rid of a seriuos bug and implemented the combining system. When you right click with a wisp on another wisp, they will merge and create a bigger wisp that does more damage. Combining 5 wisps creates a huge wisp that does tons of damage :)

Here's the map if someone is interested in helping ironing out some bugs:

http://www.hiveworkshop.com/forums/pastebin.php?id=ine0nv
 
Level 5
Joined
Oct 26, 2009
Messages
161
I hope someone else actually submits a spell that legitimately summons units in the WC3 sense instead of just abusing a 'unit' as a special effect. So far the closest things are Eccho's land mines and Deaod's ward.
 
Level 28
Joined
Jan 26, 2007
Messages
4,789
I agree, that's quite a remarkable spell, Maker ^^ (never thought of anything like that, never seen it before either), though I think that it's not suitable in many maps :S (I might be mistaken of course...).

Assuming that I don't have more time, here is my (temporary?) submission to the contest.
Too bad I didn't see this contest earlier :/

Spell Description said:
Descending Flames (Q)

Summons Lava Spawns, which come falling out of the sky.
When they touch the ground, they will deal damage to all surrounding enemies and move away from the caster until they are completely spawned and can attack enemies.

Number of spawns: 3
Dmg on impact: (Int x 2) + (25 x Spell Lvl)
Spawn attack dmg: 3 + (7 x Spell Level)
Spawn Duration: 6 + (2 x Spell Level) + (Int / 10) Seconds

Level 1: 28 cooldown, 65 mana cost
Level 1: 30 cooldown, 90 mana cost
Level 1: 32 cooldown, 115 mana cost

Duragon said:
I hope someone else actually submits a spell that legitimately summons units in the WC3 sense instead of just abusing a 'unit' as a special effect. So far the closest things are Eccho's land mines and Deaod's ward.
Well, my spell actually spawns units, which attack and move in a normal wc3 way... but they're uncontrollable (I didn't want them to be controllable, though if you suggest that they should be, I can easily change that).
 

Attachments

  • Descending Flames.w3x
    136.5 KB · Views: 79
Last edited:
Level 16
Joined
Feb 22, 2006
Messages
960
So my final entry....I think no one will have a better documentation :)

attachment.php


70650d1259740882-zephyr-challenge-6-tooltip.jpg


JASS:
/********************************************************************************************
 *  Zephyr Challenge #6 Entry by xD.Schurke
 *
 *      Ritual of Vengeance
 *
 *      Requires:
 *              - JassHelper 0.9.Z.5 by Vexorian
 *              - Table 3.0 by Vexorian
 *              - Intuitive Damage Detection System 1.13 by Rising_Dusk
 *
 *      How to implement the spell?
 *
 *              Copy this trigger into your map and check if also Table and IDDS are in your
 *              map. Then make sure u change all ID variables to your map specific spell/unit
 *              rawcodes (You also can copy the spells/units from the object editor to your
 *              map). 
 *              If you want to change some variables, you can do this in the global variable
 *              declaration part, they are all well descriped, so you will fast find the
 *              variables you may want to edit. The same you can do with the different
 *              formulas: Just change them as needed. The core of the spell shouldn't be
 *              edited unless you know what you do, but you can read through it to learn
 *              something about my coding style and vJass, hence they are well commented.
 *
 *      Some additional information
 *
 *              Why do I use Table for storing the units affected by the Lyrium Shield
 *              instead of an array?
 *              
 *              Well, I just could use a hashtable but I like the userfriendly style of 
 *              Table. In addition it has a better performance for many instances, because
 *              I don't have to look up the stored units/structs in a linear loop, 
 *              but I just can get the table entry by going to the hash related entry.
 *              So the spell will still have a good performance if one uses it some thousand
 *              times.
 *
 *      Content
 *
 *              1. Global - Variable Block
 *                 1.1 ID - Variable Block
 *                 1.2 Int - Variable Block
 *                 1.3 Real - Variable Block
 *                 1.4 String - Variable Block
 *                 1.5 Group - Variable Block 
 *              2. Functions
 *                 2.1 Formulas
 *                 2.2 Filter
 *              3. Core - Part
 *                 3.1 Shield Struct
 *                 3.2 Missile Struct
 *                 3.3 Spirit Struct
 *              4. Initialization - Part
 *                 4.1 Condition
 *                 4.2 Action
 *                 4.3 Initializer
 *
 ********************************************************************************************/ 
scope SpellScope initializer onInit
   /****************************
    * 1.Global - Variable Block*
    ****************************/        
    globals    
       /****************************
        * 1.1 ID - Variable Block  *
        ****************************/
        
        //The DUMMY_ID variable is the one which represents the raw code of your dummy unit
        private constant    integer     DUMMY_ID            =   'n001'
        //The SPELL_ID variable is the one which represents the raw code of the hero/unit spell which is used by the player
        private constant    integer     SPELL_ID            =   'A000'
        //The DMG_BUFF_ID variable is the one which represents the raw code of the ability which grants extra attack damage to the Lyrium Spirit. 
        //I used a item ability with 50 levels which just increases attack damage by increasing the level (more at 3.3 Spirit Struct)
        private constant    integer     DMG_BUFF_ID         =   'A001'
        //The UNIT_ID variable is the one which represents the raw code of the summoned Lyrium Spirit
        private constant    integer     UNIT_ID             =   'n000'        
        //The SHIELD_SPELL_ID is the one which represents the spell which is casted on the player owned hero which summoned the spirit.
        //This "shield" protects the hero (more at 3.1 Shield Struct)
        private constant    integer     SHIELD_SPELL_ID     =   'A002'
        //The SHIELD_BUFF_ID is the one which represents the buff created by the SHIELD_SPELL_ID spell it's used in 3.1 Shield Struct
        private constant    integer     SHIELD_BUFF_ID      =   'B000'
        
        
       /****************************
        * 1.2 Int - Variable Block *
        ****************************/        
        //All integer variables are used in 2.1 Formulas, you can find more information there.
        
        //UNIT_COUNT is a integer variable representing the maximum units from which the summoned spirit profits
        private constant    integer     UNIT_COUNT          =   12
        //UNIT_COUNT_INC is used for the multi-level supporting and represents the additional units per ability level
        private constant    integer     UNIT_COUNT_INC      =   0
        //DAMAGE_BOOST is used for the damage gained by the spirit for each unit sorrounding it.
        private constant    integer     DAMAGE_BOOST        =   2
        //UNIT_BOOST_INC is used for the multi-level supporting and represents the additional damage per ability level
        private constant    integer     DAMAGE_BOOST_INC    =   1
        
        
       /*****************************
        * 1.3 Real - Variable Block *
        *****************************/          
        
        //The INTERVAL variable is used by timers. Those timers are executed each INTERVAL seconds
        private constant    real        INTERVAL            =   0.03125
        //THE DURATION variable is used by the 2.1 Formuals to calculate the spirit duration
        private constant    real        DURATION            =   25.0
        //THE DURATION_INC variable is used by the 2.1 Formuals to calculate the spirit duration
        private constant    real        DURATION_INC        =   10.0
        //THE SHIELD_DUR variable is used by the 2.1 Formuals to calculate the shield duration
        private constant    real        SHIELD_DUR          =   15.0
        //THE SHIELD_DUR_INC variable is used by the 2.1 Formuals to calculate the shield duration
        private constant    real        SHIELD_DUR_INC      =   0.0
        //THE COIL_DURATION variable is used for the coil missile duration, which are send to the units
        private constant    real        COIL_DURATION       =   0.50
        //After SUMON_TIME seconds, which always has to be 2 x COIL_DURATION the Lyrium Spirit is summoned
        private constant    real        SUMMON_TIME         =   COIL_DURATION*2
        //The MISSILE_DURATION is used for the missiles send to sorrounding hostile units
        private constant    real        MISSILE_DURATION    =   1.5
        //Each DAMAGE_INTERVAL the Lyrium Spirit creates new missiles and damages all nearby foes
        private constant    real        DAMAGE_INTERVAL     =   1.5
        //The DAMAGE_RADIUS is the radius where all hostile units are damage
        private constant    real        DAMAGE_RADIUS       =   250.0
        //Each new level the damage radius is increased by DAMAGE_RADIUS_INC
        private constant    real        DAMAGE_RADIUS_INC   =   50.0
        //Each DAMAGE_INTERVAL the spirit deals AOE_DAMAGE to foes
        private constant    real        AOE_DAMAGE          =   2.0
        //AOE_DAMAGE_INC is used for multi-level support
        private constant    real        AOE_DAMAGE_INC      =   1.0
        //COIL_DAMAGE is dealt as damage to units in the beginning of the spell
        private constant    real        COIL_DAMAGE         =   10.0
        //COIL_DAMAGE_INC is used in 2.1 formuals to calculate the damage of each spell level 
        private constant    real        COIL_DAMAGE_INC     =   10.0
        //SHIELD_FACTOR represents the factor with which the sucked energy is devided
        private constant    real        SHIELD_FACTOR       =   2.0
        
        
       /*******************************
        * 1.4 String - Variable Block *
        *******************************/   
        //All following variables represent model pathes for special effects
        
        //SHIELD_SUMMON_GFX is used on the creation of the shield
        private constant    string      SHIELD_SUMMON_GFX   =   "Abilities\\Spells\\Undead\\DeathPact\\DeathPactTarget.mdl"
        //SUMMON_EFFECT is used on the summon of the spirit
        private constant    string      SUMMON_EFFECT       =   "Abilities\\Spells\\Undead\\Darksummoning\\DarkSummonTarget.mdl"
        //COIL_EFFECT represents the model, which is used to visualize the missile
        private constant    string      COIL_EFFECT         =   "Abilities\\Spells\\Undead\\DeathCoil\\DeathCoilMissile.mdl"
        //COIL_DEATH_EFFECT is shown when a missile dies
        private constant    string      COIL_DEATH_EFFECT   =   "Abilities\\Spells\\Undead\\DeathCoil\\DeathCoilSpecialArt.mdl"
        //MISSILE_EFFECT is for the missiles spawned each DAMAGE_INTERVAL
        private constant    string      MISSILE_EFFECT      =   "Abilities\\Weapons\\AvengerMissile\\AvengerMissile.mdl"
        
        
       /*******************************
        * 1.5 Group - Variable Block  *
        *******************************/   
        //The following variables shouldn't be touched, they are nessesary for group issues
        
        //TMPG is a group which is allways only used temporaly see more 4.3 Initializer for the CreateGroup()
        private             group       TMPG                =   null        
        //Always before TMPG is defined the TMPP variable should be set to the owning player
        private             player      TMPP                =   null
        //COND is used for the filter see more 2.2 Filter
        private             boolexpr    COND                =   null
    endglobals

    
   /********************
    * 2. Functions     *
    ********************/  
    //The functions part contains all nessessary stuff which is used for multi level supporting and group issues filter
 
   /********************
    * 2.1 Formulas     *
    ********************/ 
    //Change following formulas if you want to have other results
    
    private function getDuration takes integer lvl returns real
        return (lvl-1)*DURATION_INC+DURATION
    endfunction
    
    private function getShieldDuration takes integer lvl returns real
        return (lvl-1)*SHIELD_DUR_INC+SHIELD_DUR
    endfunction
    
    private function getMaximumUnitCount takes integer lvl returns integer
        return (lvl-1)*UNIT_COUNT_INC+UNIT_COUNT
    endfunction
    
    private function getDamageBoost takes integer lvl returns integer
        return (lvl-1)*DAMAGE_BOOST_INC+DAMAGE_BOOST
    endfunction
    
    private function getAoeDmg takes integer lvl returns real
        return (lvl-1)*AOE_DAMAGE_INC+AOE_DAMAGE
    endfunction
    
    private function getCoilDmg takes integer lvl returns real
        return (lvl-1)*COIL_DAMAGE_INC+COIL_DAMAGE
    endfunction
    
    private function getDamageRadius takes integer lvl returns real
        return (lvl-1)*DAMAGE_RADIUS_INC+DAMAGE_RADIUS
    endfunction

    
   /********************
    * 2.2 Filter       *
    ********************/ 
    //The filter is used for group issues. Units are put in the group variable if following conditions are true
    
    private function filter takes nothing returns boolean
        return IsUnitEnemy(GetFilterUnit(),TMPP) and (GetUnitState(GetFilterUnit(),UNIT_STATE_LIFE)>0) and IsUnitType(GetFilterUnit(),UNIT_TYPE_GROUND) and (GetUnitTypeId(GetFilterUnit())!=DUMMY_ID)
    endfunction
    
    
   /********************
    * 3. Core - Part   *
    ********************/   
    
    
   /**********************
    * 3.1 Shield Struct  *
    **********************/      
    //Everytime a Lyrium Spirit dies it releases a power which protects the caster from physical damage.
    //Here we use a HandleTable and the Intuitive Damage Detection System for absorbing the dealt damage.
    
    private struct shieldStruct
        //The following variables are set in the create method
        private unit target = null          //The target of the shield
        private real duration = 0.0         //How long the shield lasts 
        private real absorb = 0.0           //How much should the shield absorb
        
        private static HandleTable table    //The table stores all units affected by a shield. Why we use table? (see more introduction)
        private static timer tim            //This static timer loops through all instances of this struct to do some things
        private static integer total = 0    //The maximum number of current instances
        private static integer array data   //All instances are stored here for loop through it
        
        //This method is called each INTERVAL by the static timer tim
        private static method callback takes nothing returns nothing
            local thistype this
            local integer i = 0
            loop
                exitwhen i >= thistype.total
                set this = thistype.data[i] //get the struct instance at data[i]
                set this.duration = this.duration - INTERVAL 
                //If following conditions are true we should destroy the instance
                if this.duration <= 0 or this.absorb <= 0 or GetUnitState(this.target,UNIT_STATE_LIFE) <= 0.406 or GetUnitAbilityLevel(this.target,SHIELD_BUFF_ID) <= 0 then
                    set this.total = this.total - 1
                    set this.data[i] = this.data[this.total]
                    set i = i - 1
                    call this.destroy()
                endif
                set i = i + 1
            endloop
            //If there are no instances left, why should the timer still be active?
            if thistype.total == 0 then
                call PauseTimer(thistype.tim)
            endif
        endmethod
        
        //The following method allocates a new instance of this struct for later usage. In addtition all nessesary variables are set
        static method create takes unit target, real absorb, real duration returns thistype
            local thistype this = thistype.allocate()
            //Lets create a dummy which casts a buff on our target, so that also dispell spells can work with this spell
            local unit dummy = CreateUnit(GetOwningPlayer(target),DUMMY_ID,GetUnitX(target),GetUnitY(target),0)
            call UnitAddAbility(dummy,SHIELD_SPELL_ID)
            call IssueTargetOrder(dummy,"innerfire",target)
            call UnitApplyTimedLife(dummy,'BTLF',1.0)
            //Set the variables
            set this.target = target
            set this.absorb = absorb
            set this.duration = duration
            set this.table[target] = this
            //We also need some eye-candy
            call DestroyEffect(AddSpecialEffectTarget(SHIELD_SUMMON_GFX,target,"origin"))
            //If there is no instance of this struct we should start the timer, 'cause just created an instance
            if this.total == 0 then
                call TimerStart(this.tim,INTERVAL,true,function thistype.callback)
            endif
            set this.data[this.total] = this
            set this.total = this.total + 1
            set dummy = null
            return this
        endmethod
        
        //When we destroy an instance this method is called and does the things we want it to do
        private method onDestroy takes nothing returns nothing
            call UnitRemoveAbility(this.target,SHIELD_BUFF_ID)
            call this.table.flush(this.target)
            set this.target = null
        endmethod
        
        //The following methods are used to get to know of all incoming physical damage and if the attacked units has a shield
        private static method condition takes nothing returns boolean
            return GetTriggerDamageType() == DAMAGE_TYPE_ATTACK and thistype.table.exists(GetTriggerDamageTarget())
        endmethod
        
        private static method action takes nothing returns nothing
            local thistype this = thistype.table[GetTriggerDamageTarget()]
            local real life = GetUnitState(this.target,UNIT_STATE_LIFE)
            set this.absorb = this.absorb - GetTriggerDamage()
            call SetUnitState(this.target,UNIT_STATE_LIFE,life+GetTriggerDamage())
        endmethod
        
        private static method onInit takes nothing returns nothing
            local trigger trig = CreateTrigger()
            call TriggerAddCondition(trig,Condition(function thistype.condition))
            call TriggerAddAction(trig,function thistype.action)
            call TriggerRegisterDamageEvent(trig,0)
            set trig = null
            set thistype.table = HandleTable.create()
            set thistype.tim = CreateTimer()
        endmethod
    endstruct
    
    
   /**********************
    * 3.2 Missile Struct *
    **********************/ 
    //The missile struct is just an object which represents some moving effects but with no more ususage

    private struct missileStruct
        private unit missile = null         //The missile itself should be an unit
        private unit target = null          //Where should the missile move to
        private effect gfx = null           //The effect of the missile
        private real duration = 0.0         //How long the missile lasts
        private real damage = 0.0           //How much damage on impact
        
        private static timer tim            //This static timer loops through all instances of this struct to do some things
        private static integer total = 0    //The maximum number of current instances
        private static integer array data   //All instances are stored here for loop through it
        
        //This method is called each INTERVAL by the static timer tim
        private static method callback takes nothing returns nothing
            local thistype this
            local integer i = 0
            //The real variables are needed fore some mathematical calculations
            local real x1 = 0.0
            local real x2 = 0.0
            local real x3 = 0.0
            local real y1 = 0.0
            local real y2 = 0.0
            local real y3 = 0.0
            local real distance = 0.0
            local real angle = 0.0
            loop
                exitwhen i >= thistype.total
                set this = thistype.data[i]                               
                //This part is used to calculate the movement of the missile
                set x1 = GetUnitX(this.missile)
                set y1 = GetUnitY(this.missile)
                set x2 = GetUnitX(this.target)
                set y2 = GetUnitY(this.target)
                set distance = SquareRoot((x2-x1)*(x2-x1)+(y2-y1)*(y2-y1))/(this.duration/INTERVAL)
                set angle = Atan2(y2-y1,x2-x1)
                set x3 = x1 + distance * Cos(angle)
                set y3 = y1 + distance * Sin(angle)
                call SetUnitPosition(this.missile,x3,y3)
                //***********************************************************
                //Destroy the missile if it reached the target unit
                if this.duration == 0 then
                    set this.total = this.total - 1
                    set this.data[i] = this.data[this.total]
                    set i = i - 1
                    call this.destroy()
                endif
                set this.duration = this.duration - INTERVAL 
                set i = i + 1
            endloop
            if thistype.total == 0 then
                call PauseTimer(thistype.tim)
            endif
        endmethod
        
        //The following method allocates a new instance of this struct for later usage. In addtition all nessesary variables are set
        static method create takes player owner, string effectPath, real x1, real y1, unit target,real duration,real damage returns thistype
            local thistype this = thistype.allocate()
            //create the unit + effect which will represent an moving object
            set this.missile = CreateUnit(owner,DUMMY_ID,x1,y1,0)
            call AddSpecialEffectTarget(effectPath,this.missile,"origin")
            set this.target = target
            set this.duration = duration
            set this.damage = damage
            if this.total == 0 then
                call TimerStart(this.tim,INTERVAL,true,function thistype.callback)
            endif
            set this.data[this.total] = this
            set this.total = this.total + 1
            return this
        endmethod
        
        private method onDestroy takes nothing returns nothing
            call UnitDamageTargetEx(this.missile,this.target,this.damage,ATTACK_TYPE_NORMAL,DAMAGE_TYPE_SPELL,true)
            call RemoveUnit(this.missile)
            call DestroyEffect(this.gfx)
            call DestroyEffect(AddSpecialEffect(COIL_DEATH_EFFECT,GetUnitX(this.target),GetUnitY(this.target)))            
            set this.target = null
            set this.missile = null
            set this.gfx = null
        endmethod
        
        private static method onInit takes nothing returns nothing
            set thistype.tim = CreateTimer()
        endmethod
    endstruct

    
   /**********************
    * 3.3 Spirit Struct  *
    **********************/     
    //The spiritStruct is the "main" struct and it represents the Lyrium Spirit in general and its actions
    
    private struct spiritStruct
        public unit caster = null           //Who casted the spell       
        public real spellX = 0.0            //The X-Coordiante of the spell targeted area
        public real spellY = 0.0            //The Y-Coordiante of the spell targeted area
        public integer unitsInRange = 0     //Is set to the number of units in range (maximum is equal to getMaximumUnitCount see also 2.1 Formulas)
        
        private unit summon = null          //This is the Lyrium Spirit
        private unit summonRitual = null    //Just an unit representing the summon effect
        private effect ritualEffect = null  //The effect used by summonRitual
        private real timePassed = 0.0       //How long did the spirit allready lasts
        private real damageTime = 0.0       //This counts to DAMAGE_TIME and then again set to 0
        private real damageDealt = 0.0      //We must store the dealt damage to calculate the shield-strength later
        private boolean isSummoned = false  //This is set to true if the spirit is summoned
        private boolean coilWave = false    //Just needed for the summoning
        
        private static timer tim            //This static timer loops through all instances of this struct to do some things
        private static integer total = 0    //The maximum number of current instances
        private static integer array data   //All instances are stored here for loop through it

        //This method is called each INTERVAL by the static timer tim
        private static method callback takes nothing returns nothing
            local thistype this
            local integer i = 0
            //The following 2 variables are used for group-loop reasons
            local integer j = 0
            local unit u = null
            loop
                exitwhen i >= thistype.total
                set this = thistype.data[i]
                set this.timePassed = this.timePassed + INTERVAL
                set this.damageTime = this.damageTime + INTERVAL 
                //If the following conditions are true we finally can summon the spirit
                if this.timePassed >= SUMMON_TIME and this.isSummoned != true then
                    set this.summon = CreateUnit(GetOwningPlayer(this.caster),UNIT_ID,this.spellX,this.spellY,0)
                    //The ritual effect is no more needed so lets destroy it
                    call RemoveUnit(this.summonRitual)
                    call DestroyEffect(this.ritualEffect)
                    //How long should the spirit lasts see also 2.1 Formuals
                    call UnitApplyTimedLife(this.summon,'BTLF',getDuration(GetUnitAbilityLevel(this.caster,SPELL_ID)))  
                    //Should the spirit get some extra damage lets check it!
                    call UnitAddAbility(this.summon,DMG_BUFF_ID)
                    call SetUnitAbilityLevel(this.summon,DMG_BUFF_ID,this.unitsInRange*getDamageBoost(GetUnitAbilityLevel(this.caster,SPELL_ID)))
                    set this.damageDealt = this.unitsInRange*getCoilDmg(GetUnitAbilityLevel(this.caster,SPELL_ID))
                    if this.unitsInRange == 0 then
                        call UnitRemoveAbility(this.summon,DMG_BUFF_ID)
                    endif
                    set this.isSummoned = true 
                //Each DAMAGE_INTERVAL we should damage all sorrounding foes , so lets send some missiles to them and save the dealt damage
                elseif this.timePassed >= SUMMON_TIME and this.damageTime >= DAMAGE_INTERVAL then 
                    set TMPP = GetOwningPlayer(this.caster)
                    call GroupEnumUnitsInRange(TMPG,GetUnitX(this.summon),GetUnitY(this.summon),getDamageRadius(GetUnitAbilityLevel(this.caster,SPELL_ID)),COND)
                    loop
                        set u = FirstOfGroup(TMPG)
                        exitwhen u == null or j >= getMaximumUnitCount(GetUnitAbilityLevel(this.caster,SPELL_ID))  
                        set j = j + 1
                        call missileStruct.create(GetOwningPlayer(this.caster),MISSILE_EFFECT,GetUnitX(this.summon),GetUnitY(this.summon),u,MISSILE_DURATION,getAoeDmg(GetUnitAbilityLevel(this.caster,SPELL_ID)))
                        set this.damageDealt = this.damageDealt + getAoeDmg(GetUnitAbilityLevel(this.caster,SPELL_ID))
                        call GroupRemoveUnit(TMPG,u)
                    endloop                    
                    set this.damageTime = 0.0
                //We just need that part for eye-candy reasons: In general it sends missiles from the units to the summoning point
                elseif this.timePassed >= COIL_DURATION and this.coilWave != true then
                    set this.summonRitual = CreateUnit(GetOwningPlayer(this.caster),DUMMY_ID,this.spellX,this.spellY,0)
                    set this.ritualEffect = AddSpecialEffectTarget(SUMMON_EFFECT,this.summonRitual,"origin")
                    set TMPP = GetOwningPlayer(this.caster)
                    call GroupEnumUnitsInRange(TMPG,this.spellX,this.spellY,getDamageRadius(GetUnitAbilityLevel(this.caster,SPELL_ID)),COND)
                    loop
                        set u = FirstOfGroup(TMPG)
                        exitwhen u == null or j >= getMaximumUnitCount(GetUnitAbilityLevel(this.caster,SPELL_ID))  
                        set j = j + 1
                        call missileStruct.create(GetOwningPlayer(this.caster),COIL_EFFECT,GetUnitX(u),GetUnitY(u),this.summonRitual,COIL_DURATION,0)
                        call GroupRemoveUnit(TMPG,u)
                    endloop  
                    set j = 0
                    set this.coilWave = true
                endif
                //This if-block is needed to check if there are units arround and if the Lyrium Spirit should get some extra damage (Eeach Interval)
                if this.timePassed >= SUMMON_TIME and this.isSummoned == true then
                    set TMPP = GetOwningPlayer(this.caster)
                    call GroupEnumUnitsInRange(TMPG,GetUnitX(this.summon),GetUnitY(this.summon),getDamageRadius(GetUnitAbilityLevel(this.caster,SPELL_ID)),COND)
                    loop
                        set u = FirstOfGroup(TMPG)
                        exitwhen u == null or j >= getMaximumUnitCount(GetUnitAbilityLevel(this.caster,SPELL_ID))  
                        set j = j + 1
                        call GroupRemoveUnit(TMPG,u)
                    endloop  
                    if GetUnitAbilityLevel(this.summon,DMG_BUFF_ID) <= 0 then
                        call UnitAddAbility(this.summon,DMG_BUFF_ID)
                    endif
                    set this.unitsInRange = j
                    call SetUnitAbilityLevel(this.summon,DMG_BUFF_ID,this.unitsInRange*getDamageBoost(GetUnitAbilityLevel(this.caster,SPELL_ID)))
                    if this.unitsInRange == 0 then
                        call UnitRemoveAbility(this.summon,DMG_BUFF_ID)
                    endif  
                    set j = 0
                endif
                //Destroy this struct if following coditions are true
                if (this.timePassed >= getDuration(GetUnitAbilityLevel(this.caster,SPELL_ID)) or GetUnitState(this.summon,UNIT_STATE_LIFE) <= 0.406) and this.isSummoned == true then
                    set this.total = this.total - 1
                    set this.data[i] = this.data[this.total]
                    set i = i - 1
                    call shieldStruct.create(this.caster,this.damageDealt/SHIELD_FACTOR,getShieldDuration(GetUnitAbilityLevel(this.caster,SPELL_ID)))
                    call this.destroy()
                endif
                set i = i + 1
            endloop
            if thistype.total == 0 then
                call PauseTimer(thistype.tim)
            endif
        endmethod
        
        static method create takes nothing returns thistype
            local thistype this = thistype.allocate()
            if this.total == 0 then
                call TimerStart(this.tim,INTERVAL,true,function thistype.callback)
            endif
            set this.data[this.total] = this
            set this.total = this.total + 1
            return this
        endmethod
        
        private method onDestroy takes nothing returns nothing
            set this.caster = null
            set this.summon = null
            set this.ritualEffect = null            
        endmethod
        
        private static method onInit takes nothing returns nothing
            set thistype.tim = CreateTimer()
        endmethod
    endstruct

   /*****************************
    * 4. Initialization - Part  *
    *****************************/ 
    
    
   /******************
    * 4.1 Condition  *
    ******************/ 
    //When a casted spell is equal to this spell we can call the action-function
    
    private function spellCond takes nothing returns boolean
        return GetSpellAbilityId() == SPELL_ID
    endfunction
    
    
   /******************
    * 4.2 Action     *
    ******************/     
    //Here we setup the main struct and send missiles to all foes in the targeted area
    
    private function spellAction takes nothing returns nothing
        //We need an isntance of the spiritStruct to have some nice effects :P
        local spiritStruct this = spiritStruct.create()
        local integer i = 0
        local unit u = null
        //Set all public variables of the spiritStruct instance
        set this.spellX = GetSpellTargetX()
        set this.spellY = GetSpellTargetY()
        set this.caster = GetTriggerUnit()
        set TMPP = GetOwningPlayer(this.caster)
        call GroupEnumUnitsInRange(TMPG,this.spellX,this.spellY,getDamageRadius(GetUnitAbilityLevel(this.caster,SPELL_ID)),COND)
        loop
            set u = FirstOfGroup(TMPG)
            exitwhen u == null or i >= getMaximumUnitCount(GetUnitAbilityLevel(this.caster,SPELL_ID))  
            set i = i + 1
            call missileStruct.create(GetOwningPlayer(this.caster),COIL_EFFECT,GetUnitX(this.caster),GetUnitY(this.caster),u,COIL_DURATION,getCoilDmg(GetUnitAbilityLevel(this.caster,SPELL_ID)))
            call GroupRemoveUnit(TMPG,u)
        endloop
        set this.unitsInRange = i
    endfunction
    
    
   /*******************
    * 4.3 Initializer *
    *******************/ 
    //This function initializes everything... it's needed :)
    
    private function onInit takes nothing returns nothing
        local trigger trig = CreateTrigger()
        local unit dummy = null
        local integer index = 0
        loop
            call TriggerRegisterPlayerUnitEvent(trig, Player(index), EVENT_PLAYER_UNIT_SPELL_EFFECT, null)
            set index = index + 1
            exitwhen index == bj_MAX_PLAYER_SLOTS
        endloop
        call TriggerAddCondition(trig,Condition(function spellCond))
        call TriggerAddAction(trig, function spellAction)
        set trig = null        
        //Setup group Issues
        set TMPG = CreateGroup()
        set COND = Filter(function filter)
        
        //Preload-Part so no future lags
        set dummy = CreateUnit(Player(14),DUMMY_ID,0,0,0)
        call UnitAddAbility(dummy,DMG_BUFF_ID)
        call RemoveUnit(dummy)
        set dummy = null
        
        call Preload(SHIELD_SUMMON_GFX)
        call Preload(SUMMON_EFFECT)
        call Preload(COIL_EFFECT)
        call Preload(COIL_DEATH_EFFECT)
        call Preload(MISSILE_EFFECT)
        call PreloadStart()
    endfunction
endscope
 

Attachments

  • RitualOfVengeance.jpg
    RitualOfVengeance.jpg
    2.5 KB · Views: 337
  • Zephyr Challenge #6 Entry xD.Schurke.w3x
    85.1 KB · Views: 100
Level 13
Joined
Jun 22, 2004
Messages
783
Thanks :)

Here's the current version, which might be my final submission, because I might not have enough time to organize and optimize code, improve tooltips, create terrain and make the spell more customizeable. But I'll try.

I managed to get rid of a seriuos bug and implemented the combining system. When you right click with a wisp on another wisp, they will merge and create a bigger wisp that does more damage. Combining 5 wisps creates a huge wisp that does tons of damage :)

Here's the map if someone is interested in helping ironing out some bugs:

http://www.hiveworkshop.com/forums/pastebin.php?id=ine0nv

I tested out your final version, and it's a keen spell, quite original too.

When moved all wisps on one target for the first time however, it didn't really bug but special effects on the wisp weren't removed, you might want to look into that.
 
Level 37
Joined
Mar 6, 2006
Messages
9,240
Contestant : Maker

Spell : Nudgeballs v1.01
Status: Could be considered as final
Nudgeballs_7.jpg


Nudgeballs_4b.jpg

Summoning Nudgeballs

Nudgeballs_5b.jpg

Five wisps merged into one big wisp

Nudgeballs_6b.jpg

Nudgeballs having a go at some orcs


Maybe if I have time in the morning I'll do one more update, but this is pretty much it, and now I have to quit spellmaking for today :)

I'm really happy about how this turned out, especially given I only worked on this today. All in all it took about 6 hours of nothing but working on this :)

Nudgeballs v1.01

EDIT: Updated to v1.01

v1.01
Added maximum range for the wisp when it has acquired a target. If the wisp goes too far away from the caster, it will detonate.
Reduced duration to 12 seconds from 15 seconds.
Edited tooltip.
 
Last edited:
Level 25
Joined
Jun 5, 2008
Messages
2,572
Duragon said:
I hope someone else actually submits a spell that legitimately summons units in the WC3 sense instead of just abusing a 'unit' as a special effect. So far the closest things are Eccho's land mines and Deaod's ward.

Meh i only joined to refresh my memory of vJass, learn something new and see who wins =)

Btw you should chill a bit, it is all for fun ^^

@Maker

Please put the pics in hidden tag, so your post doesn't strech a mile.

@xD.Schurke

You are the guy i want for documentation in my future systems =)
Really detailed, thumbs up ^^
 
Level 6
Joined
Jan 31, 2009
Messages
166
Entery

Contestant : Arcmage
Spell : Biomancy

Well all the other contestants spells are pretty incredible but please at least take a look at my modest spell (It was my first ever contest)

On the positive side the spell fits in the theme quite well (I think)

I didn't know the proper format for submisions I hope this is expectable.


The spell takes 3/4/5 Critters or trees in its Aoe and turns them into creatures under your control



I balanced the spell based on the default blizzard spell Force of nature.
My spell summons 1 more unit and has a greater Aoe.
The units summoned based on trees are weaker than Force of nature summons but the summons based off of critters are about equal (because in most maps critters are significantly more rare than trees).
The spell costs 45 more mana than force of nature and has a Cool Down 15 seconds greater



None that I know of The spell doesn't leak (as far as I know) and when I tested via turning the spells cool down to 0 using "thereisnospoon" and spaming it about 100 times repetitively it didn't lag at all.



Spell Created for Zephyr challenge #6
Spell by Arcmage@useast
Terrain is Tristifal glade by Blizzard with randomised trees and criter (contains every tree and criter type in the game for best testing)
Credits to oh_snap for Biohazard Icon
Credits to Jetfanginfeno for the EarthNova model
Both the icon and model can be found on Hiveworkshop.com
No systems where used
 

Attachments

  • Biomancy.w3x
    93.3 KB · Views: 111
Level 23
Joined
Nov 29, 2006
Messages
2,482
Suddenly, alot more submissions have arrived. That's great, but it will also mean I will not look through them now:p Ill do so when I have time.

Duragon said:
I hope someone else actually submits a spell that legitimately summons units in the WC3 sense instead of just abusing a 'unit' as a special effect. So far the closest things are Eccho's land mines and Deaod's ward.

Well and your own ofc, and I think Ive seen some more of them now. Ap0calypse spell is suitable I think... Schurkes as well, I mean it looks promising:p But meh yeah, I was entering like Kingz, to refresh my jass. It's been several months since I made something serious.
 
Level 10
Joined
Jun 1, 2008
Messages
485
Ok, here's my Submission

Contestant Name: Mage_Goo
Entry Name: Thunder Bird

Thunder Bird
Icon.jpg
Call bird that place its egg in random location in targeted area. Egg will slowly burn mana of nearby enemy unit every second. After some time, egg will hatch and a pack of thunder bird will spawn and patrolling targeted area. Thunder Bird will attack random enemy in area, damaging it and slowing its movement.

Level 1 - Hatch after 1 second. Burn 50 mana every second. Spawn 3 Thunder Bird that deal 50 damage and 25% slow. Last 5 second and Affect 250 AoE.
Level 2 - Hatch after 1.5 second. Burn 75 mana every second. Spawn 4 Thunder Bird that deal 75 damage and 35% slow. Last 10 second and Affect 350 AoE.
Level 3 - Hatch after 2 second. Burn 100 mana every second. Spawn 5 Thunder Bird that deal 100 damage and 45% slow. Last 15 second and Affect 450 AoE.
Level 4 - Hatch after 2.5 second. Burn 125 mana every second. Spawn 6 Thunder Bird that deal 125 damage and 55% slow. Last 20 second and Affect 550 AoE.


well, here's the code
JASS:
scope ThunderBird initializer InitTrig_Initialize
    globals
        private constant integer SpellID        = 'A000'
        private constant integer DummyID        = 'n000'
        private constant string DummyAttach     = "chest"
        
        private constant real Duration          = 5.
        private constant real DurationIncr      = 5.
        private constant real EggDuration       = 1.
        private constant real EggDurationIncr   = 0.5
        
        private constant real BirdHeight        = 100
        private constant real PassingBirdHeight = 400
        
        private constant real Damage            = 50.
        private constant real DamageIncr        = 25.
        private constant real ManaDmg           = 50.
        private constant real ManaIncr          = 25.
        
        private constant real SlowAmount        = 0.25
        private constant real SlowIncr          = 0.1
        private constant real SlowDur           = 1.
        private constant real SlowDurIncr       = 0.5
        
        private constant integer BirdSum        = 3
        private constant integer BirdIncr       = 1
        
        private constant real AoE               = 250.
        private constant real AoEIncr           = 100.
        private constant real ManaAoE           = 100.
        private constant real ManaAoEIncr       = 25.
        
        private constant real MoveSpeed         = 500.
        private constant real AngSpeed          = 50.
        
        private constant string BirdModel       = "Abilities\\Weapons\\KeeperGroveMissile\\KeeperGroveMissile.mdl"
        private constant string PassBirdModel   = "units\\human\\phoenix\\phoenix.mdl"
        private constant string EggModel        = "Units\\Human\\Phoenix\\PhoenixEgg.mdl"
        private constant string AttachEffect    = "Abilities\\Spells\\Orc\\Purge\\PurgeBuffTarget.mdl"
        private constant string DeathEffect     = "Abilities\\Weapons\\Bolt\\BoltImpact.mdl"
        private constant string BirthEffect     = "Abilities\\Spells\\Other\\Monsoon\\MonsoonBoltTarget.mdl"
        private constant string DmgEffect       = "Abilities\\Weapons\\FarseerMissile\\FarseerMissile.mdl"
        private constant string ManaEffect      = "Abilities\\Weapons\\ProcMissile\\ProcMissile.mdl"
        private constant string BuffEffect      = "Abilities\\Spells\\Items\\AIlb\\AIlbSpecialArt.mdl"
        
        private constant real TimeOut           = 0.01
                                                
        private constant attacktype ATT         = ATTACK_TYPE_NORMAL
        private constant damagetype DGT         = DAMAGE_TYPE_NORMAL
        private constant weapontype WPT         = WEAPON_TYPE_WHOKNOWS
        
        private real array R
    endglobals
    private struct Struct3
        private unit Affected
        private real SlowAmount
        private real TimeLeft
        private effect Sfx
        
        static group Buffed = CreateGroup()
        
        private static Struct3 array Index
        private static integer Total = 0
        private static timer Timer = CreateTimer()
        
        static method Loop takes nothing returns nothing
            local Struct3 dat
            local integer i = 0
            loop
                exitwhen i >= Struct3.Total
                set dat = Struct3.Index[i]
                set dat.TimeLeft = dat.TimeLeft-TimeOut
                if dat.TimeLeft <= 0. then
                    call SetUnitMoveSpeed(dat.Affected,GetUnitMoveSpeed(dat.Affected)+dat.SlowAmount)
                    call DestroyEffect(dat.Sfx)
                    if IsUnitInGroup(dat.Affected,Struct3.Buffed) then
                        call GroupRemoveUnit(Struct3.Buffed,dat.Affected)
                    endif
                    call dat.destroy()
                    set Struct3.Total = Struct3.Total-1
                    set Struct3.Index[i] = Struct3.Index[Struct3.Total]
                    set i = i-1
                endif
                set i = i+1
            endloop
            if Struct3.Total == 0 then
                call PauseTimer(Struct3.Timer)
            endif
        endmethod
        
        static method Create takes unit u, real SlowAmount, real Duration, string Sfx returns nothing
            local Struct3 dat = Struct3.allocate()
            set dat.Affected = u
            call SetUnitMoveSpeed(u,GetUnitMoveSpeed(u)-SlowAmount)
            set dat.SlowAmount = SlowAmount
            set dat.TimeLeft = Duration
            set dat.Sfx = AddSpecialEffectTarget(Sfx,u,"chest")
            if Struct3.Total == 0 then
                call TimerStart(Struct3.Timer,TimeOut,true,function Struct3.Loop)
            endif
            set Struct3.Index[Struct3.Total] = dat
            set Struct3.Total = Struct3.Total+1
        endmethod
    endstruct
    
    private struct Struct1
        private unit Caster
        private unit Bird
        private unit Target
        private real Angle
        private real UnitX
        private real UnitY
        private real CentralX
        private real CentralY
        private real TimeLeft
        private real HatchTime
        private real Area
        private integer ActID
        private integer level
        private effect Sfx
        private effect Sfx2
        
        private static unit Temp
        
        private static Struct1 array Index
        private static integer Total = 0
        private static timer Timer = CreateTimer()
        
        static method CanTargeted takes nothing returns boolean
            if not IsUnitEnemy(GetFilterUnit(), GetOwningPlayer(Struct1.Temp))then
                return false
            endif
            if IsUnitType(GetFilterUnit(), UNIT_TYPE_MAGIC_IMMUNE) then
                return false
            endif
            if IsUnitType(GetFilterUnit(), UNIT_TYPE_DEAD) then
                return false
            endif
            return true
        endmethod
        
        static method Loop takes nothing returns nothing
            local Struct1 dat
            local integer i = 0
            local group g = CreateGroup()
            local unit u
            local boolexpr filter
            loop
                exitwhen i >= Struct1.Total
                set dat = Struct1.Index[i]
                if dat.ActID != 0 then
                    set dat.TimeLeft = dat.TimeLeft-TimeOut
                endif
                if dat.ActID == 0 then
                    set dat.HatchTime = dat.HatchTime-TimeOut
                    set Struct1.Temp = dat.Caster
                    set filter = Condition(function Struct1.CanTargeted)
                    call GroupEnumUnitsInRange(g,GetUnitX(dat.Bird),GetUnitY(dat.Bird),ManaAoE+(ManaAoEIncr*dat.level),filter)
                    loop
                        set u = FirstOfGroup(g)
                        exitwhen u == null
                        call GroupRemoveUnit(g,u)
                        set R[0] = GetUnitState(u,UNIT_STATE_MANA)-(ManaDmg+(ManaIncr*I2R(dat.level)))*TimeOut
                        call SetUnitState(u,UNIT_STATE_MANA,R[0])
                        call DestroyEffect(AddSpecialEffect(ManaEffect,GetUnitX(u),GetUnitY(u)))
                    endloop
                    set Struct1.Temp = null
                    call DestroyBoolExpr(filter)
                    if dat.HatchTime <= 0. then
                        call DestroyEffect(AddSpecialEffect(BirthEffect,GetUnitX(dat.Bird),GetUnitY(dat.Bird))) 
                        call DestroyEffect(dat.Sfx)
                        set dat.Sfx = AddSpecialEffectTarget(BirdModel,dat.Bird,DummyAttach)
                        set dat.Sfx2 = AddSpecialEffectTarget(AttachEffect,dat.Bird,DummyAttach)
                        call SetUnitFlyHeight(dat.Bird,BirdHeight,100.)
                        set dat.ActID = 1
                    endif
                elseif dat.ActID == 1 then
                    set dat.Angle = dat.Angle+AngSpeed*TimeOut
                    set dat.UnitX = dat.CentralX+dat.Area*Cos(dat.Angle*bj_DEGTORAD)
                    set dat.UnitY = dat.CentralY+dat.Area*Sin(dat.Angle*bj_DEGTORAD)
                    set R[0] = Atan2(dat.UnitY-GetUnitY(dat.Bird),dat.UnitX-GetUnitX(dat.Bird))
                    set R[1] = GetUnitX(dat.Bird)+(MoveSpeed*TimeOut)*Cos(R[0])
                    set R[2] = GetUnitY(dat.Bird)+(MoveSpeed*TimeOut)*Sin(R[0])
                    call SetUnitX(dat.Bird,R[1])
                    call SetUnitY(dat.Bird,R[2])
                    call SetUnitFacing(dat.Bird,R[0]*bj_RADTODEG)
                    set R[3] = R[1]-dat.UnitX
                    set R[4] = R[2]-dat.UnitY
                    set R[5] = SquareRoot(R[3]*R[3]+R[4]*R[4])
                    if R[5] <= 100. then
                        set dat.ActID = 2
                    endif
                elseif dat.ActID == 2 then
                    set dat.Angle = dat.Angle+AngSpeed*TimeOut
                    set dat.UnitX = dat.CentralX+dat.Area*Cos(dat.Angle*bj_DEGTORAD)
                    set dat.UnitY = dat.CentralY+dat.Area*Sin(dat.Angle*bj_DEGTORAD)
                    call SetUnitX(dat.Bird,dat.UnitX)
                    call SetUnitY(dat.Bird,dat.UnitY)
                    call SetUnitFacing(dat.Bird,dat.Angle+90.)
                    set Struct1.Temp = dat.Caster
                    set filter = Condition(function Struct1.CanTargeted)
                    call GroupEnumUnitsInRange(g,dat.CentralX,dat.CentralY,dat.Area,filter)
                    loop
                        set u = FirstOfGroup(g)
                        exitwhen u == null
                        call GroupRemoveUnit(g,u)
                        if (not IsUnitInGroup(u,Struct3.Buffed)) and (dat.Target == null) then
                            call GroupAddUnit(Struct3.Buffed,u)
                            set dat.Target = u
                            set dat.ActID = 3
                        endif
                    endloop
                    call DestroyBoolExpr(filter)
                    set Struct1.Temp = null
                    if dat.Angle >= 360. then
                        set dat.Angle = dat.Angle-360.
                    endif
                elseif dat.ActID == 3 then
                    set dat.Angle = dat.Angle+AngSpeed*TimeOut
                    set dat.UnitX = dat.CentralX+dat.Area*Cos(dat.Angle*bj_DEGTORAD)
                    set dat.UnitY = dat.CentralY+dat.Area*Sin(dat.Angle*bj_DEGTORAD)
                    set R[0] = bj_RADTODEG*Atan2(GetUnitY(dat.Target)-GetUnitY(dat.Bird),GetUnitX(dat.Target)-GetUnitX(dat.Bird))
                    set R[1] = GetUnitX(dat.Bird)+(MoveSpeed*TimeOut)*Cos(R[0]*bj_DEGTORAD)
                    set R[2] = GetUnitY(dat.Bird)+(MoveSpeed*TimeOut)*Sin(R[0]*bj_DEGTORAD)
                    set R[3] = GetUnitX(dat.Target)-R[1]
                    set R[4] = GetUnitY(dat.Target)-R[2]
                    set R[5] = SquareRoot(R[3]*R[3]+R[4]*R[4])
                    call SetUnitX(dat.Bird,R[1])
                    call SetUnitY(dat.Bird,R[2])
                    call SetUnitFacing(dat.Bird,R[0])
                    if R[5] <= 100 then
                        call DestroyEffect(AddSpecialEffect(DmgEffect,GetUnitX(dat.Target),GetUnitY(dat.Target)))
                        call UnitDamageTarget(dat.Caster,dat.Target,Damage+(DamageIncr*dat.level),true,false,ATT,DGT,WPT)
                        call Struct3.Create(dat.Target,GetUnitMoveSpeed(dat.Target)*(SlowAmount+(SlowIncr*dat.level)),SlowDur+(SlowDurIncr*dat.level),BuffEffect)
                        set dat.Target = null
                        set dat.ActID = 4
                    endif
                    if dat.Angle >= 360. then
                        set dat.Angle = dat.Angle-360.
                    endif
                elseif dat.ActID == 4 then
                    set dat.Angle = dat.Angle+AngSpeed*TimeOut
                    set dat.UnitX = dat.CentralX+dat.Area*Cos(dat.Angle*bj_DEGTORAD)
                    set dat.UnitY = dat.CentralY+dat.Area*Sin(dat.Angle*bj_DEGTORAD)
                    set R[0] = bj_RADTODEG*Atan2(dat.UnitY-GetUnitY(dat.Bird),dat.UnitX-GetUnitX(dat.Bird))
                    set R[1] = GetUnitX(dat.Bird)+(MoveSpeed*TimeOut)*Cos(R[0]*bj_DEGTORAD)
                    set R[2] = GetUnitY(dat.Bird)+(MoveSpeed*TimeOut)*Sin(R[0]*bj_DEGTORAD)
                    set R[3] = GetUnitX(dat.Bird)-dat.UnitX
                    set R[4] = GetUnitY(dat.Bird)-dat.UnitY
                    set R[5] = SquareRoot(R[3]*R[3]+R[4]*R[4])
                    call SetUnitX(dat.Bird,R[1])
                    call SetUnitY(dat.Bird,R[2])
                    call SetUnitFacing(dat.Bird,R[0])
                    if R[5] <= 100 then
                        call SetUnitX(dat.Bird,dat.UnitX)
                        call SetUnitY(dat.Bird,dat.UnitY)
                        call SetUnitFacing(dat.Bird,dat.Angle+90.)
                        set dat.ActID = 2
                    endif
                    if dat.Angle >= 360. then
                        set dat.Angle = dat.Angle-360.
                    endif
                endif
                if dat.TimeLeft <= 0 then
                    call DestroyEffect(AddSpecialEffectTarget(DeathEffect,dat.Bird,DummyAttach))
                    call DestroyEffect(dat.Sfx)
                    call DestroyEffect(dat.Sfx2)
                    call UnitApplyTimedLife(dat.Bird,'BTLF',0.5)
                    set dat.Caster = null
                    set dat.Bird = null
                    set dat.Target = null
                    call dat.destroy()
                    set Struct1.Total = Struct1.Total-1
                    set Struct1.Index[i] = Struct1.Index[Struct1.Total]
                    set i = i-1
                endif
                set i = i+1
            endloop
            call DestroyGroup(g)
            set g = null
            set u = null
            if Struct1.Total == 0 then
                call PauseTimer(Struct1.Timer)
            endif
        endmethod
        
        static method Start takes unit Caster, real BirdSum, real Counter, real X, real Y, real Time, real Time2, integer level returns nothing
            local Struct1 dat = Struct1.allocate()
            set dat.Caster = Caster
            set dat.ActID = 0
            set dat.level = level
            set dat.Angle = (360./BirdSum)*Counter
            set dat.TimeLeft = Time
            set dat.HatchTime = Time2
            set dat.CentralX = X
            set dat.CentralY = Y
            set dat.Area = AoE+AoEIncr*I2R(level)
            set dat.UnitX = X+dat.Area*Cos(dat.Angle*bj_DEGTORAD)
            set dat.UnitY = Y+dat.Area*Sin(dat.Angle*bj_DEGTORAD)
            set R[1] = X+GetRandomReal(0.,dat.Area)*Cos(GetRandomReal(0.,360.)*bj_DEGTORAD)
            set R[2] = Y+GetRandomReal(0.,dat.Area)*Sin(GetRandomReal(0.,360.)*bj_DEGTORAD)
            set dat.Bird = CreateUnit(GetOwningPlayer(Caster),DummyID,R[1],R[2],0.)
            call UnitAddAbility(dat.Bird,'Arav')
            call UnitRemoveAbility(dat.Bird,'Arav')
            call SetUnitFlyHeight(dat.Bird,0.,0.)
            set dat.Sfx = AddSpecialEffectTarget(EggModel,dat.Bird,DummyAttach)
            if Struct1.Total == 0 then
                call TimerStart(Struct1.Timer, TimeOut, true, function Struct1.Loop)
            endif
            set Struct1.Index[Struct1.Total] = dat
            set Struct1.Total = Struct1.Total+1
        endmethod
    endstruct
    
    private struct Struct2
        private unit Caster
        private unit PassingBird
        private real CentralX
        private real CentralY
        private integer level
        private real Time
        private real Time2
        private effect Sfx
        
        private static Struct2 array Index
        private static integer Total = 0
        private static timer Timer = CreateTimer()
        
        static method Loop takes nothing returns nothing
            local Struct2 dat
            local integer i = 0
            loop
                exitwhen i == Struct2.Total
                set dat = Struct2.Index[i]
                set R[0] = GetUnitFacing(dat.PassingBird)
                set R[1] = GetUnitX(dat.PassingBird)+(MoveSpeed*TimeOut)*Cos(R[0]*bj_DEGTORAD)
                set R[2] = GetUnitY(dat.PassingBird)+(MoveSpeed*TimeOut)*Sin(R[0]*bj_DEGTORAD)
                set R[3] = dat.CentralX-R[1]
                set R[4] = dat.CentralY-R[2]
                set R[5] = SquareRoot(R[3]*R[3]+R[4]*R[4])
                call SetUnitX(dat.PassingBird,R[1])
                call SetUnitY(dat.PassingBird,R[2])
                if R[5] <= 100. then
                    set R[6] = I2R(BirdSum+(BirdIncr*dat.level))
                    set R[7] = 0.
                    loop
                        exitwhen R[7] == R[6]
                        call Struct1.Start(dat.Caster,R[6],R[7],dat.CentralX,dat.CentralY,dat.Time,dat.Time2,dat.level)
                        set R[7] = R[7]+1.
                    endloop
                    call DestroyEffect(AddSpecialEffectTarget(DeathEffect,dat.PassingBird,DummyAttach))
                    call DestroyEffect(dat.Sfx)
                    call UnitApplyTimedLife(dat.PassingBird,'BTLF',0.5)
                    call dat.destroy()
                    set Struct2.Total = Struct2.Total-1
                    set Struct2.Index[i] = Struct2.Index[Struct2.Total]
                    set i = i-1
                endif
                set i = i+1
            endloop
            if Struct2.Total == 0 then
                call PauseTimer(Struct2.Timer)
            endif
        endmethod
        
        static method Create takes nothing returns nothing
            local Struct2 dat = Struct2.allocate()
            local unit u = GetTriggerUnit()
            local location loc = GetSpellTargetLoc()
            set dat.Caster = u
            set dat.level = GetUnitAbilityLevel(u,SpellID)-1
            set dat.CentralX = GetLocationX(loc)
            set dat.CentralY = GetLocationY(loc)
            set dat.Time = Duration+(DurationIncr*dat.level)
            set dat.Time2 = EggDuration+(EggDurationIncr*dat.level)
            set R[0] = bj_RADTODEG*Atan2(dat.CentralY-GetUnitY(u),dat.CentralX-GetUnitX(u))
            set dat.PassingBird = CreateUnit(GetOwningPlayer(u),DummyID,GetUnitX(u),GetUnitY(u),R[0])
            call UnitAddAbility(dat.PassingBird,'Arav')
            call UnitRemoveAbility(dat.PassingBird,'Arav')
            call SetUnitFlyHeight(dat.PassingBird,PassingBirdHeight,0.)
            set dat.Sfx = AddSpecialEffectTarget(PassBirdModel,dat.PassingBird,DummyAttach)
            call DestroyEffect(AddSpecialEffectTarget(BirthEffect,dat.PassingBird,DummyAttach))
            if Struct2.Total == 0 then
                call TimerStart(Struct2.Timer,TimeOut,true,function Struct2.Loop)
            endif
            set Struct2.Index[Struct2.Total] = dat
            set Struct2.Total = Struct2.Total+1
            set u = null
            call RemoveLocation(loc)
            set loc = null
        endmethod
    endstruct
    private function Conditions takes nothing returns boolean
        return GetSpellAbilityId() == SpellID
    endfunction

    private function Actions takes nothing returns nothing
        call Struct2.Create()
    endfunction
    
    private function InitTrig_Initialize takes nothing returns nothing
        local trigger t = CreateTrigger()
        call TriggerRegisterAnyUnitEventBJ(t,EVENT_PLAYER_UNIT_SPELL_EFFECT)
        call TriggerAddCondition(t, Condition(function Conditions))
        call TriggerAddAction(t, function Actions)
        call Preload(BirdModel)
        call Preload(PassBirdModel)
        call Preload(EggModel)
        call Preload(AttachEffect)
        call Preload(DeathEffect)
        call Preload(BirthEffect)
        call Preload(DmgEffect)
        call Preload(ManaEffect)
        call Preload(BuffEffect)
        call PreloadStart()
    endfunction
endscope
Screenshot attached
it's supposed to MUI, I don't know yet if it SUI(Same-Unit-Instancebility) or not.
 

Attachments

  • Thunder Bird v1.1 [MG].w3x
    76 KB · Views: 116
  • 03.jpg
    03.jpg
    709.7 KB · Views: 208
Level 13
Joined
Jun 22, 2004
Messages
783
Here is my Submission

Dimensional Influence
Rippling time, the hero creates a copy of himself in another dimension. This Spirit effect everyone in a radius slowing opponents draining their HP away, the accumulated HP are added to the hero.
Radius, movement reduction and HP is increased per level
 

Attachments

  • Dimensional Influence.jpg
    Dimensional Influence.jpg
    209.3 KB · Views: 264
  • Dimensional Influence.w3x
    38 KB · Views: 92
Level 5
Joined
Oct 26, 2009
Messages
161
You're way too excited about this. Anyways, when can we expect the poll? Or is the contest host really busy?
 
Level 10
Joined
Jun 1, 2008
Messages
485
Back to the topic, let's hope for at least 20 submissions?
Hey this really happened! QFT:
20 + Submissions for a contest I submitted and thought was only going to get about five. This is gonna be good :D

~Asomath


Here's contestant list to make thing easier.

Contestant NameSpell Name

Gamecrafter_DK
Arcane Frostshard <WIP>

RaiN.
Lightning Shards

EMPerror
Pudger

Tukki
Molten Strike

scorpion182
Pentagram

Xiliger
Apocalypse

Duragon
The Fade

Deaod
Magic Chains

Eccho
Goblin Air Strike

TriggerHappy
Dune Worm

Kingz
Flame Ruin

White-Lion
Dark Ritual

ap0calypse
Descending Flame

xD.Schurke
Ritual of Vengeance

Maker
Nudgeball

Arcmage
Biomancy

Mage_Goo
Thunder Bird

Hemlock
Dimensional Influence

Zack1996
Wing Mark <Late>

in fact, I only find 17 submission + 1 WIP that looks like a submission
If you think there's some submission that wrong link or missed, just say, I'll change it.
 
Last edited:
Level 14
Joined
Nov 18, 2007
Messages
816
There are maybe 5 submissions that could be used in a live environment (ie. a map). The rest are effect spamming cinematic sequences with a little bit of added mechanics.

Also, 12 PM being noon makes no sense, not at all. Next time, use a 24 hour clock to avoid confusion.
 
Status
Not open for further replies.
Top