• 🏆 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!

Chaosflare Orb v1.4


Description
Summons the Chaosflare Orb at target point which triggers the sky to periodically strike upon it with powerful lightnings. The orb will convert it into smaller electric pulses which will be released at random direction. Enemy units got hit by these pulses will receive minor damage and will be slowed for a short duration.
How to import



    • Copy "Chaosflare Orb" trigger group to your map
    • Delete variable creator trigger
    • Export all necessary import data to your map
    • Copy dummy unit (Object Editor) to your map
    • Copy main ability (Object Editor) to your map
    • Configure the spell
Code
JASS:
[/FONT]

    // ********************************************************
    // *
    // *                Chaosflare Orb v1.4
    // *                            by Quilnez
    // *
    // *    Description:
    // *        Summons  the Chaosflare Orb at target  point  which
    // *        triggers  the  sky to periodically strike  upon  it
    // *        with  powerful lightnings. The orb will convert  it
    // *        into smaller electric pulses which will be released
    // *        at  random direction. Enemy units got hit by  these
    // *        pulses will receive minor damage and will be slowed
    // *        for a short duration.
    // *    
    // *    Requirement(s):
    // *        None
    // *    
    // *    How to import:
    // *        • Copy "Chaosflare Orb" trigger group to your map
    // *        • Delete variable creator trigger
    // *        • Export all necessary import data to your map
    // *        • Copy dummy unit (Object Editor) to your map
    // *        • Copy abilities and buff (Object Editor) to your map
    // *        • Configure the spell
    // *    
    // *    Credits:
    // *        • BTNDarkSphere By Darkfang
    // *        • Dark Lightning.mdx By JetFangInferno
    // *        • HydraLightingOrbGroundEffectV044.mdx By kellym0
    // *        • LightningStrikeLarge.mdx By Callahan
    // *        • Haunt.mdx By nGy
    // *        • Shockwave.mdx By Vestras
    // *        • VoidSkullAura_v5.mdx By xyzier_24
    // *            (All models are edited to fulfill the
    // *                    needs of this spell)
    // *    
    // ********************************************************
   
    // ********************************************************
    // *                   Configuration
    // *    
    // *    Dummy unit's raw code at object editor
            constant function CfO__DummyID takes nothing returns integer
                return 'h000'
            endfunction
    // *    
    // *    Main ability's raw code at object editor
            constant function CfO__SpellID takes nothing returns integer
                return 'A000'
            endfunction
    // *    
    // *    Slow ability's raw code at object editor
            constant function CfO__SlowSpellID takes nothing returns integer
                return 'A001'
            endfunction
    // *    
    // *    Slow buff's raw code at object editor
            constant function CfO__SlowBuffID takes nothing returns integer
                return 'B000'
            endfunction
    // *    
    // *    Main ability's order id
            constant function CfO__OrderID takes nothing returns integer
                return 852089 // blizzard
            endfunction
    // *    
    // *    Slow ability's order id
            constant function CfO__SlowSpellOrderID takes nothing returns integer
                return 852096 // thunderclap
            endfunction
    // *    
    // *    If true, the spell will be canceled if caster is given another order
            constant function CfO__Channeling takes nothing returns boolean
                return true
            endfunction
    // *    
    // *    If true, the slow duration will be stackable
            constant function CfO__Stacking takes nothing returns boolean
                return true
            endfunction
    // *    
    // *    Lightning strike effect model path
            constant function CfO__LightningFX takes nothing returns string
                return "war3mapImported\\DarkLightning.mdx"
            endfunction
    // *    
    // *    Orb's aura effect model path
            constant function CfO__AuraFX takes nothing returns string
                return "war3mapImported\\VoidSkullAura_v5.mdx"
            endfunction
    // *    
    // *    Wave effect model path (lightning strikes the ground)
            constant function CfO__WaveFX takes nothing returns string
                return "war3mapImported\\Shockwave.mdx"
            endfunction
    // *    
    // *    Orb model path
            constant function CfO__OrbFX takes nothing returns string
                return "war3mapImported\\Haunt_v2.mdx"
            endfunction
    // *    
    // *    Missile model path
            constant function CfO__MissileFX takes nothing returns string
                return "war3mapImported\\HydraLightingOrbGroundEffectV044.mdx"
            endfunction
    // *    
    // *    Hit effect model path
            constant function CfO__HitFX takes nothing returns string
                return "war3mapImported\\ShockTarget.mdx"
            endfunction
    // *    
    // *    Hit effect attachment point
            constant function CfO__HitFXPt takes nothing returns string
                return "origin"
            endfunction
    // *    
    // *    Missile's launch Z height
            constant function CfO__MissileHeight takes nothing returns real
                return 15.0
            endfunction
    // *    
    // *    Missile's scale
            constant function CfO__MissileSize takes nothing returns real
                return 1.0
            endfunction
    // *    
    // *    Minimum delay for missiles to turn
            constant function CfO__MissileTurnDelayMin takes nothing returns real
                return 0.075
            endfunction
    // *    
    // *    Maximum delay for missiles to turn
            constant function CfO__MissileTurnDelayMax takes nothing returns real
                return 0.5
            endfunction
    // *    
    // *    Minimum turn amount (in radians) for missiles
            constant function CfO__MissileTurnAmountMin takes nothing returns real
                return 45.0*bj_DEGTORAD
            endfunction
    // *    
    // *    Maximum turn amount (in radians) for missiles
            constant function CfO__MissileTurnAmountMax takes nothing returns real
                return 180.0*bj_DEGTORAD
            endfunction
    // *    
    // *    How fast missiles may turn
            constant function CfO__MissileTurnRate takes nothing returns real
                return 10.0*bj_DEGTORAD
            endfunction
    // *    
    // *    Orb's scale
            constant function CfO__OrbSize takes nothing returns real
                return 1.0
            endfunction
    // *    
    // *    Orb's spawn Z height
            constant function CfO__OrbHeight takes nothing returns real
                return 150.0
            endfunction
    // *    
    // *    Orb's aura's scale
            constant function CfO__AuraSize takes nothing returns real
                return 1.5
            endfunction
    // *    
    // *    Orb's aura's Z height
            constant function CfO__AuraHeight takes nothing returns real
                return 0.0
            endfunction
    // *    
    // *    Maximum range for misilles to hit a target
            constant function CfO__HitRadius takes nothing returns real
                return 100.0
            endfunction
    // *    
    // *    Better to leave this one as it is
            constant function CfO__Interval takes nothing returns real
                return 0.03125
            endfunction
    // *    
    // *    Spread factor for missile launching, must be between 0 - 1
            constant function CfO__Accuracy takes nothing returns real
                return 0.25
            endfunction
    // *    
    // *    If true, each missile will home for one target
            constant function CfO__Homing takes integer level returns boolean
                return false
            endfunction
    // *    
    // *    If true, each missile will look for another target after a hit
            constant function CfO__SmartHoming takes nothing returns boolean
                return false
            endfunction
    // *    
    // *    Maximum range for missile to obtain a target
            constant function CfO__DetectRadius takes integer level returns real
                return 200.0
            endfunction
    // *    
    // *    Delay before another lightning strikes the orb
            constant function CfO__StrikeDelay takes integer level returns real
                return 2.5
            endfunction
    // *    
    // *    Delay between the strike and before the missiles are launched
            constant function CfO__ReleaseDelay takes integer level returns real
                return 0.375
            endfunction
    // *    
    // *    Speed of missiles
            constant function CfO__Velocity takes integer level returns real
                return 30.0
            endfunction
    // *    
    // *    Minimum wander distance for every missile
            constant function CfO__DistanceMin takes integer level returns real
                return 800.0
            endfunction
    // *    
    // *    Maximum wander distance for every missile
            constant function CfO__DistanceMax takes integer level returns real
                return 1600.0
            endfunction
    // *    
    // *    Damage dealt on hit
            constant function CfO__Damage takes integer level returns real
                return 15.0 * level
            endfunction
    // *    
    // *    Orb's lifespan
            constant function CfO__Duration takes integer level returns real
                return 15.0
            endfunction
    // *    
    // *    Number of missiles releashed per strike
            constant function CfO__ReleaseCount takes integer level returns integer
                return 4 + 2 * level
            endfunction
    // *    
    // *    Slow duration
            constant function CfO__SlowDuration takes integer level returns real
                return 1.5
            endfunction
    // *    
    // *    Attack type of dealt damage
            constant function CfO__AttackType takes nothing returns attacktype
                return ATTACK_TYPE_MAGIC
            endfunction
    // *    
    // *    Damage type of dealt damage
            constant function CfO__DamageType takes nothing returns damagetype
                return DAMAGE_TYPE_LIGHTNING
            endfunction
    // *    
    // *    Weapon type of dealt damage
            constant function CfO__WeaponType takes nothing returns weapontype
                return WEAPON_TYPE_WHOKNOWS
            endfunction
    // *    
    // *    No need to touch this
            function CfO__isAlive takes unit id returns boolean
                return GetWidgetLife(id) > 0.405 and not IsUnitType(id, UNIT_TYPE_DEAD)
            endfunction
    // *    
    // *    Classification of unit that can be a victim of the missiles
            function CfO__Targets takes unit target, player source returns boolean
                return CfO__isAlive(target) and IsUnitEnemy(target, source) and not(IsUnitType(target, UNIT_TYPE_STRUCTURE) or IsUnitType(target, UNIT_TYPE_MECHANICAL) or IsUnitType(target, UNIT_TYPE_FLYING) or IsUnitType(target, UNIT_TYPE_MAGIC_IMMUNE))
            endfunction
    // *    
    // *    This is where you can do additional actions on damage event (missile hits a target)
            function CfO__OnDamage takes unit target, unit caster, integer level returns nothing
            endfunction
    // *    
    // *    This is where you can do additional actions when an orb is struck by lightning
    // *        caster = spell's caster, level = spell's level, x & y = location where the spell is located
            function CfO__OnStrike takes unit caster, integer level, real x, real y returns nothing
            endfunction
    // *    
    // *    This is where you can do additional actions when missiles are going to be released
    // *        caster = spell's caster, level = spell's level, x & y = location where the spell is located
            function CfO__OnRelease takes unit caster, integer level, real x, real y returns nothing
            endfunction
    // *    
    // *    This is where you can do additional actions before the spell is ended
    // *        caster = spell's caster, level = spell's level, x & y = location where the spell is located
            function CfO__OnDispose takes unit caster, integer level, real x, real y returns nothing
            endfunction
    // *    
    // *    This is where you can do additional actions before a missile is removed
    // *        caster = spell's caster, level = spell's level, x & y = location of the missile
            function CfO__OnMissileDispose takes unit caster, integer level, real x, real y returns nothing
            endfunction
    // *    
    // *                End of Configuration
    // *    
    // ********************************************************
   
    // Check whether passed coordinate is inside the world or not
    function CfO__isInBound takes real x, real y returns boolean
        return x > udg_CfO__WorldBounds[0] and x < udg_CfO__WorldBounds[1] and y > udg_CfO__WorldBounds[2] and y < udg_CfO__WorldBounds[3]
    endfunction
   
    // Allows custom filter by user to be used by unit enumeration filter
    function CfO__filter takes nothing returns boolean
        return CfO__Targets(GetFilterUnit(), udg_CfO__Owner[udg_CfO__Missile__Source[udg_CfO__TempInt]]) and not IsUnitInGroup(GetFilterUnit(), udg_CfO__Missile__Targets[udg_CfO__TempInt])
    endfunction
   
    function CfO__slow takes nothing returns nothing
       
        local integer c
        local integer h
        local integer i = 1
        local boolean dispose
       
        loop
            exitwhen i > udg_CfO__Slow__Count
            set dispose = false
            if CfO__isAlive(udg_CfO__Slow__Target[i]) then
                set udg_CfO__Slow__Duration[i] = udg_CfO__Slow__Duration[i] - CfO__Interval()
                if udg_CfO__Slow__Duration[i] <= 0 then
                    set h = GetHandleId(udg_CfO__Slow__Target[i])
                    if CfO__Stacking() then
                        set dispose = true
                        call SaveInteger(udg_CfO__Hashtable, h, 1, 0)
                    else
                        set c = LoadInteger(udg_CfO__Hashtable, h, 1) - 1
                        call SaveInteger(udg_CfO__Hashtable, h, 1, c)
                        if c == 0 then
                            set dispose = true
                        endif
                    endif
                endif
            else
                set dispose = true
            endif
            if dispose then
                call UnitRemoveAbility(udg_CfO__Slow__Target[i], CfO__SlowBuffID())
                set udg_CfO__Slow__Target[i] = udg_CfO__Slow__Target[udg_CfO__Slow__Count]
                set udg_CfO__Slow__Duration[i] = udg_CfO__Slow__Duration[udg_CfO__Slow__Count]
                set udg_CfO__Slow__Target[udg_CfO__Slow__Count] = null
                set udg_CfO__Slow__Count = udg_CfO__Slow__Count - 1
                if udg_CfO__Slow__Count == 0 then
                    call PauseTimer(udg_CfO__Slow__Timer)
                else
                    set i = i - 1
                endif
            endif
            set i = i + 1
        endloop
       
    endfunction
   
    function CfO__applySlow takes integer source, unit target returns nothing
       
        local integer h
        local integer c
       
        set h = GetHandleId(target)
        if CfO__Stacking() then
            set c = LoadInteger(udg_CfO__Hashtable, h, 1)
            if c == 0 then
                set udg_CfO__Slow__Count = udg_CfO__Slow__Count + 1
                set udg_CfO__Slow__Target[udg_CfO__Slow__Count] = target
                set udg_CfO__Slow__Duration[udg_CfO__Slow__Count] = CfO__SlowDuration(udg_CfO__Level[source])
                call SetUnitX(udg_CfO__Slow__Caster, GetUnitX(target))
                call SetUnitY(udg_CfO__Slow__Caster, GetUnitY(target))
                call IssueImmediateOrderById(udg_CfO__Slow__Caster, CfO__SlowSpellOrderID())
                call SaveInteger(udg_CfO__Hashtable, h, 1, udg_CfO__Slow__Count)
            else
                set udg_CfO__Slow__Duration[c] = udg_CfO__Slow__Duration[c] + CfO__SlowDuration(udg_CfO__Level[source])
            endif
        else
            set udg_CfO__Slow__Count = udg_CfO__Slow__Count + 1
            set udg_CfO__Slow__Target[udg_CfO__Slow__Count] = target
            set udg_CfO__Slow__Duration[udg_CfO__Slow__Count] = CfO__SlowDuration(udg_CfO__Level[source])
            set c = LoadInteger(udg_CfO__Hashtable, h, 1) + 1
            call SaveInteger(udg_CfO__Hashtable, h, 1, c)
            if c == 1 then
                call SetUnitX(udg_CfO__Slow__Caster, GetUnitX(target))
                call SetUnitY(udg_CfO__Slow__Caster, GetUnitY(target))
                call IssueImmediateOrderById(udg_CfO__Slow__Caster, CfO__SlowSpellOrderID())
            endif
        endif
        if udg_CfO__Slow__Count == 1 then
            call TimerStart(udg_CfO__Slow__Timer, CfO__Interval(), true, function CfO__slow)
        endif
       
    endfunction
   
    // Periodic callback for missiles
    function CfO__missile takes nothing returns nothing
       
        local integer i = 1
        local boolean dispose
        local unit fog
       
        loop
            exitwhen i > udg_CfO__Missile__Count
            set dispose = false
            if udg_CfO__Missile__Distance[i] > udg_CfO__Velocity[udg_CfO__Missile__Source[i]] and CfO__isAlive(udg_CfO__Caster[udg_CfO__Missile__Source[i]]) then
                // If don't have valid target
                if udg_CfO__Missile__Target[i] == null or not CfO__isAlive(udg_CfO__Missile__Target[i]) then
                    if udg_CfO__Missile__TurnDelay[i] > CfO__Interval() then
                        set udg_CfO__Missile__TurnDelay[i] = udg_CfO__Missile__TurnDelay[i] - CfO__Interval()
                    else
                        set udg_CfO__Missile__TurnDelay[i] = GetRandomReal(CfO__MissileTurnDelayMin(), CfO__MissileTurnDelayMax())
                        set udg_CfO__Missile__AngleX[i] = udg_CfO__Missile__Angle[i] + GetRandomReal(CfO__MissileTurnAmountMin(), CfO__MissileTurnAmountMax()) * GetRandomInt(-1, 1)
                    endif
                   
                    if CfO__Homing(udg_CfO__Level[udg_CfO__Missile__Source[i]]) then
                        set udg_CfO__TempInt = i
                        call GroupEnumUnitsInRange(udg_CfO__TempGroup, udg_CfO__Missile__X[i], udg_CfO__Missile__Y[i], CfO__DetectRadius(udg_CfO__Level[udg_CfO__Missile__Source[i]]), Filter(function CfO__filter))
                        set udg_CfO__Missile__Target[i] = GroupPickRandomUnit(udg_CfO__TempGroup)
                        call GroupClear(udg_CfO__TempGroup)
                    endif
                else
                    // Set target angle to the location of target
                    set udg_CfO__Missile__AngleX[i] = Atan2(GetUnitY(udg_CfO__Missile__Target[i]) - udg_CfO__Missile__Y[i], GetUnitX(udg_CfO__Missile__Target[i]) - udg_CfO__Missile__X[i])
                endif
               
                // Adjust missile's angle to the target
                if CfO__MissileTurnRate() > 0 and Cos(udg_CfO__Missile__Angle[i]-udg_CfO__Missile__AngleX[i]) < Cos(CfO__MissileTurnRate()) then
                    if Sin(udg_CfO__Missile__AngleX[i]-udg_CfO__Missile__Angle[i]) >= 0 then
                        set udg_CfO__Missile__Angle[i] = udg_CfO__Missile__Angle[i] + CfO__MissileTurnRate()
                    else
                        set udg_CfO__Missile__Angle[i] = udg_CfO__Missile__Angle[i] - CfO__MissileTurnRate()
                    endif
                else
                    set udg_CfO__Missile__Angle[i] = udg_CfO__Missile__AngleX[i]
                endif
               
                set udg_CfO__Missile__X[i] = udg_CfO__Missile__X[i] + udg_CfO__Velocity[udg_CfO__Missile__Source[i]]*Cos(udg_CfO__Missile__Angle[i])
                set udg_CfO__Missile__Y[i] = udg_CfO__Missile__Y[i] + udg_CfO__Velocity[udg_CfO__Missile__Source[i]]*Sin(udg_CfO__Missile__Angle[i])
                set udg_CfO__Missile__Distance[i] = udg_CfO__Missile__Distance[i] - udg_CfO__Velocity[udg_CfO__Missile__Source[i]]
                // Move missile and detect for reachable targets
                if CfO__isInBound(udg_CfO__Missile__X[i], udg_CfO__Missile__Y[i]) then
                    call SetUnitX(udg_CfO__Missile__Dummy[i], udg_CfO__Missile__X[i])
                    call SetUnitY(udg_CfO__Missile__Dummy[i], udg_CfO__Missile__Y[i])
                    call GroupEnumUnitsInRange(udg_CfO__TempGroup, udg_CfO__Missile__X[i], udg_CfO__Missile__Y[i], CfO__HitRadius(), null)
                    loop
                        set fog = FirstOfGroup(udg_CfO__TempGroup)
                        exitwhen fog == null
                        call GroupRemoveUnit(udg_CfO__TempGroup, fog)
                        if CfO__Targets(fog, udg_CfO__Owner[udg_CfO__Missile__Source[i]]) and not IsUnitInGroup(fog, udg_CfO__Missile__Targets[i]) then
                            call GroupAddUnit(udg_CfO__Missile__Targets[i], fog)
                            call DestroyEffect(AddSpecialEffectTarget(CfO__HitFX(), fog, CfO__HitFXPt()))
                            call UnitDamageTarget(udg_CfO__Caster[udg_CfO__Missile__Source[i]], fog, udg_CfO__Damage[udg_CfO__Missile__Source[i]], false, false, CfO__AttackType(), CfO__DamageType(), CfO__WeaponType())
                            call CfO__OnDamage(fog, udg_CfO__Caster[udg_CfO__Missile__Source[i]], udg_CfO__Level[udg_CfO__Missile__Source[i]])
                            if CfO__isAlive(fog) then
                                call CfO__applySlow(udg_CfO__Missile__Source[i], fog)
                            endif
                            if CfO__SmartHoming() and CfO__Homing(udg_CfO__Level[udg_CfO__Missile__Source[i]]) then
                                set udg_CfO__Missile__Target[i] = null
                            endif
                        endif
                    endloop
                else
                    set dispose = true
                endif
            else
                set dispose = true
            endif
           
            if dispose then
                call CfO__OnMissileDispose(udg_CfO__Caster[udg_CfO__Missile__Source[i]], udg_CfO__Level[udg_CfO__Missile__Source[i]], udg_CfO__Missile__X[i], udg_CfO__Missile__Y[i])
                // Detach disposed missile from the system
                call UnitApplyTimedLife(udg_CfO__Missile__Dummy[i], 'BTLF', 5.0)
                call DestroyEffect(udg_CfO__Missile__Fx[i])
                call DestroyGroup(udg_CfO__Missile__Targets[i])
                set udg_CfO__MCount[udg_CfO__Missile__Source[i]] = udg_CfO__MCount[udg_CfO__Missile__Source[i]] - 1
                if i != udg_CfO__Missile__Count then
                    // Deindex
                    set udg_CfO__Missile__Angle[i] = udg_CfO__Missile__Angle[udg_CfO__Missile__Count]
                    set udg_CfO__Missile__AngleX[i] = udg_CfO__Missile__AngleX[udg_CfO__Missile__Count]
                    set udg_CfO__Missile__X[i] = udg_CfO__Missile__X[udg_CfO__Missile__Count]
                    set udg_CfO__Missile__Y[i] = udg_CfO__Missile__Y[udg_CfO__Missile__Count]
                    set udg_CfO__Missile__Distance[i] = udg_CfO__Missile__Distance[udg_CfO__Missile__Count]
                    set udg_CfO__Missile__Source[i] = udg_CfO__Missile__Source[udg_CfO__Missile__Count]
                    set udg_CfO__Missile__Target[i] = udg_CfO__Missile__Target[udg_CfO__Missile__Count]
                    set udg_CfO__Missile__Targets[i] = udg_CfO__Missile__Targets[udg_CfO__Missile__Count]
                    set udg_CfO__Missile__TurnDelay[i] = udg_CfO__Missile__TurnDelay[udg_CfO__Missile__Count]
                    set udg_CfO__Missile__Dummy[i] = udg_CfO__Missile__Dummy[udg_CfO__Missile__Count]
                    set udg_CfO__Missile__Fx[i] = udg_CfO__Missile__Fx[udg_CfO__Missile__Count]
                    // Remove leaks
                    set udg_CfO__Missile__Dummy[udg_CfO__Missile__Count] = null
                    set udg_CfO__Missile__Target[udg_CfO__Missile__Count] = null
                    set udg_CfO__Missile__Targets[udg_CfO__Missile__Count] = null
                    set udg_CfO__Missile__Fx[udg_CfO__Missile__Count] = null
                endif
                set udg_CfO__Missile__Count = udg_CfO__Missile__Count - 1
                if udg_CfO__Missile__Count == 0 then
                    call PauseTimer(udg_CfO__Missile__Timer)
                    exitwhen true
                else
                    set i = i - 1
                endif
            endif
            set i = i + 1
        endloop
       
    endfunction
   
    // Launch an electric pulse to given direction
    function CfO__launch takes integer source, real angle returns nothing
   
        set udg_CfO__Missile__Count = udg_CfO__Missile__Count + 1
        set udg_CfO__Missile__Angle[udg_CfO__Missile__Count] = angle*bj_DEGTORAD
        set udg_CfO__Missile__AngleX[udg_CfO__Missile__Count] = udg_CfO__Missile__Angle[udg_CfO__Missile__Count] + GetRandomReal(CfO__MissileTurnAmountMin(), CfO__MissileTurnAmountMax()) * GetRandomInt(-1, 1)
        set udg_CfO__Missile__X[udg_CfO__Missile__Count] = udg_CfO__X[source]
        set udg_CfO__Missile__Y[udg_CfO__Missile__Count] = udg_CfO__Y[source]
        set udg_CfO__Missile__Distance[udg_CfO__Missile__Count] = GetRandomReal(CfO__DistanceMin(udg_CfO__Level[source]), CfO__DistanceMax(udg_CfO__Level[source]))
        set udg_CfO__Missile__Source[udg_CfO__Missile__Count] = source
        set udg_CfO__Missile__Target[udg_CfO__Missile__Count] = null
        set udg_CfO__Missile__Targets[udg_CfO__Missile__Count] = CreateGroup()
        set udg_CfO__Missile__TurnDelay[udg_CfO__Missile__Count] = GetRandomReal(CfO__MissileTurnDelayMin(), CfO__MissileTurnDelayMax())
        set udg_CfO__Missile__Dummy[udg_CfO__Missile__Count] = CreateUnit(udg_CfO__Owner[source], CfO__DummyID(), udg_CfO__X[source], udg_CfO__Y[source], angle)
        set udg_CfO__Missile__Fx[udg_CfO__Missile__Count] = AddSpecialEffectTarget(CfO__MissileFX(), udg_CfO__Missile__Dummy[udg_CfO__Missile__Count], "origin")
           
        if UnitAddAbility(udg_CfO__Missile__Dummy[udg_CfO__Missile__Count], 'Amrf') and UnitRemoveAbility(udg_CfO__Missile__Dummy[udg_CfO__Missile__Count], 'Amrf') then
        endif
        call SetUnitScale(udg_CfO__Missile__Dummy[udg_CfO__Missile__Count], CfO__MissileSize(), 1, 1)
        call SetUnitFlyHeight(udg_CfO__Missile__Dummy[udg_CfO__Missile__Count], CfO__MissileHeight(), 0)
       
        if udg_CfO__Missile__Count == 1 then
            call TimerStart(udg_CfO__Missile__Timer, CfO__Interval(), true, function CfO__missile)
        endif
       
    endfunction
   
    // Periodic callback for orbs
    function CfO__periodic takes nothing returns nothing
       
        local integer h
        local integer i = 1
        local integer j
        local real space
       
        loop
            exitwhen i > udg_CfO__Count
            // If the spell is still ongoing
            if udg_CfO__Duration[i] > CfO__Interval() and CfO__isAlive(udg_CfO__Caster[i]) and (not CfO__Channeling() or GetUnitCurrentOrder(udg_CfO__Caster[i]) == CfO__OrderID()) then
                set udg_CfO__Duration[i] = udg_CfO__Duration[i] - CfO__Interval()
                if udg_CfO__StrikeDelay[i] > CfO__Interval() then
                    set udg_CfO__StrikeDelay[i] = udg_CfO__StrikeDelay[i] - CfO__Interval()
                elseif udg_CfO__ReleaseDelay[i] > CfO__Interval() then
                    // Play "lightning strike" animation
                    if udg_CfO__ReleaseDelay[i] == udg_CfO__ReleaseDelayX[i] then
                        call DestroyEffect(AddSpecialEffectTarget(CfO__LightningFX(), udg_CfO__Orb[i], "origin"))
                        call DestroyEffect(AddSpecialEffect(CfO__WaveFX(), udg_CfO__X[i], udg_CfO__Y[i]))
                        call CfO__OnStrike(udg_CfO__Caster[i], udg_CfO__Level[i], udg_CfO__X[i], udg_CfO__Y[i])
                    endif
                    set udg_CfO__ReleaseDelay[i] = udg_CfO__ReleaseDelay[i] - CfO__Interval()
                else
                    // Release electric pulses
                    set udg_CfO__StrikeDelay[i] = udg_CfO__StrikeDelayX[i]
                    set udg_CfO__ReleaseDelay[i] = udg_CfO__ReleaseDelayX[i]
                    call CfO__OnRelease(udg_CfO__Caster[i], udg_CfO__Level[i], udg_CfO__X[i], udg_CfO__Y[i])
                    set space = 360/udg_CfO__ReleaseCount[i]
                    set j = 0
                    loop
                        exitwhen j == udg_CfO__ReleaseCount[i]
                        set udg_CfO__MCount[i] = udg_CfO__MCount[i] + 1
                        call CfO__launch(i, space*j + GetRandomReal(-space*CfO__Accuracy(), space*CfO__Accuracy()))
                        set j = j + 1
                    endloop
                endif
            else
                if udg_CfO__OrbFx[i] != null then
                    call CfO__OnDispose(udg_CfO__Caster[i], udg_CfO__Level[i], udg_CfO__X[i], udg_CfO__Y[i])
                       
                    if CfO__Channeling() then
                        set h = GetHandleId(udg_CfO__Caster[i])
                        if LoadInteger(udg_CfO__Hashtable, h, 0) == i then
                            call SaveInteger(udg_CfO__Hashtable, h, 0, 0)
                        endif
                    endif
                   
                    call UnitApplyTimedLife(udg_CfO__Orb[i], 'BTLF', 5)
                    call UnitApplyTimedLife(udg_CfO__Aura[i], 'BTLF', 5)
                    call DestroyEffect(udg_CfO__OrbFx[i])
                    call DestroyEffect(udg_CfO__AuraFx[i])
                    set udg_CfO__OrbFx[i] = null
                endif
               
                if udg_CfO__MCount[i] <= 0 then
                    if i != udg_CfO__Count then
                        // Index correction
                        if CfO__Channeling() then
                            call SaveInteger(udg_CfO__Hashtable, GetHandleId(udg_CfO__Caster[udg_CfO__Count]), 0, i)
                        endif
                       
                        // Deindex
                        set udg_CfO__Caster[i] = udg_CfO__Caster[udg_CfO__Count]
                        set udg_CfO__Owner[i] = udg_CfO__Owner[udg_CfO__Count]
                        set udg_CfO__X[i] = udg_CfO__X[udg_CfO__Count]
                        set udg_CfO__Y[i] = udg_CfO__Y[udg_CfO__Count]
                        set udg_CfO__Orb[i] = udg_CfO__Orb[udg_CfO__Count]
                        set udg_CfO__OrbFx[i] = udg_CfO__OrbFx[udg_CfO__Count]
                        set udg_CfO__Aura[i] = udg_CfO__Aura[udg_CfO__Count]
                        set udg_CfO__AuraFx[i] = udg_CfO__AuraFx[udg_CfO__Count]
                        set udg_CfO__MCount[i] = udg_CfO__MCount[udg_CfO__Count]
                       
                        set udg_CfO__Level[i] = udg_CfO__Level[udg_CfO__Count]
                        set udg_CfO__Velocity[i] = udg_CfO__Velocity[udg_CfO__Count]
                        set udg_CfO__Duration[i] = udg_CfO__Duration[udg_CfO__Count]
                        set udg_CfO__ReleaseDelayX[i] = udg_CfO__ReleaseDelayX[udg_CfO__Count]
                        set udg_CfO__StrikeDelayX[i] = udg_CfO__StrikeDelayX[udg_CfO__Count]
                        set udg_CfO__ReleaseDelay[i] = udg_CfO__ReleaseDelay[udg_CfO__Count]
                        set udg_CfO__StrikeDelay[i] = udg_CfO__StrikeDelay[udg_CfO__Count]
                        set udg_CfO__ReleaseCount[i] = udg_CfO__ReleaseCount[udg_CfO__Count]
                       
                        // Remove leaks
                        set udg_CfO__Orb[udg_CfO__Count] = null
                        set udg_CfO__OrbFx[udg_CfO__Count] = null
                        set udg_CfO__Aura[udg_CfO__Count] = null
                        set udg_CfO__AuraFx[udg_CfO__Count] = null
                        set udg_CfO__Caster[udg_CfO__Count] = null
                       
                        // Source index corrections
                        set j = 1
                        loop
                            exitwhen j > udg_CfO__Missile__Count
                            if udg_CfO__Missile__Source[j] == udg_CfO__Count then
                                set udg_CfO__Missile__Source[j] = i
                            endif
                            set j = j + 1
                        endloop
                    endif
                    set udg_CfO__Count = udg_CfO__Count - 1
                    if udg_CfO__Count == 0 then
                        call PauseTimer(udg_CfO__Timer)
                    else
                        set i = i - 1
                    endif
                endif
            endif
            set i = i + 1
        endloop
       
    endfunction
   
    // On cast event
    function CfO__onCast takes nothing returns boolean
       
        local integer h
        local integer i
       
        if GetSpellAbilityId() == CfO__SpellID() then
            set udg_CfO__Count = udg_CfO__Count + 1
            set udg_CfO__Caster[udg_CfO__Count] = GetTriggerUnit()
            set udg_CfO__Owner[udg_CfO__Count] = GetTriggerPlayer()
            set udg_CfO__X[udg_CfO__Count] = GetSpellTargetX()
            set udg_CfO__Y[udg_CfO__Count] = GetSpellTargetY()
            set udg_CfO__Orb[udg_CfO__Count] = CreateUnit(udg_CfO__Owner[udg_CfO__Count], CfO__DummyID(), udg_CfO__X[udg_CfO__Count], udg_CfO__Y[udg_CfO__Count], 0)
            set udg_CfO__OrbFx[udg_CfO__Count] = AddSpecialEffectTarget(CfO__OrbFX(), udg_CfO__Orb[udg_CfO__Count], "origin")
            set udg_CfO__Aura[udg_CfO__Count] = CreateUnit(udg_CfO__Owner[udg_CfO__Count], CfO__DummyID(), udg_CfO__X[udg_CfO__Count], udg_CfO__Y[udg_CfO__Count], 0)
            set udg_CfO__AuraFx[udg_CfO__Count] = AddSpecialEffectTarget(CfO__AuraFX(), udg_CfO__Aura[udg_CfO__Count], "origin")
            set udg_CfO__MCount[udg_CfO__Count] = 0
           
            set udg_CfO__Level[udg_CfO__Count] = GetUnitAbilityLevel(udg_CfO__Caster[udg_CfO__Count], CfO__SpellID())
            set udg_CfO__Velocity[udg_CfO__Count] = CfO__Velocity(udg_CfO__Level[udg_CfO__Count])
            set udg_CfO__Damage[udg_CfO__Count] = CfO__Damage(udg_CfO__Level[udg_CfO__Count])
            set udg_CfO__Duration[udg_CfO__Count] = CfO__Duration(udg_CfO__Level[udg_CfO__Count])
            set udg_CfO__ReleaseDelayX[udg_CfO__Count] = CfO__ReleaseDelay(udg_CfO__Level[udg_CfO__Count])
            set udg_CfO__StrikeDelayX[udg_CfO__Count] = CfO__StrikeDelay(udg_CfO__Level[udg_CfO__Count])
            set udg_CfO__ReleaseDelay[udg_CfO__Count] = udg_CfO__ReleaseDelayX[udg_CfO__Count]
            set udg_CfO__StrikeDelay[udg_CfO__Count] = udg_CfO__StrikeDelayX[udg_CfO__Count]
            set udg_CfO__ReleaseCount[udg_CfO__Count] = CfO__ReleaseCount(udg_CfO__Level[udg_CfO__Count])
           
            if UnitAddAbility(udg_CfO__Orb[udg_CfO__Count], 'Amrf') and UnitRemoveAbility(udg_CfO__Orb[udg_CfO__Count], 'Amrf') then
            endif
            call SetUnitScale(udg_CfO__Orb[udg_CfO__Count], CfO__OrbSize(), 1, 1)
            call SetUnitFlyHeight(udg_CfO__Orb[udg_CfO__Count], CfO__OrbHeight(), 0)
           
            if UnitAddAbility(udg_CfO__Aura[udg_CfO__Count], 'Amrf') and UnitRemoveAbility(udg_CfO__Aura[udg_CfO__Count], 'Amrf') then
            endif
            call SetUnitScale(udg_CfO__Aura[udg_CfO__Count], CfO__AuraSize(), 1, 1)
            call SetUnitFlyHeight(udg_CfO__Aura[udg_CfO__Count], CfO__AuraHeight(), 0)
           
            if CfO__Channeling() then
                set h = GetHandleId(udg_CfO__Caster[udg_CfO__Count])
                set i = LoadInteger(udg_CfO__Hashtable, h, 0)
                if i != 0 then
                    set udg_CfO__Duration[i] = 0
                endif
                call SaveInteger(udg_CfO__Hashtable, h, 0, udg_CfO__Count)
            endif
           
            if udg_CfO__Count == 1 then
                call TimerStart(udg_CfO__Timer, CfO__Interval(), true, function CfO__periodic)
            endif
        endif
       
        return false
    endfunction
   
    function InitTrig_Chaosflare_Orb takes nothing returns nothing
       
        // World bounds initialization
        set udg_CfO__WorldBounds[0] = GetRectMinX(bj_mapInitialPlayableArea)
        set udg_CfO__WorldBounds[1] = GetRectMaxX(bj_mapInitialPlayableArea)
        set udg_CfO__WorldBounds[2] = GetRectMinY(bj_mapInitialPlayableArea)
        set udg_CfO__WorldBounds[3] = GetRectMaxY(bj_mapInitialPlayableArea)
       
        set udg_CfO__Timer = CreateTimer()
        set udg_CfO__Slow__Timer = CreateTimer()
        set udg_CfO__Missile__Timer = CreateTimer()
        set gg_trg_Chaosflare_Orb = CreateTrigger()
        set udg_CfO__Slow__Caster = CreateUnit(Player(PLAYER_NEUTRAL_PASSIVE), CfO__DummyID(), 0, 0, 0)
        call UnitAddAbility(udg_CfO__Slow__Caster, CfO__SlowSpellID())
        call TriggerRegisterAnyUnitEventBJ(gg_trg_Chaosflare_Orb, EVENT_PLAYER_UNIT_SPELL_EFFECT)
        call TriggerAddCondition(gg_trg_Chaosflare_Orb, Condition(function CfO__onCast))
       
        if CfO__Channeling() then
            set udg_CfO__Hashtable = InitHashtable()
        endif
       
    endfunction
   [FONT=Palatino Linotype]
