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

Dark Matter v2.1

235220-albums7916-picture93926.png


(Description)
Summons a dark matter at the targeted point. The dark matter has ability to absorb all enemy units within 400 range onto it's position while releasing smaller dark particles to attack those captured units. Each particle deals 90 damage on hit. Lasts for 15 seconds.​

(Details)
  • Level(s): 1
  • Manacost: 270
  • Cooldown: 145 s
  • Cast range: 800
  • Area of Effect: 400
235220-albums7916-picture93928.png

235220-albums7916-picture93932.gif
235220-albums7916-picture93930.png


235220-albums7916-picture93929.png
(Required)
  • Stack
  • CTL
  • WorldBounds
(Optional)
  • SpellEffectEvent
  • AutoFly
  • Table
235220-albums7916-picture93927.png

  • Import all necessary datas (imports, objects, triggers, etc.) into your map.
  • Install all required dependencies correctly.
  • Configure the spell.
  • Done.

235220-albums7916-picture93924.png


(Readme)
JASS:
scope DarkMatter
/*

            ~* Dark Matter *~
                    version 2.1
           
        Created by: Dalvengyr aka Quilnez
        Copyright 2015
   
        This resource is copyright protected.
        Don't redistribute without permission.
       
        You are free to edit, use, remake, etc.
        but don't remove the copyright notes
        above.
   
*/

    /*                 *\
        Configuration
    \*                 */
   
    globals
   
    /*  I. General settings */
   
        // Dummy unit's raw code at Object Editor
        private constant integer    DUMMY_OBJECT_ID       = 'h000'
       
        // Main spell's raw code at Object Editor
        private constant integer    SPELL_OBJECT_ID       = 'A000'
       
        // General decay time for special effects
        private constant real       SFX_DECAY_TIME        = 5.0
       
        // General units' hit z offset. Used for 3D collision
        private constant real       UNITS_HIT_Z_OFFSET    = 50.0
       
   
    /*  II. Orb settings
            (Orb is an object at the center of spell area)
    */
        // Model's file path
        private constant string     ORB_SFX               = "war3mapImported\\BlackHole.mdx"
       
        // Flying height
        private constant real       ORB_HEIGHT_Z          = 0.0
       
        // Scale/size
        private constant real       ORB_SCALE             = 1.0
       
        // How bad range between victims and the orb can affect the absorb power
        private constant real       ORB_POWER_FACTOR      = 0.375
       
       
    /*  III. Swirl settings
             (Swirl consists of objects which swirl around the main orb)
    */
        // Raw code at Object Editor
        private constant integer    SWIRL_WAVE_OBJECT_ID  = 'h001'
       
        // Animation speed
        private constant real       SWIRL_TIME_SCALE      = 0.1
       
        // Flying height
        private constant real       SWIRL_HEIGHT_Z        = 100.0
       
        // Scale/size
        private constant real       SWIRL_SCALE           = 1.25
       
       
    /*  IV. Particle settings
            (Particles are missiles that are periodically released by the orb)
    */
        // Model file path
        private constant string     PARTICLE_SFX          = "Abilities\\Weapons\\AvengerMissile\\AvengerMissile.mdl"
   
        // Starting fly height when launched
        private constant real       PARTICLE_LAUNCH_Z     = 100.0
   
        // Scale/size
        private constant real       PARTICLE_SCALE        = 0.2
   
        // Turn rate
        private constant real       PARTICLE_TURN_SPEED   = 0.1
   
        // Max range between particle at target to hit the target
        private constant real       PARTICLE_HIT_RADIUS   = 70.0
   
        // If false, each particle can only hits one target
        private constant boolean    PARTICLE_PIERCING     = false
       
        // Dealt damage setting
        private constant attacktype PARTICLE_ATTACK_TYPE  = ATTACK_TYPE_NORMAL
        private constant damagetype PARTICLE_DAMAGE_TYPE  = DAMAGE_TYPE_NORMAL
       
        endglobals
   
    /*  V. Dynamic settings
            (Allows you to set dynamic values based on parameters)
    */
   
        // Number of created wave to swirl around the orb
        private constant function SwirlCount takes integer level returns integer
            return 9
        endfunction
       
        // Range/distance from the orb to the created waves
        private constant function SwirlRadius takes integer level returns real
            return 125.0
        endfunction
       
        // Rotation speed of waves, in radians
        private constant function SwirlRotation takes integer level returns real
            return 0.09
        endfunction
       
        // Move speed of each particle
        private constant function ParticleSpeed takes integer level returns real
            return 5.0
        endfunction
       
        // Minimum delay before the orb releases another particle
        private constant function ParticleSpawnDelayMin takes integer level returns real
            return 0.0
        endfunction
       
        // Maximum delay before the orb releases another particle
        private constant function ParticleSpawnDelayMax takes integer level returns real
            return 0.5
        endfunction
       
        // The absorbtion power
        private constant function OrbPower takes integer level returns real
            return 15.0
        endfunction
       
        // Dealt damage when particle hits a target
        private constant function Damage takes integer level returns real
            return 90.0
        endfunction
       
        // Maximum range between the orb and targets to absorb them
        private constant function AoE takes integer level returns real
            return 400.0
        endfunction
       
        // Duration of the spell
        private constant function Duration takes integer level returns real
            return 15.0
        endfunction
       
        // Maximum missile count launched to each target
        private constant function MaxCount takes integer level returns integer
            return 99
        endfunction
       
        // Classifications of targets that can be affected by this spell.
        private constant function SpellTargets takes unit target, player caster returns boolean
            return IsUnitEnemy(target, caster) and not IsUnitType(target, UNIT_TYPE_STRUCTURE)
        endfunction
       
        // You can add any additional effects to the target here
        // This function is executed right before the damage is dealt to
        // the target
        private module DarkMatterDamageEvent
            static method onDamage takes unit caster, unit target returns nothing
               
            endmethod
        endmodule
   
    // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   
    globals
        private constant real INTERVAL = 0.0312500
        private location Loc = Location(0, 0)
        private group Group  = CreateGroup()
        private unit Checker = null
    endglobals
   
    // Native declaration
    native UnitAlive takes unit id returns boolean
   
    // Reset ground unit's position without interrupting orders
    private function UnstuckUnit takes unit whichUnit returns nothing
        if IsUnitType(whichUnit, UNIT_TYPE_GROUND) then
            call SetUnitPosition(Checker, GetUnitX(whichUnit), GetUnitY(whichUnit))
            call SetUnitX(whichUnit, GetUnitX(Checker))
            call SetUnitY(whichUnit, GetUnitY(Checker))
        endif
    endfunction
   
    private function GetLocZ takes real x, real y returns real
        call MoveLocation(Loc, x, y)
        return GetLocationZ(Loc)
    endfunction
       
    private function SetUnitZ takes unit u, real z returns nothing
        call SetUnitFlyHeight(u, z - GetLocZ(GetUnitX(u), GetUnitY(u)), 0)
    endfunction
   
    // Stack used to contain waves
    private struct Swirl extends array
        unit unit
        implement Stack
    endstruct
   
    private struct Tornado extends array
       
        Swirl swirl
        integer count
       
        real distance
        real angle
        real rotation
       
        real space
        real x
        real y
        real z
       
        static constant real TAU = 2*bj_PI
       
        method terminate takes nothing returns nothing
           
            local Swirl node = .swirl.first
           
            // Kill all waves
            loop
                exitwhen node == 0
                call KillUnit(node.unit)
                set node.unit = null
                set node = node.next
            endloop
           
            call .swirl.destroy()
            call destroy()
           
        endmethod
       
        implement CTL
       
            local real a
            local real x2
            local real y2
            local integer i
            local Swirl node
           
        implement CTLExpire
       
            set i = .count
            set node = .swirl.first
            set .angle = .angle + .rotation
           
            // Iterate update nodes' angles/rotations
            loop
                exitwhen i <= 0
                set a = .angle+.space*i
                set x2 = .x+.distance*Cos(a)
                set y2 = .y+.distance*Sin(a)
                call SetUnitX(node.unit, x2)
                call SetUnitY(node.unit, y2)
                call SetUnitFacing(node.unit, a*bj_RADTODEG)
                call SetUnitZ(node.unit, .z + SWIRL_HEIGHT_Z)
                set node = node.next
                set i = i - 1
            endloop
           
        implement CTLEnd
       
        static method spawn takes player p, integer count, real x, real y, real dist, real rot returns thistype
           
            local thistype this = create()
            local integer i = 0
            local real a
            local real x2
            local real y2
            local Swirl node
           
            // Allocate stack for waves
            set .swirl = Swirl.create()
            // Angle difference between each wave
            set .space = TAU/count
            set .angle = GetRandomReal(-bj_PI, bj_PI)
            set .distance = dist
            set .rotation = rot
            set .count = count
            set .x = x
            set .y = y
            set .z = GetLocZ(x, y) + ORB_HEIGHT_Z
           
            // Create the waves and store into the stack
            loop
                exitwhen i >= count
                // Allocate new node to the stack
                set node = .swirl.push()
                set a = .angle+.space*i
                set x2 = x+dist*Cos(a)
                set y2 = y+dist*Sin(a)
                set node.unit = CreateUnit(p, SWIRL_WAVE_OBJECT_ID, x2, y2, a*bj_RADTODEG)
                call SetUnitScale(node.unit, SWIRL_SCALE, 1, 1)
                call SetUnitTimeScale(node.unit, SWIRL_TIME_SCALE)
                if SWIRL_HEIGHT_Z > 0 then
                    static if not LIBRARY_AutoFly then
                        if UnitAddAbility(node.unit, 'Amrf') and UnitRemoveAbility(node.unit, 'Amrf') then
                        endif
                    endif
                    call SetUnitZ(node.unit, .z + SWIRL_HEIGHT_Z)
                endif
                set i = i + 1
            endloop
           
            return this
        endmethod
       
    endstruct
   
    private keyword DarkMatter
   
    // Launch 3D homing missile
    private struct SimpleMissile extends array
       
        effect sfx
        player owner
        group targets
       
        unit caster
        unit target
        unit missile
       
        real x
        real y
        real z
       
        real dc
        real dx
        real damage
       
        real turn
        real angle
        real speed
       
        method terminate takes nothing returns nothing
       
            // Group is only created if piercing is true
            static if PARTICLE_PIERCING then
                call DestroyGroup(.targets)
                set .targets = null
            endif
            call DestroyEffect(.sfx)
            call UnitApplyTimedLife(.missile, 'BTLF', SFX_DECAY_TIME)
            call destroy()
            // Remove leaks
            set .missile = null
            set .target = null
            set .caster = null
            set .sfx = null
           
        endmethod
       
        implement optional DarkMatterDamageEvent
       
        implement CTL
       
            local real a
            local real v
            local real h
           
            local real d
            local real x
            local real y
           
            local unit u
            local unit t
            local integer rand
           
        implement CTLExpire
       
            set .dc = .dc + .speed
            set .x = .x + .speed * Cos(.angle)
            set .y = .y + .speed * Sin(.angle)
            // Parabola equation
            set v = 4 * (.dx-.dc) * (.dc/.dx) + PARTICLE_LAUNCH_Z
            // If not supposed to dead yet
            if v > 0 and .x < WorldBounds.maxX and .x > WorldBounds.minX and .y < WorldBounds.maxY and .y > WorldBounds.minY and UnitAlive(.caster) then
                call SetUnitX(.missile, .x)
                call SetUnitY(.missile, .y)
                call SetUnitFlyHeight(.missile, v, 0)
                // Adjust the angle to face the target
                set a = Atan2(GetUnitY(.target)-.y, GetUnitX(.target)-.x)
                if Cos(.angle - a) < Cos(.turn) then
                    if Sin(a - .angle) >= 0 then
                        set .angle = .angle + .turn
                    else
                        set .angle = .angle - .turn
                    endif
                else
                    set .angle = a
                endif
                // Determine one random target from all possible targets
                static if not PARTICLE_PIERCING then
                    set t = null
                    set rand = 0
                endif
               
                // Iterates all units around the missile
                call GroupEnumUnitsInRange(Group, .x, .y, PARTICLE_HIT_RADIUS, null)
                loop
                    set u = FirstOfGroup(Group)
                    exitwhen u == null
                    call GroupRemoveUnit(Group,  u)
                    if UnitAlive(u) and SpellTargets(u, owner) then
                        set x = GetUnitX(u)
                        set y = GetUnitY(u)
                        set h = GetUnitFlyHeight(u) + UNITS_HIT_Z_OFFSET - v
                        set d = SquareRoot((.x-x)*(.x-x)+(.y-y)*(.y-y))
                        // 3D spherical collision
                        if SquareRoot(d*d+h*h) <= PARTICLE_HIT_RADIUS then
                            static if PARTICLE_PIERCING then
                                if not IsUnitInGroup(u, .targets) then
                                    static if thistype.onDamage.exists then
                                        call thistype.onDamage(.caster, u)
                                    endif
                                    call UnitDamageTarget(.caster, u, .damage, false, false, PARTICLE_ATTACK_TYPE, PARTICLE_DAMAGE_TYPE, null)
                                    call GroupAddUnit(.targets, u)
                                endif
                            else
                                // Quite effective to obtain random unit from a group
                                set rand = rand + 1
                                if GetRandomInt(1, rand) == 1 then
                                    set t = u
                                endif
                            endif
                        endif
                    endif
                endloop
               
                static if not PARTICLE_PIERCING then
                    // If a target is found
                    if t != null then
                        static if thistype.onDamage.exists then
                            call thistype.onDamage(.caster, t)
                        endif
                        call UnitDamageTarget(.caster, t, .damage, false, false, PARTICLE_ATTACK_TYPE, PARTICLE_DAMAGE_TYPE, null)
                        call terminate()
                        set t = null
                    endif
                endif
            else
                call terminate()
            endif
           
        implement CTLEnd
       
        static method launch takes DarkMatter source, unit target returns thistype
           
            local thistype this = create()
            local real x = GetUnitX(target)
            local real y = GetUnitY(target)
           
            set .target = target
            set .caster = source.caster
            set .owner  = source.owner
            // Launch from random location nearby the orb
            set .x = source.x + GetRandomReal(-source.tornado.distance, source.tornado.distance)
            set .y = source.y + GetRandomReal(-source.tornado.distance, source.tornado.distance)
            set .angle = GetRandomReal(-bj_PI, bj_PI)
           
            set .missile = CreateUnit(.owner, DUMMY_OBJECT_ID, .x, .y, .angle*bj_RADTODEG)
            set .sfx = AddSpecialEffectTarget(PARTICLE_SFX, .missile, "origin")
            set .turn = PARTICLE_TURN_SPEED
            set .damage = source.damage
            set .speed = source.speed
            set .dx = source.aoe
            set .dc = 0
           
            // Create group if only piercing is true
            static if PARTICLE_PIERCING then
                set .targets = CreateGroup()
            endif
            static if not LIBRARY_AutoFly then
                if UnitAddAbility(.missile, 'Amrf') and UnitRemoveAbility(.missile, 'Amrf') then
                endif
            endif
            call SetUnitFlyHeight(.missile, PARTICLE_LAUNCH_Z, 0)
            call SetUnitScale(.missile, PARTICLE_SCALE, 1, 1)
           
            return this
        endmethod
       
    endstruct
   
    // Main spell's struct
    private struct DarkMatter extends array
   
        unit orb
        unit caster
        group targets
       
        Tornado tornado
        integer hitx
        player owner
        effect sfx
       
        real aspd
        real aspdo
        real aspdx
        real speed
       
        real damage
        real power
        real aoe
       
        real duration
        real x
        real y
       
        real delay
        real delayx
        real rotation
        real amount
       
        static if LIBRARY_Table then
            static TableArray Ht
        else
            static hashtable Ht
        endif
       
        static constant real HP = bj_PI/2
       
        method terminate takes nothing returns nothing
       
            local unit u
       
            // Turn all remaining units' collision back to on
            loop
                set u = FirstOfGroup(.targets)
                exitwhen u == null
                call GroupRemoveUnit(.targets, u)
                call SetUnitPathing(u, true)
                call UnstuckUnit(u)
                static if LIBRARY_Table then
                    call Ht[this].integer.remove(GetHandleId(u))
                else
                    call RemoveSavedInteger(Ht, GetHandleId(u), 0)
                endif
            endloop
       
            call .tornado.terminate()
            call DestroyEffect(.sfx)
            call DestroyGroup(.targets)
            call UnitApplyTimedLife(.orb, 'BTLF', SFX_DECAY_TIME)
           
            call destroy()
            // Remove leaks
            set .targets = null
            set .caster = null
            set .orb = null
            set .sfx = null
           
        endmethod
       
        implement CTL
           
            local group g
            local boolean b
            local integer hand
       
            local integer rand = 0
            local unit t = null
            local unit u
           
            local real d
            local real x
            local real y
           
            local real h
            local real a
            local real pow
           
        implement CTLExpire
       
            if .duration > INTERVAL and UnitAlive(.caster) then
                set .duration = .duration - INTERVAL
                // Iterate through all units around the orb (within aoe).
                call GroupEnumUnitsInRange(Group, .x, .y, .aoe, null)
                loop
                    set u = FirstOfGroup(Group)
                    exitwhen u == null
                    call GroupRemoveUnit(Group, u)
                    if UnitAlive(u) and SpellTargets(u, owner) then
                        set x = GetUnitX(u)
                        set y = GetUnitY(u)
                        set d = SquareRoot((.x-x)*(.x-x)+(.y-y)*(.y-y))
                        // Power is affected by distance between orb and the target.
                        set pow = .power - .power*(d/.aoe)*ORB_POWER_FACTOR
                        // Calculate target angle.
                        set a = Atan2(.y-y, .x-x)-(HP*(d/.aoe))*.rotation
                        if not IsUnitInGroup(u, .targets) then
                            call GroupAddUnit(.targets, u)
                            call SetUnitPathing(u, false)
                        endif
                        if .aspd <= INTERVAL then
                            static if LIBRARY_Table then
                                set b = Ht[this].integer[GetHandleId(u)] < .hitx
                            else
                                set b = LoadInteger(Ht, this, GetHandleId(u)) < .hitx
                            endif
                            if b then
                                set rand = rand + 1
                                if GetRandomInt(1, rand) == 1 then
                                    set t = u
                                endif
                            endif
                        endif
                        if d > pow then
                            call SetUnitX(u, x + pow * Cos(a))
                            call SetUnitY(u, y + pow * Sin(a))
                        else
                            call SetUnitX(u, .x)
                            call SetUnitY(u, .y)
                        endif
                    endif
                endloop
               
                // Iterates all affected units which have
                // escaped the spell area and turn their
                // collision on.
                set g = .targets
                set .targets = CreateGroup()
                loop
                    set u = FirstOfGroup(g)
                    exitwhen u == null
                    call GroupRemoveUnit(g, u)
                    set x = GetUnitX(u)
                    set y = GetUnitY(u)
                    if SquareRoot((.x-x)*(.x-x)+(.y-y)*(.y-y)) > .aoe then
                        call SetUnitPathing(u, true)
                        call UnstuckUnit(u)
                        static if LIBRARY_Table then
                            call Ht[this].integer.remove(GetHandleId(u))
                        else
                            call RemoveSavedInteger(Ht, this, GetHandleId(u))
                        endif
                    else
                        call GroupAddUnit(.targets, u)
                    endif
                endloop
               
                if .aspd > INTERVAL then
                    set .aspd = .aspd - INTERVAL
                elseif t != null then
                    // Launch missile if a random target is found
                    set .aspd = GetRandomReal(.aspdo, .aspdx)
                    call SimpleMissile.launch(this, t)
                    set hand = GetHandleId(t)
                    static if LIBRARY_Table then
                        set Ht[this].integer[hand] = Ht[this].integer[hand] + 1
                    else
                        call SaveInteger(Ht, this, hand, LoadInteger(Ht, this, hand) + 1)
                    endif
                    set t = null
                endif
                // Remove leaks
                call DestroyGroup(g)
                set g = null
            else
                call terminate()
            endif
           
        implement CTLEnd
       
        static method onCast takes nothing returns nothing
           
            local thistype this = create()
            local integer l
           
            set .caster = GetTriggerUnit()
            set .owner = GetTriggerPlayer()
            set .x = GetSpellTargetX()
            set .y = GetSpellTargetY()
            set .targets = CreateGroup()
            set l = GetUnitAbilityLevel(.caster, SPELL_OBJECT_ID)
            set .orb = CreateUnit(.owner, DUMMY_OBJECT_ID, .x, .y, 270)
            set .sfx = AddSpecialEffectTarget(ORB_SFX, .orb, "origin")
            set .duration = Duration(l)
            set .power = OrbPower(l)
            set .aoe = AoE(l)
           
            set .rotation = SwirlRotation(l)
            set .tornado = Tornado.spawn(.owner, SwirlCount(l), .x, .y, SwirlRadius(l), .rotation)
            // Get the rotation direction
            set .rotation = .rotation/RAbsBJ(.rotation)
            set .speed = ParticleSpeed(l)
            set .damage = Damage(l)
            set .hitx = MaxCount(l)
            set .aspdx = ParticleSpawnDelayMax(l)
            set .aspdo = ParticleSpawnDelayMin(l)
            set .aspd = GetRandomReal(.aspdo, .aspdx)
            call SetUnitScale(.orb, ORB_SCALE, 1, 1)
           
            if ORB_HEIGHT_Z > 0 then
                static if not LIBRARY_AutoFly then
                    if UnitAddAbility(.orb, 'Amrf') and UnitRemoveAbility(.orb, 'Amrf') then
                    endif
                endif
                call SetUnitFlyHeight(.orb, ORB_HEIGHT_Z, 0)
            endif
           
        endmethod
           
        static if not LIBRARY_SpellEffectEvent then
            private static method check takes nothing returns boolean
                if GetSpellAbilityId() == SPELL_OBJECT_ID then
                    call thistype.onCast()
                endif
                return false
            endmethod
        endif
       
        static method onInit takes nothing returns nothing

            local trigger t
           
            static if LIBRARY_SpellEffectEvent then
                call RegisterSpellEffectEvent(SPELL_OBJECT_ID, function thistype.onCast)
            else
                set t = CreateTrigger()
                call TriggerRegisterAnyUnitEventBJ(t, EVENT_PLAYER_UNIT_SPELL_EFFECT)
                call TriggerAddCondition(t, Condition(function thistype.check))
            endif
            static if LIBRARY_Table then
                set Ht = TableArray[0x2000]
            else
                set Ht = InitHashtable()
            endif
            set Checker = CreateUnit(Player(PLAYER_NEUTRAL_PASSIVE), 'uabo', 0, 0, 0)
            call PauseUnit(Checker, true)
            call ShowUnit(Checker, false)
           
        endmethod
       
    endstruct
   
