Need Help fixing a bug with a system

Coding Help

Need Help debugging a system please test map,
I am having trouble with a spell called Meteor Shower, the first cast works the second cast buggs, it sends way to many meteors, the meteors don't deal damage and some of them don't move.

Code (jass) Select
library Effects uses Target
    globals
        private force eval = CreateForce()
        spelleffect RUNNING
        spellprojectile PROJECTILE
        private boolean FINISHED
    endglobals
    function ReturnEffect takes boolean continue returns nothing
        set FINISHED = continue
    endfunction
    module Rarray
        real d0
        real d1
        real d2
        real d3
        method operator [] takes integer i returns real
            if i < 2 then
                if i == 0 then
                    return d0
                endif
                return d1
            endif
            if i == 2 then
                return d2
            endif
            return d3
        endmethod
        method operator []= takes integer i, real r returns nothing
            if i < 2 then
                if i == 0 then
                    set d0 = r
                    return
                endif
                set d1 = r
                return
            endif
            if i == 2 then
                set d2 = r
                return
            endif
            set d3 = r
            return
        endmethod
    endmodule
    struct spelleffect_root extends array
        static      thistype array Rc   
        static      integer c           = 0
        boolexpr action
        integer instance
        integer model
        static method allocate takes nothing returns thistype
            local thistype this = Rc[0]
            if 0 == this then
                set this = c+1
                set c = this
            else
                set Rc[0] = Rc[this]
            endif
            return this
        endmethod
        method deallocate takes nothing returns nothing
            if 0 == this then
                return
            endif
            set Rc[this]= Rc[0]
            set Rc[0] = this
        endmethod
        implement Rarray
        static method create takes nothing returns thistype
            local thistype this = allocate()
            return this
        endmethod
        /*static method createEx takes boolexpr b, real d0, real d1, real d2, real d3 returns thistype
            local thistype this = allocate()
            set action = b
            set this[0]= d0
            set this[1]= d1
            set this[2] = d2
            set this[3] = d3
            set instance = 0
            return this
        endmethod*/
        method unlock takes nothing returns nothing
            if this!= 0 then
                set instance = instance-1
                if instance < 1 then
                    call this.deallocate()
                endif
            endif
        endmethod
        method lock takes nothing returns nothing
            set instance = instance+1
        endmethod
    endstruct
    struct spelleffect extends array
        static      thistype array Rc   
        static      integer c           = 0
        boolexpr action
        Spell_Cast spell
        integer next
        integer model
        Target caster
        Target target
        spelleffect master
        static method allocate takes nothing returns thistype
            local thistype this = Rc[0]
            if 0 == this then
                set this = c+1
                set c = this
            else
                set Rc[0] = Rc[this]
            endif
            return this
        endmethod
        method deallocate takes nothing returns nothing
            set Rc[this]= Rc[0]
            set Rc[0] = this
        endmethod
        method destroy takes nothing returns nothing
            if 0 == this then
                return
            endif
            debug call BJDebugMsg("Destroying Effect "+I2S(this))
            if this.isProxy then
                call target.unlock()
                call caster.unlock()
                call spell.unlock()
            endif
            set this.action = null
            call this.deallocate()
        endmethod
        method operator isProxy takes nothing returns boolean
            return master != 0
        endmethod
        implement Rarray
        static method create takes spelleffect_root root, Spell_Cast boss returns thistype
            local thistype this = allocate()
            set action = root.action
            set this[0] = root[0]
            set this[1] = root[1]
            set this[2] = root[2]
            set this[3] = root[3]
            set this.spell = boss
            set this.model = root.model
            set this.target = boss.target
            set this.master = 0
            set this.caster = boss.caster
            set boss[boss.effects]= this
            set boss.effects = boss.effects+1
            return this
        endmethod
        method run takes nothing returns boolean
            set RUNNING = this
            set FINISHED = true
            call ForceEnumPlayersCounted(eval,action,1)
            return FINISHED
        endmethod
        static method createProxy takes spelleffect master,Target caster, Target t returns thistype
            local thistype this = allocate()
            set .action = master.action
            set this[0]= master[0]
            set this[1]= master[1]
            set this[2]= master[2]
            set this[3]= master[3]
            set .next = master.next
            set .master = master
            set .target = t
            set .spell = master.spell
            set .model = master.model
            set .caster = caster
            call caster.lock()
            call t.lock()
            call .spell.lock()
            return this
        endmethod
    endstruct
    function CreateSpellEffect takes boolexpr b, real d0, real d1, real d2, real d3, integer model returns spelleffect_root
        local spelleffect_root this = spelleffect_root.create()
        set this.action = b
        set this[0] = d0
        set this[1] = d1
        set this[2] = d2
        set this[3] = d3
        set this.model = model
        return this
    endfunction