Credits



    • BTNDarkSphere By Darkfang
    • Dark Lightning.mdx By JetFangInferno
    • HydraLightingOrbGroundEffectV044.mdx By kellym0
    • LightningStrikeLarge.mdx By Callahan
    • Haunt.mdx By nGy
    • Shockwave.mdx By Vestras
    • VoidSkullAura_v5.mdx By xyzier_24


Keywords:
chaosflare, orb
Previews
Contents

Chaosflare Orb (Map)

Reviews
BPower: Bugs fixed. Approved. Great spell. Temporary set back to Need Fix, because of an elementar mistake I missed in my first review. 13:10, 11th Jun 2015 BPower: Code, documentation, presentation and demo map are very nice done!

Moderator

M

Moderator

BPower: Bugs fixed. Approved. Great spell.

Temporary set back to Need Fix, because of an
elementar mistake I missed in my first review.



13:10, 11th Jun 2015
BPower:
Code, documentation, presentation and demo map are very nice done!
 
I quickyly checked it and seems to be a good spell. Well coded, and looks nice.

Personaly I could imagine kind of little explosion in end, but what ever, it just came in mind.

When setting this to true in config:
JASS:
3. If true, the spell will be canceled if caster is given another order
constant function CfO__Channeling takes nothing returns boolean
    return true