endscope

235220-albums7916-picture93925.png
  • Nestharus
    | Stack, CTL, WorldBounds, AutoFly​
  • Bribe
    | SpellEffectEvent, Table​
  • JetFangInferno
    | Deathwave.mdx​
  • WILL THE ALMIGHTY
    | Blackhole.mdx​
  • Hellx-Magnus
    | BTNEyeOfShadow​
Contents

Dark Matter (Map)

Reviews
12:38, 15ndth Sep 2015 This resource has been Approved by BPower. Criticism: Impressive spell and excellent configuration options. Good Job! I agree that a birth animation for the wave model would be awesome. 16:15, 8th Apr 2015 IcemanBo...

Moderator

M

Moderator

12:38, 15ndth Sep 2015

This resource has been Approved by BPower.

Criticism:
Impressive spell and excellent configuration options. Good Job!
I agree that a birth animation for the wave model would be awesome.

16:15, 8th Apr 2015
IcemanBo: Read post in thread.
 

Kazeon

Hosted Project: EC
Level 33
Joined
Oct 12, 2011
Messages
3,449
Also I don't get it, why implement a native if you can create one?(see Maker's method)
They said native is the most powerful one to check unit alive.

just why? why not a global instead of a struct?
Bcz it's only used by that struct. Dunno, just my style :)