endlibrary


Code (jass) Select
library SpellGenerator /* v0.2.3.0
*************************************************************************************
*
*         Enables the generation of spells in game and can also be used
*             to easily make new spells with just a few keystrokes
*
*************************************************************************************
*
*      */uses /*
*                    */ Target /*
*                    */ SFX /*
*                    */ Effects /* 
*                    */ SpellProjectile/*
***************************************************************************************
*
* struct Spell extends array
*       boolean permanent  whether to keep or destroy the spell when it has no instances
*
*       method operator [] takes integer i returns integer
*               this retur
*       method operator []= takes integer i integer returns nothing
*               be warned you can leak effects if you do not unlock the effect first
*       method lock takes nothing returns nothing
*               locks the spell preventing it from getting destroyed
*       method unlock takes nothing returns nothing
*               when you are done with a spell you should unlock it
*                   has no effect on permanent spells
*
*       static method createEx takes nothing returns Spell
*           
*****/
    private module allocator
        static integer array recycle
        static integer c = 0
        static method allocate takes nothing returns thistype
            local thistype this = recycle[0]
            if this == 0 then
                set this = c+1
                set c = this
            else
                set recycle[0] = recycle[this]
            endif
    endmodule
    private module deallocate
        method deallocate takes nothing returns nothing
            if 0 == this then
                call BJDebugMsg("Attempted to deallocate a null struct")
                return
            endif
            set recycle[this] = recycle[0]
            set recycle[0] = this
        endmethod
    endmodule
    private module serarray
        spelleffect_root d0
        spelleffect_root d1
        spelleffect_root d2
        spelleffect_root d3
        method operator [] takes integer i returns spelleffect_root
            if i < 2 then
                if i == 0 then
                    return d0
                endif
                return d1
            endif
            if i == 2 then
                return d2
            endif
            return d3
        endmethod
        method operator []= takes integer i, integer what returns nothing
            if i < 2 then
                if i ==0 then
                    set d0 = what
                    return
                endif
                set d1 = what
                return
            endif
            if i == 2 then
                set d2 = what
                return
            endif
            set d3 = what
        endmethod
    endmodule
    private module searray
        spelleffect d0
        spelleffect d1
        spelleffect d2
        spelleffect d3
        method operator [] takes integer i returns spelleffect
            if i < 2 then
                if i == 0 then
                    return d0
                endif
                return d1
            endif
            if i == 2 then
                return d2
            endif
            return d3
        endmethod
        method operator []= takes integer i, integer what returns nothing
            if i < 2 then
                if i ==1 then
                    set d1 = what
                    return
                endif
                set d0 = what
                return
            endif
            if i == 2 then
                set d2 = what
                return
            endif
            set d3 = what
        endmethod
    endmodule
   
    struct Spell_Cast extends array
        Target caster
        Target target
        Spell root
        //integer current
        integer instance
        integer effects
        implement searray
        implement allocator
            //set instance = 0
            set effects = 0
            return this
        endmethod
        implement deallocate
        method lock takes nothing returns nothing
            set .instance = .instance+1
        endmethod
        method destroy takes nothing returns nothing
            debug call BJDebugMsg("Destroyed Spell"+I2S(this))
            call this[0].destroy()
            call this[1].destroy()
            call this[2].destroy()
            call this[3].destroy()
            call root.unlock()
            call target.unlock()
            call caster.unlock()
            call deallocate()
        endmethod
        method unlock takes nothing returns nothing
            if .instance > 0 then
                set .instance = .instance-1
                if .instance == 0 then
                    call destroy()
                endif
            endif
        endmethod
        method core takes spelleffect current returns boolean
            local spelleffect Snext = 0
            local integer next
            debug call BJDebugMsg("Running core for "+I2S(current))
            if current < 0 then
                set next = 1
                set Snext = this[0]
            elseif current == 0 then
                call unlock()
                return true
            else
                set next = current.next
                if current.isProxy then
                   
                    debug call BJDebugMsg(I2S(current)+" is a Proxy")
                    if next != 0 then
                        debug call BJDebugMsg("creating new Proxy")
                        set Snext = spelleffect.createProxy(this[next],current.caster, current.target)
                    endif         
                    call current.destroy()
                else
                    set Snext = this[next]
                endif
            endif
            if next == 0 then
                call unlock()
                call BJDebugMsg("Next = 0 .instance ="+I2S(this.instance))
                return true
            endif
           
            if Snext.run() then
                debug call BJDebugMsg("The effect ran, going to next effect")
                call core(Snext)
                return false
            endif
            debug call BJDebugMsg("The effect ran, and is waiting to finish")
            return false
        endmethod
        static method create takes Spell root, Target t returns thistype
            local thistype this = allocate()
            local integer i = 0
            set target = t
            set instance = 1
            call t.lock()
            loop
                if root[i] == 0 then
                    set i = i -1
                    exitwhen true
                endif
                set this[i] = spelleffect.create( root[i], this)
                set this[i].next = i+1
                set i = i+1
                exitwhen i == 4
            endloop
            set this[i].next = 0
            set .root = root
            return this
        endmethod
    endstruct
    struct Spell extends array
        boolean permanent
        private integer instance
        implement serarray
        implement allocator
            return this
        endmethod
        implement deallocate
        method destroy takes nothing returns nothing
            call deallocate()
            call this[0].unlock()
            call this[1].unlock()
            call this[2].unlock()
            call this[3].unlock()
        endmethod
        static method create takes spelleffect_root first returns thistype
            local thistype this = allocate()
            set this[0] = first
            return this
        endmethod
        static method createEx takes spelleffect_root s0, spelleffect_root s1, spelleffect_root s2, spelleffect_root s3, boolean destroy returns thistype
            local thistype this = allocate()
            call s0.lock()
            call s1.lock()
            call s2.lock()
            call s3.lock()
            set this[0] = s0
            set this[1] = s1
            set this[2] = s2
            set this[3] = s3
            set permanent = not destroy
            return this
        endmethod
        method lock takes nothing returns nothing
            set .instance = .instance+1
        endmethod
        method unlock takes nothing returns nothing
            set .instance = .instance-1
            if not permanent and .instance < 0 then
                call destroy()
            endif
        endmethod
        method cast takes unit caster, Target target returns boolean // the return value is whether the spell completed every thing instantly, or if it is waiting.
            local Spell_Cast cast = Spell_Cast.create(this,target)
            call lock()
            //call cast.lock()
            set cast.caster = Target[caster]
            call cast.caster.lock()
            //set cast.target = target
            //call cast.caster.lock()
            return cast.core(-1)
        endmethod
    endstruct
    function CreateSpell takes spelleffect_root s0, spelleffect_root s1, spelleffect_root s2, spelleffect_root s3, boolean destroy returns Spell
        local Spell this = Spell.allocate()
        call s0.lock()
        call s1.lock()
        call s2.lock()
        call s3.lock()
        static if DEBUG_MOD then
            if s0 == 0 then
                call BJDebugMsg("Trying to create a spell with a null first effect")
                return 0
            endif
        endif
        set this[0] = s0
        set this[1] = s1
        set this[2] = s2
        set this[3] = s3
        set this.permanent = not destroy
        return this
    endfunction