endfunction
It works for all but only one case.
Unit can still use spell order and cast the spell multple times, even it's channeling.
I noticed it with abusing the demo "Esc" trigger, but it also can happen with shorter CDs of course.
 

Kazeon

Hosted Project: EC
Level 33
Joined
Oct 12, 2011
Messages
3,449
I quickyly checked it and seems to be a good spell. Well coded, and looks nice.

Personaly I could imagine kind of little explosion in end, but what ever, it just came in mind.

When setting this to true in config:
JASS:
3. If true, the spell will be canceled if caster is given another order
constant function CfO__Channeling takes nothing returns boolean
    return true
endfunction
It works for all but only one case.
Unit can still use spell order and cast the spell multple times, even it's channeling.
I noticed it with abusing the demo "Esc" trigger, but it also can happen with shorter CDs of course.

I'm aware. But it requires UnitIndexer to fix it (the first solution came to my mind), which is a big NO.

Wait, I think I can use hashtable.

I will add onDispose event as well to allow user to do actions at the end of the spell.
 
Level 19
Joined
Mar 18, 2012
Messages
1,716
I just tested the demo map and I like it. :p

If IcemanBo gives his ok, it's ready for approval. I didn't check the code itself,
because he already said that it is well done.

Edit:

Why didn't you use RemoveSavedInteger and HaveSavedInteger over
LoadInteger == 0 and SaveInteger(table, handle, 0)?
 