Honestly, I think the more standard way (less lazy) is to create two timers. The first is the periodic timer than runs your effect. The second is the timeout timer that ends the effect. This is how I do spells anyways :eek:
You do spells?
 
Hey Quilnez,

in my test I created a Dark Matter at cliffs and as result the enemy units got stucked in into it.
The units had no chance to flee, and I killed em all easily. \o/
No, now seriously... there probably should be kind of a check to prevent units to get to positions where they are not able to move anymore.

When testing scenario with dying caster, bug occurs.
When testing scenario with caster being removed, bug occurs and no damage will be dealt after removal.

Please privatize your demo functions. The map didn't compile for me... I'm not certain why only for me.
But privatising "function start" helped for me, as it was re-declared for me. (first comes from Stack library)

Well coded, very readable. Good presentation. :)
 

Kazeon

Hosted Project: EC
Level 33
Joined
Oct 12, 2011
Messages
3,449
Update!
- Fixed stuck issues
- Fixed damage bug when caster's dead
- Added fancy sound effect to the orb model
- To avoid being too overpowered, now you may configure how many times a unit may be targeted by the missiles. But now it uses Table (optional).
- Swirls' height z is now equalized to orb's height z
- Minimum spawn rate for missiles is now configurable
- A lot of documentation improvements
- Minimized code size


I would be loved if someone's willing to help me, to add some kind of "birth animation" to the wave model. Where it grows from nothing to it's normal size. :)
 
Level 19
Joined
Mar 18, 2012
Messages
1,716
I discovered once an issue with the KillUnit native and units having alloc.
KillUnit enables these unit for GroupEnumUnitInRange enumeration, which can
lead to unwanted problems. I discovered this when I was working on Missile and
tried to figure out the best solution to remove a missile delayed.
When I used KillUnit, missile which were fired later in the same angle/direction,
evaluated the onCollide method.
 
Top