endlibrary


Code (jass) Select
library LibraryOfEffects uses Effects, SpellGenerator
    globals
        private boolexpr epcast
        private spelleffect array next
        private spelleffect array prev
        private real array Sangle
        private real array Eangle
        private integer array left
        private integer total = 0
        private real array time
        private real array distance
        private timer EP_Timer = CreateTimer()
        private constant real PERIOD = .0325000
    endglobals
    private function ep takes nothing returns nothing
        local spelleffect this = next[0]
        local real angle
        local real dis
        call BJDebugMsg("its working total ="+I2S(total))
        if total == 0 then
            set next[0] = 0
            set prev[0] = 0
            return
        endif
        if this.spell[1].action == epcast then
            call BJDebugMsg("Effect "+I2S(this.spell[1])+" has the wrong action")
        endif
        loop
            exitwhen 0 == this
            set time[this] = time[this]-PERIOD
            if time[this]<= 0 then
                set angle = GetRandomReal(Sangle[this],Eangle[this])
                set dis = GetRandomReal(0,distance[this])

                call this.spell.core(spelleffect.createProxy(this,this.caster,  /*
                    */Target.create(this.target.x+Cos(angle)*dis,this.target.y+Sin(angle)*dis,0)))
               
                set left[this] = left[this]-1
                if left[this]<= 0 then
                    call BJDebugMsg("In EP periodic With next["+I2S(this)+"]="+I2S(next[this])+" and prev["+I2S(this)+"]="+I2S(prev[this]))
                    set next[prev[this]]=next[this]
                    set prev[next[this]]=prev[this]
                   

                    set total = total-1

                    call this.spell.unlock()//this is neccessary as it always calls back to the core via proxy
                    if this.isProxy then
                        call this.destroy()//also neccessary to prevent leaks
                    endif
                    if total == 0 then
                        set next[0] = 0
                        set prev[0] = 0
                        return
                    endif

                else
                    set time[this] = time[this]+this[1]
                endif
            endif
       
            set this = next[this]
        endloop
        call TimerStart(EP_Timer,PERIOD,false,function ep)
    endfunction
    function ep_cast takes nothing returns boolean
        local spelleffect this = RUNNING
        local real face = GetUnitFacing(this.spell.caster.unit)
        call BJDebugMsg("Running ep_Cast for "+I2S(RUNNING))
        set epcast = Filter(function ep_cast)
        //call BJDebugMsg("checking if it is already running")
        if total == 0 then
            //call BJDebugMsg("Nope, it wasn't")
            set next[0] = this
            set prev[0] = this
            set next[this] = 0
            set prev[this] = 0
            call TimerStart(EP_Timer,PERIOD,false,function ep)
        else
        //call BJDebugMsg("Still not broken yet")
            set next[this] = 0
            set prev[this] = prev[0]
            set next[prev[0]]=this
            set prev[0] = this
        endif
        set total = total +1
        call this.spell.lock()
        set distance[this] = this[2]
        set Sangle[this] = (face-this[3])*bj_DEGTORAD
        set Eangle[this] = (face+this[3])*bj_DEGTORAD
        set left[this] = R2I(this[0])
        //call BJDebugMsg("left[this]="+I2S(left[this]))
        call ReturnEffect(false)
        return true
    endfunction