Kazeon

Hosted Project: EC
Level 33
Joined
Oct 12, 2011
Messages
3,449
If I use HaveSavedInteger, I need to change
JASS:
                set i = LoadInteger(udg_CfO__Hashtable, h, 0)
                if i != 0 then
                    set udg_CfO__Duration[i] = 0
to
JASS:
                if HaveSavedInteger then
                    set udg_CfO__Duration[LoadInteger(udg_CfO__Hashtable, h, 0)] = 0
means 2x function call :p

And what's the difference between RemoveSavedInteger and SaveInteger 0 anyway? I think they both simply change the saved value to 0.

Well, honestly that's because I'm not familiar with those function :p If you think they have advantages over the current one, I will change it right away.

EDIT:
Minor update, I forgot to revert the spell mode back to channeling.
 
Last edited:
Level 1
Joined
Feb 8, 2011
Messages
3
Followed all the instructions, but this trigger isn't working for me.

It's returning 247 compile errors.

Am I doing something wrong?
Help please. I really want to use this spell.
 
Level 17
Joined
Nov 12, 2016
Messages
780
i wolde like to know more about how can i import or use the dark orb spell on a map so can you please give me more help with witch i can use cuz idk to how to do it and my tryings havent been working
 

Kazeon

Hosted Project: EC
Level 33
Joined
Oct 12, 2011
Messages
3,449
Just follow the importing manual:
  • Copy "Chaosflare Orb" trigger group to your map
    : Crystal clear

  • Delete variable creator trigger
    : It's a trigger in that trigger group

  • Export all necessary import data to your map
    : Simply import all imported files in the spell map to your map

  • Copy dummy unit (Object Editor) to your map
    : In the object editor (in unit category) there is an object named Dummy. Just copy paste it to your map

  • Copy main ability (Object Editor) to your map
    : Same as above but it's in the ability category

  • Configure the spell
    :
    JASS:
        // *    Dummy unit's raw code at object editor
                constant function CfO__DummyID takes nothing returns integer
                    return 'h000'
                endfunction
    Replace 'h000' with the raw code of the dummy unit object in your map. To see the raw code, go to object editor then press CTRL+D, press it again to revert.

    Same thing for main ability, slow ability, and the buff.
Sorry I can make a better instruction actually but I'm quite busy atm.

Thanks for using the spell.
 
Top