endlibrary


Code (jass) Select
library SpellProjectile uses Missile Target Effects
    globals
        boolexpr RegProjectile
        boolexpr Meteor
    endglobals
    struct spellprojectile extends array
        static method onRemove takes Missile this returns boolean
            local spelleffect se = this.data
            debug call BJDebugMsg("Missile for Effect "+I2S(se)+" Calling core")
            call se.spell.core(se)
            return true
        endmethod
       
        // meteor 0 is fall time, 1 is height, 2 makes it circle as it falls
         static method meteor takes nothing returns boolean
            local Spell_Cast spell = RUNNING.spell
            local real x = RUNNING.target.x
            local real y = RUNNING.target.y
            local integer i = 0
            local real sp = 5/RUNNING[0]*0.0325000
            local group g
            local Target u
            local Missile new// = Missile.create(x,y,65,x+1000*Cos(a),y+1000*Sin(a),0)
            debug call BJDebugMsg("Running Meteor RUNNING="+I2S(RUNNING)+"\nRUNNING[0]="+R2S(RUNNING[0])+"Target="+I2S(RUNNING.target))
            if RUNNING.target.isGroup then
                set g = CreateGroup()
                call GroupAddGroup(g,RUNNING.target.group)
                loop
                    set u = Target[FirstOfGroup(g)]
                    exitwhen 0 == u
                    set new = Missile.createLoc(AdvLoc.create(u.x+5, u.y, u.z+RUNNING[1]),AdvLoc.create(u.x,u.z,u.z))
                    set new.target = u.unit
                    //set new.height = RUNNING[1]
                    set new.open = RUNNING[2]
                    set new.speed=sp
                    set new.model=GetSFXPath(RUNNING.model)
                    set new.source=spell.caster.unit
                    set new.collision=80
                    //set new.distance = 200
                    set new.data = spelleffect.createProxy(RUNNING, spell.caster, u)
                    call launch(new)
                endloop
                call DestroyGroup(g)
                set g =null
            else
               
                set u = RUNNING.target
                if RUNNING.target.isUnit then
                    set new = Missile.createLoc(AdvLoc.create(x+5, y, u.z+RUNNING[1]),AdvLoc.create(x,y,u.z))
                    set new.target = RUNNING.target.unit
                else
               
                    set new = Missile.createLoc(AdvLoc.create(x+5, y, 500/*+RUNNING[1]*/),AdvLoc.create(x,y,u.z))
                endif
                //set new.arc= RUNNING[1]
                //set new.height = u.z+RUNNING[1]
                set new.speed=sp
                set new.model=GetSFXPath(RUNNING.model)
                set new.source=spell.caster.unit
                //set new.distance = 200
                set new.open = RUNNING[2]
                set new.collision=80
                set new.data = RUNNING
                call launch(new)
            endif
            call ReturnEffect(false)
            return true
        endmethod
       
        implement MissileStruct
        static method onInit takes nothing returns nothing
            set RegProjectile= Filter(function spellprojectile.reg)
            set Meteor = Filter(function thistype.meteor)
        endmethod
endstruct
endlibrary


Code (jass) Select
scope SpellTest initializer init
    private function test_cast takes nothing returns boolean
        if GetSpellAbilityId() == 'A001' then
            debug call BJDebugMsg("casting Spell")
            call EffectDepository_pillaroffire.cast(GetTriggerUnit(),Target.create(GetSpellTargetX(),GetSpellTargetY(),0))
            debug call BJDebugMsg("Spell cast")
        elseif GetSpellAbilityId() == 'A002' then
            debug call BJDebugMsg("castingMeteor")
            call EffectDepository_MeteorShower.cast(GetTriggerUnit(),Target.create(GetSpellTargetX(),GetSpellTargetY(),0))
        endif
        return false
    endfunction
   
    function init takes nothing returns nothing
        //debug call BJDebugMsg("Creating Spell PillarofFire")
        //set EffectDepository_pillaroffire = CreateSpell(CreateSpellEffect(RegProjectile, 900, 150, 35, 0,GetSFX(SFX_FIRE_EFFECTS, 1, 6)),CreateSpellEffect(Filter(function EffectDepository_pof_cast), 300, 15, 3, 0,GetSFX(SFX_FIRE_EFFECTS, 0, 4)),CreateSpellEffect(Filter(function EffectDepository_pof_cast),300,5,12,0,GetSFX(SFX_FIRE_EFFECTS, 1, 3)),0,false)
        //debug call BJDebugMsg("SpellCreated "+I2S(EffectDepository_pillaroffire))
        set EffectDepository_pillaroffire = CreateSpell(CreateSpellEffect(Filter(function spellprojectile.meteor), 1, 600, 0, 0,GetSFX(SFX_FIRE_EFFECTS, 1, 3)),CreateSpellEffect(Filter(function EffectDepository_pof_cast), 300, 15, 3, 0,GetSFX(SFX_FIRE_EFFECTS, 0, 6))/*
        */,CreateSpellEffect(Filter(function EffectDepository_pof_cast),300,5,12,0,GetSFX(SFX_FIRE_EFFECTS, 0, 3)),0,false)
        set EffectDepository_MeteorShower = CreateSpell(/*
            */CreateSpellEffect(Filter(function ep_cast),12,.15,300,180,0),/*
            */CreateSpellEffect(Filter(function spellprojectile.meteor),1,600,0,0,GetSFX(SFX_FIRE_EFFECTS, 1, 3)),/*
            */CreateSpellEffect(Filter(function EffectDepository_Pure_Damage),125,25,0,0,GetSFX(SFX_MAGIC_EFFECTS, 0, 3)),/*
            */0,false)
      //  set EffectDepository_MeteorShower = CreateSpell(/*
      //      */CreateSpellEffect(Filter(function ep_cast),1,0.13,300,180,0),/*
      //      */CreateSpellEffect(Filter(function spellprojectile.meteor),1,600,0,0,GetSFX(SFX_FIRE_EFFECTS, 1, 3)),/*
      //      */0,0,false)
        call RegisterPlayerUnitEvent(EVENT_PLAYER_UNIT_SPELL_CAST,function test_cast)
    endfunction
endscope


Code (jass) Select
library EffectDepository uses Effects SpellProjectile

    globals
        public Spell pillaroffire
        public Spell MeteorShower
        private spelleffect array pof_next
        private spelleffect array pof_prev
        public boolexpr Damage
        private integer pof_start = 0
        private integer pof_t= 0
        private timer pof = CreateTimer()
        private group temp = CreateGroup()
        private real pof_period = .5
    endglobals
   
   
       private function forDamageGroup takes nothing returns nothing
        call UnitDamageTarget(RUNNING.spell.caster.unit, GetEnumUnit(),RUNNING[1],false,false,ATTACK_TYPE_CHAOS,DAMAGE_TYPE_ENHANCED,null)
        call DestroyEffect( AddSpecialEffectTarget(GetSFXPath(RUNNING.model),GetEnumUnit(),"chest"))
    endfunction
    public function Pure_Damage takes nothing returns boolean
        local Target target = RUNNING.target
        local unit u
        if target.isUnit or target.isDestructable then
            call DestroyEffect( AddSpecialEffectTarget(GetSFXPath(RUNNING.model),RUNNING.target.widget,"chest"))
            call UnitDamageTarget(RUNNING.spell.caster.unit, target.widget,RUNNING[1],false,false,ATTACK_TYPE_CHAOS,DAMAGE_TYPE_ENHANCED,null)
        elseif target.isGroup then
            call ForGroup(target.group,function Pure_Damage)
        else
            call GroupEnumUnitsInRange(temp,target.x,target.y,RUNNING[0],null)
            call DestroyEffect( AddSpecialEffect(GetSFXPath(RUNNING.model),target.x,target.y))
            loop
                set u = FirstOfGroup(temp)
                exitwhen null == u
                call GroupRemoveUnit(temp,u)
               
                call UnitDamageTarget(RUNNING.spell.caster.unit, u,RUNNING[1],false,false,ATTACK_TYPE_CHAOS,DAMAGE_TYPE_ENHANCED,null)
            endloop
        endif
        call ReturnEffect(true)
        return true
    endfunction

       
Ok, first of all welcome to Blizzmod community :)

In order to help you efficiently, I'd need some info:

1. Is this a system developed by you? if not I'd like a link to the source to read the documentation.
2. What's the general idea of the spell? Could you describe the levels and the specific behavior of the spell.
3. The purpose of this system is to "generate spells" ingame?, and the most important, why your game needs to create spells ingame???

Could you please repost the last code, it got truncated :P

Right now I'm at the office so I can't check the attached map.

1: it was developed by me
2: there is only one level, it creates meteor like projectiles in a target area which do damage when they hit, it works on the first cast but then it bugs, on the second, and the other spell that I made using the Generator also bugs up after the Meteor Shower messes up.
3: I am planning on developing a couple more systems similar to it, including a Item generator, and a potion generator theses systems are going to be part of an ORPG template.

I am editing the posted code so that it only shows all code related to the Spell That is messing up.
At first sight, I'm seeing a problem with you way of allocating. I'd suggest to start using Alloc 2. This will help you to make your structs faster and forget to worry about indexing issues.

About point 3, I see a clear purpose in the systems you propose but I don't have it totally clear the purpose of the ability system. I see that you gather the effects, and you have a projectile system. The idea is to get a system which can set the effect according to some kind of parameters??

Help me clarifying this and I'll start suggesting things :D
After reviewing the system... I think you could merge the effect system with the projectile system. In fact it will be convenient to set a hierarchy about the components of the system.

I understand the purpose of this system is to have TOTAL control about the damage to units and how is done. So it will be mandatory to have clear what scenarios you'll have. Example:

[btable=Scenarios]1[c]Melee attack Physical[r]2[c]Ranged attack physical[r]3[c]Melee attack magical[r]4[c]ranged attack magical[/btable]

Or better...

Some example scenarios:

  • Melee

    • Physical

      • DAMAGE_ROCK
      • DAMAGE_SLICE
    • Magical

      • DAMAGE_NEAR_EXPLOSION
      • DAMAGE_NEAR_FIRE
  • Ranged

    • Physical

      • DAMAGE_ARROW
      • DAMAGE_SPLASH_BULLETS
    • Magical

      • DAMAGE_FIRE_BALL
      • DAMAGE_ICE_SHARD
  • Instant

    • Physical
    • Magical
etc....

This hierarchy should be used in the new struct. Example:

Code (jass) Select
library DamageEffectSys

struct DamageStyle extends array
static private integer count = 1 // this struct won't require to destroy elements in game time
//Set your properties here...

static method create takes <your arguments> returns thistype
local thistype this = thistype(thistype.count) // sets the allocation process
set thistype.count = thistype.count + 1
// more settings...
return this
endmethod
endstruct

struct DamageType extends array
static private integer count = 1 // this struct won't require to destroy elements in game time
//Set your properties here...

static method create takes <your arguments> returns thistype
local thistype this = thistype(thistype.count) // sets the allocation process
set thistype.count = thistype.count + 1
// more settings...
return this
endmethod
endstruct

struct DamageForm extends array
static private integer count = 1 // this struct won't require to destroy elements in game time
//Set your properties here...

static method create takes <your arguments> returns thistype
local thistype this = thistype(thistype.count) // sets the allocation process
set thistype.count = thistype.count + 1
// more settings...
return this
endmethod
endstruct

struct Damage extends array
static private integer count = 1 // this struct won't require to destroy elements in game time
DamageStyle DS // Melee, ranged or instant
DamageType DT //Physical or magical
DamageForm DF //DAMAGE_SLICE, DAMAGE_FIREBALL, etc

static method create takes nothing returns thistype
local thistype this = thistype(thistype.count) // sets the allocation process
set thistype.count = thistype.count + 1
return this
endmethod
endstruct

endlibrary


As you can see, we can define in an organized way all the information and setting you need according to your type of damage. For example in Damage Style struct you can define a set of methods which will manage the projectile settings and values.

You can make it in the form of several libraries with one struct per library and manage dependencies.



Thank you for all of your help, I am sorry was unable to reply earlier.
I took your advice, and improved my allocation, also your advice helped me find the root of the problem(I was unlocking twice) and now the system is full functional.

I am sorry I was unable to explain the purpose of the system earlier. its whole purpose is to have an easy way to create custom spells specifically for randomly generated items.
Without something like this magical items would be really boring, all they could do is add fire/ice/whatever damage, or would be limited to a very small static list of spells,'and while it is true that the system would have a finite number of spells(excluding variations in damage duration/whatever) but its finite amount of spells would be dramatically greater(supposing I only make 10 effects, I would still have 10000 possible spells, though in reality that number is a little smaller because some effects would be worthless as a last effect.  )

Also I am intending on making a random spell generator later on.

I do like your idea for a damage hierchy, it would be really useful for resistances/armor reductions.