1. Music Contest #10 - Results are finally published! Drop by to check some retro songs and congratulate the winners!
    Dismiss Notice
  2. Join Terraining Contest #19 and witness the aftermath!
    Dismiss Notice
  3. The 3rd Melee Mapping Contest is ON! Join in on a ride of a 4v4 melee experience!
    Dismiss Notice
  4. The 30th edition of the Modeling Contest is finally up! The Portable Buildings need your attention, so come along and have a blast!
    Dismiss Notice

[vJASS] What does this even mean?

Discussion in 'Triggers & Scripts' started by Dat-C3, Sep 18, 2014.

  1. Dat-C3

    Dat-C3

    Joined:
    Mar 15, 2012
    Messages:
    2,435
    Resources:
    10
    Models:
    1
    Maps:
    5
    Spells:
    3
    Tutorials:
    1
    Resources:
    10
    Line 878: C is not of a type that allows . syntax

    If I fix or remove it then everything else starts blowing up too, I tried to set new variables as well.

    Code (vJASS):

    function InitTrig_vectorsystem takes nothing returns nothing
    endfunction


    //===========================================================================
    library vectorsystem initializer init



    //  **********************
    //  **  VECTOR SYSTEM   **
    //  **********************

    //  Original concept by iNfraNe
    //  Then Made by Anitarf
    // ported to structs by vexorian (actually just copied the math)
       globals
           private location stupid
       endglobals


    struct vector
       real x=0.
       real y=0.
       real z=0.
     


       private boolean safety=true

       private method onDestroy takes nothing returns nothing
           set this.safety=false
       endmethod

       method created takes nothing returns boolean
           return this.safety
       endmethod

       method length takes nothing returns real
           return SquareRoot(this.x*this.x + this.y*this.y+this.z*this.z)
       endmethod

       method add takes vector B returns nothing
          set this.x=this.x+B.x
          set this.y=this.y+B.y
          set this.z=this.z+B.z
       endmethod


       method add_factored takes vector B, real fc returns nothing
          set this.x=this.x+fc*B.x
          set this.y=this.y+fc*B.y
          set this.z=this.z+fc*B.z
       endmethod

       method substract takes vector B returns nothing
          set this.x=this.x-B.x
          set this.y=this.y-B.y
          set this.z=this.z-B.z
       endmethod

       static method sum takes vector A, vector B returns vector
        local vector C=vector.create()

          set C.x=A.x+B.x
          set C.y=A.y+B.y
          set C.z=A.z+B.z
        return C
       endmethod

       static method difference takes vector A, vector B returns vector
        local vector C=vector.create()

          set C.x=A.x-B.x
          set C.y=A.y-B.y
          set C.z=A.z-B.z
        return C
       endmethod

       method scale takes real factor returns nothing
          set this.x=this.x*factor
          set this.y=this.y*factor
          set this.z=this.z*factor
       endmethod

       static method amplify takes vector A, real factor returns vector
        local vector C=vector.create()
          set C.x=A.x*factor
          set C.y=A.y*factor
          set C.z=A.z*factor
        return C
       endmethod

       static method productScalar takes vector A, vector B returns real
           return A.x*B.x+A.y*B.y+A.z*B.z
       endmethod

       method dot takes vector B returns real
           return this.x*B.x+this.y*B.y+this.z*B.z
       endmethod

       static method productVector takes vector A, vector B returns vector
        local vector C=vector.create()

           set C.x= A.y*B.z - A.z*B.y
           set C.y= A.z*B.x - A.x*B.z
           set C.z= A.x*B.y - A.y*B.x
        return C
       endmethod

       method project takes vector B returns vector
        local vector C=vector.create()
        local real r=this.dot(B)
        local real l=B.dot(B)
           if (l==0.) then
               return 0
           endif
        return vector.amplify(B,r/l)
       endmethod

       method projectPlane takes vector planeNormal returns vector
        local vector vect= this.project(planeNormal)
        local vector vect2= vector.difference(this,vect)
            call vect.destroy()
        return vect2
       endmethod


       method setLength takes real length returns boolean
        local real l=this.length()
           if (l==0) then
               return false
           endif
           call this.scale(length/l)
        return true
       endmethod

       method clone takes nothing returns vector
        local vector C=vector.create()
           set C.x=this.x
           set C.y=this.y
           set C.z=this.z
        return C
       endmethod

       static method angle takes vector A, vector B returns real
        local real l1=A.length()
        local real l2=B.length()
            if (l1==0) or (l2==0) then
                return 0.
            endif
            return Acos(vector.productScalar(A,B)/(l1*l2) )
       endmethod


       static method distance takes vector A, vector B returns real
           return SquareRoot((A.x-B.x)*(A.x-B.x)+(A.y-B.y)*(A.y-B.y)+(A.z-B.z)*(A.z-B.z))
       endmethod

       static method distanceSquare takes vector A, vector B returns real
           return (A.x-B.x)*(A.x-B.x)+(A.y-B.y)*(A.y-B.y)+(A.z-B.z)*(A.z-B.z)
       endmethod


       method rotate takes vector axis, real angle returns vector
        local vector locX
        local vector locY
        local vector locZ= this.project(axis)
        local vector result

        if locZ == 0 then
            return 0
        endif
        set locX = vector.difference(this,locZ)
        set locY = vector.productVector(this, locX)
        call locY.setLength(locX.length())
        call locX.scale(Cos(angle))
        call locY.scale(Sin(angle))
        set result= vector.sum(locX,locY)
        call result.add(locZ)

        call locX.destroy()
        call locY.destroy()
        call locZ.destroy()

        return result
       endmethod


       static method createFrom takes real x, real y, real z returns vector
        local vector C=vector.create()
           set C.x=x
           set C.y=y
           set C.z=z
        return C
       endmethod

       static method getTerrainPosition takes real x, real y returns vector
        local integer C=vector.create()
           call MoveLocation(stupid,x,y)
           set C.x=x
           set C.y=y
           set C.z=GetLocationZ(stupid)
        return C
       endmethod

       static method getTerrainNormal takes real x, real y, real sampleRadius returns vector

        local real z1
        local real z2
        local real z3
        local real z4
        local vector xvect
        local vector yvect
        local vector normvect
        call MoveLocation(stupid, x-sampleRadius, y)
        set z1=GetLocationZ(stupid)
        call MoveLocation(stupid, x+sampleRadius, y)
        set z2=GetLocationZ(stupid)
        call MoveLocation(stupid, x, y-sampleRadius)
        set z3=GetLocationZ(stupid)
        call MoveLocation(stupid, x, y+sampleRadius)
        set z4=GetLocationZ(stupid)

        set xvect = vector.createFrom(2*sampleRadius, 0., z2-z1)
        set yvect = vector.createFrom(0., 2*sampleRadius, z4-z3)
        set normvect = vector.productVector(xvect, yvect)
        call xvect.destroy()
        call yvect.destroy()
        return normvect
       endmethod

       method inCylinder takes vector cylinderOriginV, vector cylinderHeightV, real cylinderRadius returns boolean
        local vector v1
        local vector v2
        local vector v3
        local boolean b = false
        local real l = cylinderHeightV.length()
        if (l > 0.) then
            set v1=vector.difference(this, cylinderOriginV)
            set v2=vector.difference(v1, cylinderHeightV)
            set v3=v1.projectPlane( cylinderHeightV)
            if vector.productScalar(v1, cylinderHeightV)>=0 and vector.productScalar(v2, cylinderHeightV)<=0 and vector.productScalar(v3, v3)<=cylinderRadius*cylinderRadius then
                set b = true
            endif
            call v1.destroy()
            call v2.destroy()
            call v3.destroy()
        endif
        return b
       endmethod

       method move takes real x, real y, real z returns nothing
          set this.x=x
          set this.y=y
          set this.z=z
       endmethod

        method inCone takes vector coneOriginV, vector coneHeightV, vector coneRadius returns boolean
        local vector v1
        local vector v2
        local vector v3
        local vector v4
        local boolean b = false
        local real r
        local real l = coneHeightV.length()
        if (l>0.0) then
            set v1=vector.difference(this, coneOriginV)
            set v2=vector.difference(v1, coneHeightV)
            set v3=v1.project( coneHeightV)
            set v4=vector.difference(v1,v3)
            set r = 1.0-( v3.length()/l )
            if vector.productScalar(v1, coneHeightV)>=0 and v4.length()<=(coneRadius*r) then
                set b = true
            endif
            call v1.destroy()
            call v2.destroy()
            call v3.destroy()
            call v4.destroy()
        endif
        return b
        endmethod

        method inSphere takes vector sphereOriginV, real sphereRadius returns boolean
        local vector v
        local boolean b

            set v=vector.difference(this, sphereOriginV)
            set b= (vector.productScalar(v,v)<= sphereRadius*sphereRadius)
            call v.destroy()
        return b
        endmethod

       
       


    endstruct

    private function init takes nothing returns nothing
       set stupid=Location(0.,0.)
    endfunction


    endlibrary




     


    I am actually attempting to fix a certain map. =)

    Hope I can get info/help on what's going wrong.
     
  2. IcemanBo

    IcemanBo

    Joined:
    Sep 6, 2013
    Messages:
    5,797
    Resources:
    22
    Maps:
    3
    Spells:
    11
    Template:
    1
    Tutorials:
    4
    JASS:
    3
    Resources:
    22
    In same method
    local integer C=vector.create()

    -->
    local thistype C=vector.create()


    thistype
    is like a new variable type. The type of the struct in which it gets used.
     
  3. Dat-C3

    Dat-C3

    Joined:
    Mar 15, 2012
    Messages:
    2,435
    Resources:
    10
    Models:
    1
    Maps:
    5
    Spells:
    3
    Tutorials:
    1
    Resources:
    10
    [jass=Line]
    set C.x=x
    [/jass]

    So it's been duplicated IcemanBo and that is why it is failing?
     
  4. deathismyfriend

    deathismyfriend

    Joined:
    Oct 24, 2012
    Messages:
    6,532
    Resources:
    14
    Spells:
    12
    Tutorials:
    2
    Resources:
    14
    No the reason it is failing is in the above answer.
    This
    Code (vJASS):

       static method getTerrainPosition takes real x, real y returns vector
        local integer C=vector.create()
           call MoveLocation(stupid,x,y)
           set C.x=x
           set C.y=y
           set C.z=GetLocationZ(stupid)
        return C
       endmethod

    Needs to get changed to this.

    Code (vJASS):

       static method getTerrainPosition takes real x, real y returns vector
        local vector C=vector.create()
           call MoveLocation(stupid,x,y)
           set C.x=x
           set C.y=y
           set C.z=GetLocationZ(stupid)
        return C
       endmethod

    or this.
    Code (vJASS):

       static method getTerrainPosition takes real x, real y returns vector
        local thistype C=thistype.create()
           call MoveLocation(stupid,x,y)
           set C.x=x
           set C.y=y
           set C.z=GetLocationZ(stupid)
        return C
       endmethod
     
  5. IcemanBo

    IcemanBo

    Joined:
    Sep 6, 2013
    Messages:
    5,797
    Resources:
    22
    Maps:
    3
    Spells:
    11
    Template:
    1
    Tutorials:
    4
    JASS:
    3
    Resources:
    22
    It's because C.x = x needs C. to be an instance of the struct.

    But as its declared as integer "integer C = ..." it'S not working.
    You need "thistype C = ... "
     
  6. Dat-C3

    Dat-C3

    Joined:
    Mar 15, 2012
    Messages:
    2,435
    Resources:
    10
    Models:
    1
    Maps:
    5
    Spells:
    3
    Tutorials:
    1
    Resources:
    10
    Okay now that was fixed, thanks guys however more problems just popped up. . . =(

    Can't believe I yet again missed such a big mistake. Dat syntax...

    By any chance would you guys help me with the other errors?

    The problems are undeclared functions which I am sure are from a system that can't work anymore, some type of storage system for arrays. I don't quite know though.

    Messing up lines -
    Code (vJASS):

                call DestroyEffect(GetArrayEffect(g , i * 2 - 1))
            set m = GetArrayUnit(g , i * 2)
                call DestroyEffect(GetArrayEffect(g , i * 2 - 1))
        if ( GetArrayUnit(g , i * 2) == u ) then
                        call SetArrayObject(g , n * 2 - 1 , AddSpellEffectTargetById(s , EFFECT_TYPE_AREA_EFFECT , u , GetAbilityEffectById(s , EFFECT_TYPE_AREA_EFFECT , 1)))
                call SetArrayObject(g , n * 2 , u)
     


    A problem

    [jass=Undeclared functions of some sort]
    //********************************************************************************************************
    //* A JESP Spell by Vexorian
    //* Codename: RagingCharge
    //* ¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯
    //* Requirements:
    //* ¯¯¯¯¯¯¯¯¯¯¯¯¯
    //* - The RagingCharge ability
    //* - The Caster System ( http://wc3campaigns.net/vexorian ) >=14.0
    //* - JASSHelper or other global merger preprocessor ( http://wc3campaigns.net/vexorian/jasshelper/ )
    //* - This Trigger (MAKE SURE TO change the rawcodes in the trigger to the correct ones of your map)
    //*
    //* Object Editor fields
    //* ¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯
    //* - Duration : Duration of the ability determines how much the charge lasts.
    //* - Art - Caster : After charge Animation
    //* - Art - Special (1) : Hero charge effect
    //* - Art - Special (2) : Hero charge effect attachment point
    //* - Art - Area Effect (1) : Knockback effect
    //* - Art - Area Effect (2) : Knockback effect attachment point
    //* - Art - Target (1) : Impact effect
    //* - Art - Target (2) : Impact effect attachment point
    //*
    //********************************************************************************************************

    //========================================================================================================
    // RagingCharge Spell Configuration:
    //
    //
    ////
    // SpellId
    // ¯¯¯¯¯¯¯
    // Make sure to replace A007 with the correct Rawcode in your map.
    //
    constant function RagingCharge_SpellId takes nothing returns integer
    return 'A001'
    endfunction

    ////
    // Animation Stuff:
    // ¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯
    // _AnimationIndex : The sequence index of the animation you want to be played during the charge,
    // (Depends on the model used, see next trigger for more info)
    // _AnimationDuration: Duration of the animation (Period of time before playing it again)
    // _AnimationSpeed : Speed factor for the animation
    //
    constant function RagingCharge_AnimationIndex takes integer level returns integer
    return 5
    endfunction
    constant function RagingCharge_AnimationDuration takes integer level returns real
    return 0.466
    endfunction
    constant function RagingCharge_AnimationSpeed takes real level returns real
    return 1.+level*0
    endfunction
    constant function RagingCharge_Speed takes real level returns real
    return 800.0+level*0
    endfunction

    ////
    // Balance Stuff:
    // ¯¯¯¯¯¯¯¯¯¯¯¯¯
    // _Damage : Damage done to units that are hit by RagingCharge
    // _DamagePerSecond : Damage per second units get during knockback
    // _ImpactRange : How close must a unit be to be hit by RagingCharge?
    // _FrontAngle : Angle in Deg, less than 180.0 that determines the front of the hero
    //
    constant function RagingCharge_Damage takes real level returns real
    return 0.0
    // return -5 + (85-5*level)*level
    endfunction
    constant function RagingCharge_DamagePerSecond takes real level returns real
    return 0.
    endfunction
    constant function RagingCharge_ImpactRange takes real level returns real
    return 128.0 //256.0
    endfunction
    constant function RagingCharge_FrontAngle takes real level returns real
    return 179.0
    endfunction
    constant function RagingCharge_MaxKnockbackTargets takes integer level returns integer
    return 5+level
    // Keep this number small, it is also used for array allocation, so using
    //10000 might mean infinite but it would cause a lot of problems, it is not like
    // you really need more than 50 for this value.
    endfunction


    ////
    // Targetting options:
    // ¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯
    function RagingCharge_DamageOptions takes integer level returns integer
    //** Damage options for impact damage:
    return DamageTypes(ATTACK_TYPE_NORMAL,DAMAGE_TYPE_FIRE) + DamageOnlyEnemies() + DamageException(UNIT_TYPE_FLYING,0)
    //
    // Will do fire spell damage, won't damage allies, and will only affect ground units.
    // other damage options can be used, check caster system readme for more information.
    //
    // (This is for the Impact damage)
    //
    endfunction
    function RagingCharge_KnockbackOptions takes integer level returns integer
    //** Damage options for knockback:
    return DamageOnlyEnemies() + DamageException(UNIT_TYPE_FLYING,0)
    //
    // Will knockback enemy ground units
    // other damage options can be used, check caster system readme for more information.
    //
    // (This is for the Knockback, meaning that only in case these damage options determine an unit is
    // immune, it won't be affected by the knockback, this has nothing to do with damage
    //
    endfunction
    function RagingCharge_KillTrees takes integer level returns boolean
    //** true == kill trees ; false == don't kill trees
    return true
    endfunction

    ////
    // Other:
    // ¯¯¯¯¯
    constant function RagingCharge_Timer takes nothing returns real
    //** Timer Period:
    return 0.04
    //
    // This is the timer period, a low value (0.01) will look better but will be worse lag-wise, a high
    // value (1.0) would be faster lag-wise but will surelly look bad. I think 0.04 is the perfect value.
    endfunction




    //========================================================================================================
    // RagingCharge code:
    //
    // Why RagingCharge_ItemCheck instead of IsTerrainPathable?
    // IsTerrainPathable doesn't consider pathing blockers, destructables nor buildings
    //

    struct RagingCharge_data
    unit u=null //casting hero
    integer g=0 //arrayid of the knockback array
    integer l=0 // level of the spell
    real f=0. // direction of the charge
    trigger ran=null //range eent trigger
    trigger endt=null //stop casts event
    triggeraction ac=null //action of range event
    effect fx=null //charge fx
    integer times=0 // number of cycles done
    real next=0 //next time to play animation

    endstruct

    function RagingCharge_GetI takes nothing returns nothing
    set bj_rescueChangeColorUnit = bj_rescueChangeColorUnit or (GetEnumItem()!=bj_itemRandomCurrentPick)
    endfunction
    function RagingCharge_ItemCheck takes item p, real x, real y returns boolean
    local integer i=50
    local rect r
    call SetItemPosition(p,x,y)
    if ((Pow(GetItemX(p)-x,2)+Pow(GetItemY(p)-y,2))<=100) then
    return true
    endif
    set r=Rect(x-i,y-i,x+i,y+i)
    set bj_itemRandomCurrentPick=p
    set bj_rescueChangeColorUnit=false
    call EnumItemsInRect(r,null,function RagingCharge_GetI)
    call RemoveRect(r)

    set r=null
    return bj_rescueChangeColorUnit
    endfunction
    function RagingCharge_CheckPathability takes real x, real y returns boolean
    return true
    // local item it=CreateItem('ciri',x,y)
    // local boolean b =RagingCharge_ItemCheck(it,x,y)
    // call SetItemVisible(it,false)
    // call RemoveItem(it)

    // set it=null
    // return b
    endfunction

    function RagingCharge_OrbMov takes unit m,integer l, timer t, RagingCharge_data k returns boolean
    local real x=GetUnitX(m)
    local real y=GetUnitY(m)
    local real kf
    local integer kl
    local unit ku
    local real f=kf
    local real d=RagingCharge_Speed(l)*RagingCharge_Timer()
    local real nx=x+d*Cos(f*bj_DEGTORAD)
    local real ny=y+d*Sin(f*bj_DEGTORAD)
    local boolean b
    local integer error
    local integer n = k.times+1
    local real nex

    set k.times=n



    call SetUnitFacing(m,f)
    set nex=k.next

    if (n * RagingCharge_Timer() >= nex) then
    set k.next=nex+RagingCharge_AnimationDuration(l)
    call SetUnitAnimationByIndex(m,RagingCharge_AnimationIndex(l))
    endif


    if ((RagingCharge_CheckPathability(nx,ny)) and (CS_MoveUnit(m,nx,ny))) then
    return true
    endif

    call SetUnitPosition(m,x,y)
    call TriggerEvaluate( k.endt)
    return false
    endfunction

    function RagingCharge_Mov takes nothing returns nothing
    local timer t=GetExpiredTimer()
    local RagingCharge_data k= GetCSData(t)
    local unit m
    local unit o
    local real f
    local real sf=k.f
    local real h
    local real dir
    local real inc
    local real x
    local real y
    local real nx
    local real ny
    local real px
    local real py
    local real mina
    local real maxa
    local integer kg
    local integer tms
    local integer l= k.l
    local trigger tg=k.endt

    local integer g=kg
    local integer i
    local integer n=GetArrayInt(g,0)

    set o=k.u
    if (GetTriggerEvalCount(tg)>0) then

    set i=1
    set x=GetUnitX(o)
    set y=GetUnitY(o)
    loop
    exitwhen (i>n)
    // set m=GetArrayUnit(g,i*2)
    // set nx=GetUnitX(m)
    // set ny=GetUnitY(m)
    // set f= Angles_GetMidAngle(Angles_GetMidAngle(Atan2(ny-y,nx-x)*bj_RADTODEG,sf),sf)*bj_DEGTORAD
    //
    // call buffs_addKnockback(m,RagingCharge_Speed(l),f)
    call DestroyEffect(GetArrayEffect(g,i*2-1))
    set i=i+1
    endloop
    call DestroyArray(g)
    call DestroyTrigger(tg)
    set tg=k.ran
    call TriggerRemoveAction(tg, k.ac )
    call DestroyTrigger(tg)
    call ReleaseTimer(t)
    set m=k.u
    call DestroyEffect(k.fx)
    if (GetWidgetLife(m)>0.405) then
    call QueueUnitAnimation(m,GetAbilityEffectById(RagingCharge_SpellId(),EFFECT_TYPE_CASTER,0))
    endif
    call SetUnitTimeScale(m,1)
    call k.destroy()
    set o=null
    set t=null
    set m=null
    return
    endif
    set tg=null



    set x=GetUnitX(o)
    set y=GetUnitY(o)

    set inc=RagingCharge_Speed(l)*RagingCharge_Timer()

    if (RagingCharge_KillTrees(l)) then
    call DamageTreesInCircle(x,y,RagingCharge_ImpactRange(l))
    endif
    set h=RagingCharge_DamagePerSecond(l)*RagingCharge_Timer()
    set i=1
    loop
    exitwhen (i>n)
    set m=GetArrayUnit(g,i*2)
    set nx=GetUnitX(m)
    set ny=GetUnitY(m)

    if (IsUnitInRange(m,o,RagingCharge_ImpactRange(l))) and (GetWidgetLife(m)>0.405) then
    call DamageUnitByOptions(o,m,h,RagingCharge_DamageOptions(l))
    //set f= Angles_GetMidAngle(Angles_GetMidAngle(Atan2(ny-y,nx-x)*bj_RADTODEG,sf),sf)*bj_DEGTORAD
    //set f= Atan2(ny-y,nx-x)
    set f= Angles_GetMidAngle((Atan2(ny-y,nx-x)*bj_RADTODEG),sf)*bj_DEGTORAD
    set px=nx+inc*Cos(f)
    set py=ny+inc*Sin(f)
    call buffs_addKnockback(m,RagingCharge_Speed(l),f)
    // call SetUnitPosition(m,px,py)
    // call CS_MoveUnit(m,px,py)
    call SetUnitFacing(m,GetRandomReal(0,360))
    //if (Pow(GetUnitX(m)-px,2)+Pow(GetUnitY(m)-py,2))>400 then
    // call SetUnitPosition(m,nx,ny)
    //endif
    else
    // Destroy the effect, remove from array.
    call DestroyEffect( GetArrayEffect(g,i*2-1) )
    call SetArrayInt(g,i*2,GetArrayInt(g,n*2))
    call SetArrayInt(g,i*2-1,GetArrayInt(g,n*2-1))
    set n=n-1
    call SetArrayInt(g,0,n)
    endif
    set i=i+1
    endloop

    call RagingCharge_OrbMov(o,l,t,k)


    set t=null
    set m=null
    endfunction

    function RagingCharge_InGArray takes unit u, integer g, integer n returns boolean
    local integer i=0
    loop
    exitwhen i>n
    if (GetArrayUnit(g,i*2)==u) then
    return true
    endif
    set i=i+1
    endloop
    return false
    endfunction

    function RagingCharge_OrbImpact takes nothing returns nothing
    local integer k=GetCSData( GetTriggeringTrigger() )
    local unit u
    local unit m
    local unit ku
    local integer kg
    local integer kl
    local integer g=kg
    local integer l=kl
    local real kf
    local real f
    local real dt
    local integer s=RagingCharge_SpellId()
    local integer i=0
    local integer n=GetArrayInt(g,0)



    if (n>=RagingCharge_MaxKnockbackTargets(l)) then
    return //why even bother?
    endif

    set u=GetTriggerUnit()
    set m=ku


    if not( RagingCharge_InGArray(u,g,n)) and (GetWidgetLife(u)>0) and not(IsUnitType(u,UNIT_TYPE_DEAD)) and not(IsUnitType(u,UNIT_TYPE_STRUCTURE)) then

    set f = kf
    set dt=RagingCharge_FrontAngle(l)/2
    if (Angles_IsAngleBetweenAngles( Atan2BJ(GetUnitY(u)-GetUnitY(m),GetUnitX(u)-GetUnitX(m)),f-dt,f+dt)) then
    if (GetDamageFactorByOptions(m,u,RagingCharge_KnockbackOptions(l))!=0) then
    call DestroyEffect( AddSpellEffectTargetById(s,EFFECT_TYPE_TARGET,u,GetAbilityEffectById(s,EFFECT_TYPE_TARGET,1)) )
    set n=n+1
    call SetArrayObject(g,n*2-1, AddSpellEffectTargetById(s,EFFECT_TYPE_AREA_EFFECT,u,GetAbilityEffectById(s,EFFECT_TYPE_AREA_EFFECT,1)) )
    call SetArrayObject(g,n*2, u )
    call SetArrayInt(g,0,n)
    endif
    endif

    call DamageUnitByOptions(m,u,RagingCharge_Damage(l),RagingCharge_DamageOptions(l))
    endif

    set u=null
    set m=null
    endfunction

    function RagingCharge_Actions takes nothing returns nothing
    local unit u=GetTriggerUnit()
    local integer s=GetSpellAbilityId()
    local integer l=GetUnitAbilityLevel(u,s)
    local location loc
    local real x=GetUnitX(u)
    local real y=GetUnitY(u)
    local real f
    local timer t=NewTimer()
    local integer g=NewArray(1+RagingCharge_MaxKnockbackTargets(l)*2,false)
    local trigger tg=CreateTrigger()
    local RagingCharge_data data= RagingCharge_data.create()

    call SetArrayInt(g,0,0) //number of units in the array.

    set data.ac=TriggerAddAction(tg,function RagingCharge_OrbImpact)

    call SetCSData(t,data)
    call SetCSData(tg,data)



    if (GetSpellTargetUnit()!=null) then
    set loc=GetUnitLoc(GetSpellTargetUnit())
    else
    set loc=GetSpellTargetLoc()
    endif
    set f=Atan2(GetLocationY(loc)-y,GetLocationX(loc)-x) * bj_RADTODEG
    call RemoveLocation(loc)

    set data.l=l
    set data.f=f


    set data.u=u
    set data.g=g
    set data.ran=tg


    set data.fx=AddSpellEffectTargetById(s,EFFECT_TYPE_SPECIAL,u,GetAbilityEffectById(s,EFFECT_TYPE_SPECIAL,1))



    call TriggerRegisterUnitInRange(tg,u,RagingCharge_ImpactRange(l),null)


    set tg=CreateTrigger()
    call TriggerRegisterUnitEvent(tg,u,EVENT_UNIT_SPELL_ENDCAST)
    set data.endt=tg



    call TimerStart(t,RagingCharge_Timer(),true,function RagingCharge_Mov)
    call SetUnitTimeScale(u,RagingCharge_AnimationSpeed(l))
    call SetUnitAnimationByIndex(u,RagingCharge_AnimationIndex(l))

    set tg=null
    set u=null
    set loc=null
    set t=null

    endfunction
    function InitTrig_RagingCharge takes nothing returns nothing
    local integer s=RagingCharge_SpellId()
    call OnAbilityEffect(s,"RagingCharge_Actions" )
    call Preload(GetAbilityEffectById(s,EFFECT_TYPE_SPECIAL,0))
    call Preload(GetAbilityEffectById(s,EFFECT_TYPE_TARGET,0))
    call Preload(GetAbilityEffectById(s,EFFECT_TYPE_AREA_EFFECT,0))
    endfunction
    [/jass]
     
  7. IcemanBo

    IcemanBo

    Joined:
    Sep 6, 2013
    Messages:
    5,797
    Resources:
    22
    Maps:
    3
    Spells:
    11
    Template:
    1
    Tutorials:
    4
    JASS:
    3
    Resources:
    22
    It compiles for me. (after integer --> thistype)
     
  8. Dat-C3

    Dat-C3

    Joined:
    Mar 15, 2012
    Messages:
    2,435
    Resources:
    10
    Models:
    1
    Maps:
    5
    Spells:
    3
    Tutorials:
    1
    Resources:
    10
    Well what I posted was a new trigger, the trigger you guys helped fix is perfect I think. I am mostly a GUI'er but I have skill/talent/knowledge/ability in almost every field in wc3. =)

    Though that doesn't change the fact I am still really terrible at VJass.
     
  9. IcemanBo

    IcemanBo

    Joined:
    Sep 6, 2013
    Messages:
    5,797
    Resources:
    22
    Maps:
    3
    Spells:
    11
    Template:
    1
    Tutorials:
    4
    JASS:
    3
    Resources:
    22
    I don't know what to do with the few JASS lines you posted under "Messing up lines -". What's the problem?

    In the library you posted under "A problem"... Read the requirements and ensure you can provide the needs.
     
  10. Dat-C3

    Dat-C3

    Joined:
    Mar 15, 2012
    Messages:
    2,435
    Resources:
    10
    Models:
    1
    Maps:
    5
    Spells:
    3
    Tutorials:
    1
    Resources:
    10
    I don't see any requirements :ogre_icwydt:
     
  11. IcemanBo

    IcemanBo

    Joined:
    Sep 6, 2013
    Messages:
    5,797
    Resources:
    22
    Maps:
    3
    Spells:
    11
    Template:
    1
    Tutorials:
    4
    JASS:
    3
    Resources:
    22
    Have you read the comments on top of the code? (green highlighted text)
     
  12. Dat-C3

    Dat-C3

    Joined:
    Mar 15, 2012
    Messages:
    2,435
    Resources:
    10
    Models:
    1
    Maps:
    5
    Spells:
    3
    Tutorials:
    1
    Resources:
    10
    Ah I see, that system is broken though due to the patch.... How would I adjust it to the latest? The caster system that is.
     
  13. IcemanBo

    IcemanBo

    Joined:
    Sep 6, 2013
    Messages:
    5,797
    Resources:
    22
    Maps:
    3
    Spells:
    11
    Template:
    1
    Tutorials:
    4
    JASS:
    3
    Resources:
    22
    I don't know.
     
  14. deathismyfriend

    deathismyfriend

    Joined:
    Oct 24, 2012
    Messages:
    6,532
    Resources:
    14
    Spells:
    12
    Tutorials:
    2
    Resources:
    14
    Can you post the caster system.
     
  15. Dat-C3

    Dat-C3

    Joined:
    Mar 15, 2012
    Messages:
    2,435
    Resources:
    10
    Models:
    1
    Maps:
    5
    Spells:
    3
    Tutorials:
    1
    Resources:
    10
  16. deathismyfriend

    deathismyfriend

    Joined:
    Oct 24, 2012
    Messages:
    6,532
    Resources:
    14
    Spells:
    12
    Tutorials:
    2
    Resources:
    14
    I mean post the trigger on this thread so we don't have to keep loading another page.
     
  17. Dat-C3

    Dat-C3

    Joined:
    Mar 15, 2012
    Messages:
    2,435
    Resources:
    10
    Models:
    1
    Maps:
    5
    Spells:
    3
    Tutorials:
    1
    Resources:
    10
    Can't, Ralle made the char limit too small... Sorry.
     
  18. deathismyfriend

    deathismyfriend

    Joined:
    Oct 24, 2012
    Messages:
    6,532
    Resources:
    14
    Spells:
    12
    Tutorials:
    2
    Resources:
    14
    Post it in sections.
     
  19. Dat-C3

    Dat-C3

    Joined:
    Mar 15, 2012
    Messages:
    2,435
    Resources:
    10
    Models:
    1
    Maps:
    5
    Spells:
    3
    Tutorials:
    1
    Resources:
    10

    Then it'd get confusing since its just one trigger, what are you banned from Pastebin or something? It's much easier clicking it and viewing it there

    However fine.

    part1

    Code (vJASS):

    library CasterSystem initializer InitCasterSystem requires CSSafeCache, GroupUtils, TimerUtils

         //***************************************************************************
         //*                                                                         *
         //* Caster System 16.0                                                      *
         //* ¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯               [url]http://wc3campaigns.net/vexorian[/url]       *
         //* Requires:                                                               *
         //* ¯¯¯¯¯¯¯¯¯                                                               *
         //* - Jasshelper / Newgen pack                                              *
         //*                                                                         *
         //* - The CSSafeCache Module                                                *
         //* - The CSData Module                                                     *
         //* - The CSSafety Module                                                   *
         //*                                                                         *
         //* - The caster unit from this map Can be found in this map's unit editor  *
         //*   ( Custom Units\Neutral Passive\Units\Caster )                         *
         //*                                                                         *
         //*   ( Update the cs_CasterUnitId constant next:)                          *
         //*                                                                         *
         //* - the war3mapImported\dummy.mdx imported file (find it in this map)     *
         //*                                                                         *
         //***************************************************************************

         //====================================================================================================================================================================
         //  Caster System Configuration constants :
         //
         globals
             //
             // Caster Unit type rawcode  (changes betwen maps, always use it inside '')
             //
             constant  integer    cs_CasterUnitId         = 'e000'

             // cs_TIMER_CYCLE : Cycle value for the projectile movement in seconds (Each 0.04 the projectiles get moved)
             // 0.01 looks smooth but is lag friendly
             // 0.025 looks smooth and probably matches wc3's frame rate (so in theory, lower values than it are not needed)
             // 0.1 looks horrible but is not laggy
             // 0.04 is decent for the human eye and very efficient.
             // 0.035 is ... well, a little smoother than 0.04
             // 0.05 would be an improvement in efficiency but probably doesn't look too well )
             //
             constant real       cs_TIMER_CYCLE          = 0.035

             //
             // The eat tree ability, don't need to change this rawcode unless you modiffied that ability in your map, in that case copy it, reset the copied one and use its rawcode here.
             //
             constant integer    cs_DamageTreeDetectorId = 'Aeat'

             //
             // Medivh's Crow form ability, don't need to change this rawcode unless you
             // modiffied that ability in your map, in that case copy it, reset the copied one and use its rawcode here:
             //
             constant integer    cs_FlyingHeightHack     = 'Amrf'

             //
             // This must point to an inventory ability with 6 slots that does not add bonuses, you don't need one unless
             // the caster system item hiding functions are used in your map
             //
             constant integer    cs_DummyInventory_Id    = 'null'

             //
             //Maximum collision size in your map - Affects the caster system's area cast/damage functions
             //
             constant real       cs_MaxUnitCollisionSize = 55.0

             //
             // Next are default attack and damage types for the old caster system functions or when using 0 as damageoptions
             //
             constant attacktype cs_DefaultAttackType    = ATTACK_TYPE_CHAOS
             constant damagetype cs_DefaultDamageType    = DAMAGE_TYPE_UNIVERSAL
             
             //
             // cs_InitialCastersNumber: Number of casters to create on map init:
             //
             constant integer cs_InitialCastersNumber    = 12
             
         endglobals
         //


         //=================================================================================================
         // Caster System script:
         // ¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯

         //=================================================================================================
         // main Caster System global variables:
         //
         globals
             //old ones (udg_ preffix forced for compat ( )
             unit          udg_currentcaster = null
             real array    udg_castervars
             group         udg_casters       = null
             integer       udg_currentabi    = 0
             unit          udg_currenthurter = null
             real          udg_delayhack     = 0.
             location      udg_sourcehack    = null

             //--
             integer array cs_missiles
             integer       cs_missilecount   = 0
             timer         cs_movementtimer        = CreateTimer()
             boolean       cs_movementtimer_active = false

         endglobals

         //=================================================================================================
         function CS_CopyGroup takes group g returns group
             set bj_groupAddGroupDest=NewGroup()
             call ForGroup(g, function GroupAddGroupEnum)
          return bj_groupAddGroupDest
         endfunction

         globals
             constant real cs_RectLimitOffSet = 50.0
             real cs_game_maxx
             real cs_game_maxy
             real cs_game_miny
             real cs_game_minx
         endglobals

         function CS_SafeXY_Init takes nothing returns nothing
             set cs_game_maxx=GetRectMaxX(bj_mapInitialPlayableArea)-cs_RectLimitOffSet
             set cs_game_maxy=GetRectMaxY(bj_mapInitialPlayableArea)-cs_RectLimitOffSet
             set cs_game_miny=GetRectMinY(bj_mapInitialPlayableArea)+cs_RectLimitOffSet
             set cs_game_minx=GetRectMinX(bj_mapInitialPlayableArea)+cs_RectLimitOffSet
         endfunction

         function CS_SafeX takes real x returns real
             if (x<cs_game_minx) then
                 return cs_game_minx
             elseif (x>cs_game_maxx) then
                     return cs_game_maxx
             endif
          return(x)
         endfunction

         function CS_SafeY takes real y returns real
             if (y<cs_game_miny) then
                 return cs_game_minx
             elseif (y>cs_game_maxy) then
                     return cs_game_maxy
             endif
          return(y)
         endfunction

         //Deprecated, since patch 1.21 there is no crash anymore, it is possibly
         // still mildly useful since it does bound checking.
         function CS_MoveUnit takes unit u, real x, real y returns boolean
          local boolean b=true
             if (x<cs_game_minx) then
                 set b=false
             elseif (x>cs_game_maxx) then
                 set b=false
             elseif (y>cs_game_maxy) then
                 set b=false
             elseif (y<cs_game_miny) then
                 set b=false
             endif

             if (b) then
                 call SetUnitX(u, x)
                 call SetUnitY(u, y)
             endif
          return b
         endfunction
         function CS_MoveUnitLoc takes unit u, location loc returns boolean
             return CS_MoveUnit(u,GetLocationX(loc),GetLocationY(loc))
         endfunction

         //==================================================================================================
         function CS_EnumUnitsInAOE_Filter takes nothing returns boolean
             return IsUnitInRangeLoc(GetFilterUnit(), bj_enumDestructableCenter ,bj_enumDestructableRadius)
         endfunction

         //==================================================================================================
         // Use this version when you only have coordinates of the point.
         //
         function CS_EnumUnitsInAOE takes group g, real x, real y, real area, boolexpr bx returns nothing
          local boolexpr cond
          local boolexpr aux=Condition(function CS_EnumUnitsInAOE_Filter)

             if (bx==null) then
                 set cond=aux
             else
                 set cond=And(aux,bx)
             endif
             set bj_enumDestructableCenter=Location(x,y)
             set bj_enumDestructableRadius=area
             call GroupEnumUnitsInRange(g,x,y,cs_MaxUnitCollisionSize+area,cond)
             if (bx!=null) then
                 call DestroyBoolExpr(cond)
             endif
             call RemoveLocation(bj_enumDestructableCenter)
          set aux=null
          set cond=null
         endfunction

         //==================================================================================================
         // Use this version whenever you already have a location for that point, to save some steps
         //
         function CS_EnumUnitsInAOELoc takes group g, location loc, real area, boolexpr bx returns nothing
          local boolexpr cond
          local boolexpr aux=Condition(function CS_EnumUnitsInAOE_Filter)

             if (bx==null) then
                 set cond=aux
             else
                 set cond=And(aux,bx)
             endif
             set bj_enumDestructableCenter=loc
             set bj_enumDestructableRadius=area
             call GroupEnumUnitsInRangeOfLoc(g,loc,cs_MaxUnitCollisionSize+area,cond)
             call DestroyBoolExpr(cond)
             if (bx!=null) then
                 call DestroyBoolExpr(aux)
             endif
          set aux=null
          set cond=null
         endfunction




         //==================================================================================================
         // Angle Calculations
         //
         // I decided to add them to the caster system, because I found myself using them everytime, I am
         // trying to convert the caster system into a Spell Development Framework (hehe)
         //
         //=================================================================================================
         // Returns the angle distance between angles a1 and a2 (For example: a1=30 , a2=60 , return= 30 )
         //
         function Angles_GetAngleDifference takes real a1, real a2 returns real
          local real x
             set a1=ModuloReal(a1,360)
             set a2=ModuloReal(a2,360)
             if a1>a2 then
                 set x=a1
                 set a1=a2
                 set a2=x
             endif
             set x=a2-360
             if a2-a1 > a1-x then
                 set a2=x
             endif
             set x=a1-a2
             if (x<0) then
                 return -x
             endif
          return x
         endfunction

         //=================================================================================================
         // Returns the mid angle between a1 and a2 (For example: a1=30 , a2=60 , return= 45 )
         //
         function Angles_GetMidAngle takes real a1, real a2 returns real
          local real x
             set a1=ModuloReal(a1,360)
             set a2=ModuloReal(a2,360)
             if a1>a2 then
                 set x=a1
                 set a1=a2
                 set a2=x
             endif
             set x=a2-360
             if a2-a1 > a1-x then
                 set a2=x
             endif
          return (a1+a2)/2
         endfunction

         //=================================================================================================
         // Makes angle a1 advance i units towards angle a2 (For Example: a1=30, a2=60, i=10, return=40 )
         //
         function Angles_MoveAngleTowardsAngle takes real a1, real a2, real i returns real
          local real x
             set a1=ModuloReal(a1,360)
             set a2=ModuloReal(a2,360)
             if a1>a2 then
                 set x=a1-360
                 if a1-a2 > a2-x then
                     set a1=x
                 endif
             else
                 set x=a2-360
                 if a2-a1 > a1-x then
                     set a2=x
                 endif
             endif
             if a1>a2 then
                 set x=a1-i
                 if x<=a2 then
                     return a2
                 endif
                return x
             endif
             set x=a1+i
             if x>=a2 then
                 return a2
             endif
          return x
         endfunction

         //=================================================================================================
         // Returns true if the angle 'angle' is between 'angle1' and 'angle2'
         //
         function Angles_IsAngleBetweenAngles takes real angle, real angle1, real angle2 returns boolean
          local real x
             set angle=ModuloReal(angle,360)
             set angle1=ModuloReal(angle1,360)
             set angle2=ModuloReal(angle2,360)
             if (angle1>angle2) then
                 set x=angle1
                 set angle1=angle2
                 set angle2=x
             endif
             if (angle2-angle1)>(angle1 - (angle2-360)) then
                 set angle2=angle2-360
                 if angle > 180 then
                     set angle=angle-360
                 endif
                 return angle>=angle2 and angle<=angle1
             endif
          return (angle>=angle1) and (angle<=angle2)
         endfunction

         //====================================================================================================================================================================
         function CreateCaster takes real fac, real x , real y returns unit
          local unit m
             if (x!=0) then
                 set x=CS_SafeX(x)
             endif
             if (y!=0) then
                 set y=CS_SafeY(y)
             endif
             set m=CreateUnit( Player(15), cs_CasterUnitId, x ,y ,fac)

             
             call UnitAddAbility(m, 'Aloc')
             call UnitAddAbility(m, cs_FlyingHeightHack)
             call UnitRemoveAbility(m, cs_FlyingHeightHack )
          set udg_currentcaster=m
          set m=null
          return udg_currentcaster
         endfunction



         function AddCasterFacing takes real fac returns unit
             return CreateCaster(fac,0,0)
         endfunction

         function AddCaster takes nothing returns unit
             return CreateCaster(0,0,0)
         endfunction


         //====================================================================================================================================================================
         function CreateCasters takes integer n returns nothing
          local integer a=0
          local unit c
             loop
                 exitwhen a>=n
                 set c=CreateCaster(0,0,0)
                 call GroupAddUnit( udg_casters, c)
                 set a=a+1
             endloop
          set c=null
         endfunction

         private function InitCasterSystem takes nothing returns nothing
             set udg_casters=NewGroup()
             call CS_SafeXY_Init()
             call CreateCasters(cs_InitialCastersNumber)
             set udg_castervars[100]=-1
             set udg_castervars[101]=-1
             set udg_castervars[102]=-1
             set udg_castervars[103]=-1
             set udg_castervars[104]=-1

             set cs_dmg_caster=CreateCaster(0.,0.,0.)
             call UnitRemoveAbility(cs_dmg_caster,'Aloc') //Otherwise the units would flee like crazy

         endfunction



         //====================================================================================================================================================================
         function GetACaster takes nothing returns unit
             set udg_currentcaster=FirstOfGroup( udg_casters)
             if udg_currentcaster == null then
                 set udg_currentcaster=CreateCaster(0,0,0)
             endif
             call GroupRemoveUnit( udg_casters,udg_currentcaster)
             call SetUnitState( udg_currentcaster, UNIT_STATE_MANA, 1000)
          return udg_currentcaster
         endfunction

         //====================================================================================================================================================================
         function Caster_SetZAngle takes unit caster, real ang returns nothing
          local real a=(ModuloReal(GetUnitFacing(caster),360)*bj_DEGTORAD)
          local real x
             set ang=ModuloReal(ang,360)
             if ( ang == 90 ) then
                 set ang = 89
             endif
             if ( ang == 270 ) then
                 set ang = 271
             endif
             if (ang>90) and (ang<270) then
                 set x=-1
             else
                 set x=1
             endif
             set ang=ang*bj_DEGTORAD
             call SetUnitLookAt(caster,"Bone_Chest",caster, 10000.0*Cos(a)*Cos(ang), 10000.0*Sin(a)*Cos(ang), x*(10000.0*Tan(ang)+90.0) )
         endfunction

         //====================================================================================================================================================================
         function Caster_SetZAngle2 takes unit caster, integer ang returns nothing
             call SetUnitAnimationByIndex(caster,ang+90) //Thanks infrane!
         endfunction

         //====================================================================================================================================================================
         function RecycleCaster takes unit caster returns nothing
             if GetWidgetLife(caster)>=0.405 then
                 call ResetUnitLookAt(caster)
                 call SetUnitOwner( caster, Player(15), true)
                 call SetUnitVertexColor( caster, 255,255,255,255)
                 call SetUnitScale( caster, 1,1,1)
                 call SetUnitTimeScale( caster, 1)
                 call SetUnitMoveSpeed( caster, 522)
                 call SetUnitFlyHeight( caster, 0,0)
                 call UnitAddAbility(caster, 'Aloc')
                 call SetUnitTurnSpeed( caster, 0.6)
                 call GroupAddUnit( udg_casters, caster)
             endif
         endfunction

         function RecycleCaster_Light takes unit caster returns nothing
             if GetWidgetLife(caster)>=0.405 then
                 call SetUnitOwner( caster, Player(15), true)
                 call GroupAddUnit( udg_casters, caster)
             endif
         endfunction
         function RecicleCaster takes unit caster returns nothing
             call RecycleCaster(caster)
         endfunction
         function RecicleCaster_Light takes unit caster returns nothing
             call RecycleCaster_Light(caster)
         endfunction

         private struct csrecy
             unit caster
             integer abil
         endstruct

         function CasterRecycleTimed_X takes nothing returns nothing
          local timer t=GetExpiredTimer()
          local csrecy k=GetCSData(t)
             if (k.abil!=0) then
                 call UnitRemoveAbility(k.caster,k.abil)
             endif
             call RecycleCaster(k.caster)
             call k.destroy()
             call ReleaseTimer(t)
         endfunction

         function CasterRecycleTimed takes unit caster, integer abi, real delay returns nothing
          local timer t=NewTimer()
          local csrecy k= csrecy.create()
             set k.caster=caster
             set k.abil=abi
             call SetCSData(t,k)

             call TimerStart(t,delay,false,function CasterRecycleTimed_X)
         endfunction

         function CasterWaitForEndCast takes nothing returns nothing
          local unit caster=udg_currentcaster
          local integer abilid=udg_currentabi
          local real delay=udg_castervars[0]
          local boolean activeability=(udg_castervars[1]>0)
             loop
                 exitwhen GetUnitCurrentOrder(caster) == 0
                 call TriggerSleepAction(0)
             endloop
             if (delay>0) then
                 if activeability then
                     call CasterRecycleTimed(caster,abilid,delay)
                 else
                     call UnitRemoveAbility( caster, abilid)
                     call CasterRecycleTimed(caster,0,delay)
                 endif
             else
                 call UnitRemoveAbility( caster, abilid)
                 call RecycleCaster(caster)
             endif
          set caster=null
         endfunction

         function RecycleCasterAfterCastEx takes unit caster, real delaytime, integer abilid, boolean activeability returns nothing
             set udg_castervars[0]=delaytime
             set udg_castervars[1]=IntegerTertiaryOp(activeability,1,0)
             set udg_currentabi=abilid
             set udg_currentcaster=caster
             call ExecuteFunc("CasterWaitForEndCast" )
         endfunction
         function RecicleCasterAfterCastEx takes unit caster, real delaytime, integer abilid, boolean activeability returns nothing
             call RecycleCasterAfterCastEx(caster,delaytime,abilid,activeability)
         endfunction

         function CasterWaitForEndCast_Light takes nothing returns nothing
          local unit caster=udg_currentcaster
          local integer abilid=udg_currentabi
          local real delay=udg_castervars[0]
          local boolean activeability=(udg_castervars[1]>0)
             loop
                 exitwhen GetUnitCurrentOrder(caster) == 0
                 call TriggerSleepAction(0)
             endloop
             if (delay>0) then
                 if activeability then
                     call CasterRecycleTimed(caster,abilid,delay)
                 else
                     call UnitRemoveAbility( caster, abilid)
                     call CasterRecycleTimed(caster,0,delay)
                 endif
             else
                 call UnitRemoveAbility( caster, abilid)
                 call RecycleCaster_Light(caster)
             endif
          set caster=null
         endfunction

         function RecycleCasterAfterCastEx_Light takes unit caster, real delaytime, integer abilid, boolean activeability returns nothing
             set udg_castervars[0]=delaytime
             set udg_castervars[1]=IntegerTertiaryOp(activeability,1,0)
             set udg_currentabi=abilid
             set udg_currentcaster=caster
             call ExecuteFunc("CasterWaitForEndCast_Light" )
         endfunction


         function RecicleCasterAfterCastEx_Light takes unit caster, real delaytime, integer abilid, boolean activeability returns nothing
             call RecycleCasterAfterCastEx_Light(caster,delaytime,abilid,activeability)
         endfunction
         function RecicleCasterAfterCast takes unit caster, integer abilid returns nothing
             call RecycleCasterAfterCastEx(caster,udg_delayhack,abilid,false)
         endfunction
         function RecycleCasterAfterCast takes unit caster, integer abilid returns nothing
             call RecycleCasterAfterCastEx(caster,udg_delayhack,abilid,false)
         endfunction


         //====================================================================================================================================================================
         function PreloadAbility takes integer abilid returns integer
          local unit u=FirstOfGroup(udg_casters)
             if u==null then
                 set u=GetACaster()
                 call UnitAddAbility(u, abilid)
                 call UnitRemoveAbility(u, abilid)
                 call RecycleCaster_Light( u)
             else
                 call UnitAddAbility(u, abilid)
                 call UnitRemoveAbility(u, abilid)
             endif
          set u=null
          return abilid
         endfunction

         //====================================================================================================================================================================
         function CasterCastAbilityEx takes player owner, real x, real y, real z, integer abilid, integer level, string order, widget target, real delay returns unit
          local unit caster=GetACaster()
          local boolean done=false
             call SetUnitOwner( caster, owner, false)
             call UnitAddAbility( caster, abilid)
             call SetUnitAbilityLevel(caster,abilid,level)
             call SetUnitX(caster,x)
             call SetUnitY(caster,y)
             call SetUnitFlyHeight(caster,z,0)
             if S2I(order) != 0 then
                 set done=IssueTargetOrderById( caster, S2I(order), target )
             else
                 set done=IssueTargetOrder( caster, order, target )
             endif
             if (delay<=0) or not(done) then
                 call UnitRemoveAbility( caster, abilid)
                 call RecycleCaster_Light( caster)
             else
                 call RecycleCasterAfterCastEx_Light(caster, delay, abilid, true)
             endif
          set udg_currentcaster=caster
          set caster=null
          return udg_currentcaster
         endfunction

         //====================================================================================================================================================================
         function CasterCastAbilityExLoc takes player owner, location loc, real z, integer abilid, integer level, string order, widget target, real delay returns unit
             return CasterCastAbilityEx(owner,GetLocationX(loc),GetLocationY(loc),z,abilid,level,order,target,delay)
         endfunction

         //====================================================================================================================================================================
         function CasterCastAbilityLevel takes player owner, integer abilid, integer level, string order, widget target, boolean instant returns unit
          local real x
          local real y
          local real d
             if udg_sourcehack!=null then
                 set x=GetLocationX(udg_sourcehack)
                 set y=GetLocationY(udg_sourcehack)
             else
                 set x=GetWidgetX(target)
                 set y=GetWidgetY(target)
             endif
             if not(instant)  then
                 set d=udg_delayhack+0.01
             else
                 set d=0
             endif
          return CasterCastAbilityEx(owner,x,y,0,abilid,level,order,target,d)
         endfunction

         //====================================================================================================================================================================
         function CasterCastAbility takes player owner, integer abilid, string order, widget target, boolean instant returns unit
             return CasterCastAbilityLevel( owner, abilid, 1, order, target, instant )
         endfunction

         //====================================================================================================================================================================
         function CasterCastAbilityPointEx takes player owner, real x1, real y1, real z1, integer abilid, integer level, string order, real x2, real y2, real delay returns unit
          local unit caster=GetACaster()
             call SetUnitOwner( caster, owner, false)
             call UnitAddAbility( caster, abilid)
             call SetUnitAbilityLevel(caster,abilid,level)
             call SetUnitX(caster,x1)
             call SetUnitY(caster,y1)
             call SetUnitFlyHeight(caster,z1,0)
             if S2I(order) != 0 then
                 if not IssuePointOrderById( caster, S2I(order), x2,y2 ) then
                     call IssueImmediateOrderById( caster, S2I(order) )
                 endif
             else
                 if not IssuePointOrder( caster, order, x2,y2 ) then
                     call IssueImmediateOrder( caster, order )
                 endif
             endif
             if (delay<=0) then
                 call UnitRemoveAbility( caster, abilid)
                 call RecycleCaster_Light( caster)
             else
                 call RecicleCasterAfterCastEx_Light(caster, delay, abilid, true)
             endif
          set udg_currentcaster=caster
          set caster=null
          return udg_currentcaster
         endfunction

         //====================================================================================================================================================================
         function CasterCastAbilityPointExLoc takes player owner, location loc1, real z1, integer abilid, integer level, string order, location loc2, real delay returns unit
             return CasterCastAbilityPointEx(owner,GetLocationX(loc1),GetLocationY(loc1),z1,abilid,level,order,GetLocationX(loc2),GetLocationY(loc2),delay)
         endfunction

         //====================================================================================================================================================================
         function CasterCastAbilityLevelPoint takes player owner, integer abilid, integer level, string order, real x, real y, boolean instant returns unit
          local real sx
          local real sy
          local real d
             if udg_sourcehack!=null then
                 set sx=GetLocationX(udg_sourcehack)
                 set sy=GetLocationY(udg_sourcehack)
             else
                 set sx=x
                 set sy=y
             endif
             if instant then
                 set d=0
             else
                 set d=udg_delayhack+0.01
             endif
          return CasterCastAbilityPointEx(owner,sx,sy,0,abilid,level,order,x,y,d)
         endfunction

         function CasterCastAbilityPoint takes player owner, integer abilid, string order, real x, real y, boolean instant returns unit
             return CasterCastAbilityLevelPoint(owner,abilid,1,order,x,y,instant)
         endfunction

         function CasterCastAbilityPointLoc takes player owner, integer abilid, string order, location loc, boolean instant returns unit
             return CasterCastAbilityLevelPoint( owner, abilid, 1,order, GetLocationX(loc), GetLocationY(loc), instant )
         endfunction

         function CasterCastAbilityLevelPointLoc takes player owner, integer abilid, integer level, string order, location loc, boolean instant returns unit
             return CasterCastAbilityLevelPoint( owner, abilid, level,order, GetLocationX(loc), GetLocationY(loc), instant )
         endfunction

         //====================================================================================================================================================================
         private struct cssabi
            effect fx
            unit caster
            integer abil
         endstruct

         function CasterUseAbilityLevelStatic_Rec takes nothing returns nothing
          local timer t=GetExpiredTimer()
          local cssabi k=GetCSData(t)
             call RecycleCaster(k.caster)
             call k.destroy()
             call ReleaseTimer(t)
         endfunction

         function CasterUseAbilityLevelStatic_X takes nothing returns nothing
          local timer t=GetExpiredTimer()
          local cssabi k=GetCSData(t)

             call DestroyEffect(k.fx)
             call UnitRemoveAbility( k.caster, k.abil)
             call TimerStart(t,2,false, function CasterUseAbilityLevelStatic_Rec)
         endfunction

         function CasterUseAbilityLevelStatic takes player owner, string modelpath, integer abilityid, integer level, real duration, real x, real y returns unit
          local timer t=NewTimer()
          local unit c=GetACaster()
          local cssabi k= cssabi.create()


             call SetUnitPosition( c, x, y)
             set k.fx= AddSpecialEffectTarget( modelpath, c,"origin" )
             set k.caster = c
             set k.abil=abilityid

             call SetUnitOwner(c, owner, true)
             call UnitAddAbility(c, abilityid)
             call SetUnitAbilityLevel(c, abilityid, level)

             call SetCSData(t,k)
             call TimerStart(t,duration,false,function CasterUseAbilityLevelStatic_X)


             set udg_currentcaster=c
          set c=null
          return udg_currentcaster
         endfunction

         function CasterUseAbilityStatic takes player owner, string modelpath, integer abilityid, real duration, real x, real y returns unit
             return CasterUseAbilityLevelStatic(owner,modelpath,abilityid,1,duration,x,y)
         endfunction

         function CasterUseAbilityStaticLoc takes player owner, string modelpath, integer abilityid, real duration, location loc returns unit
             return CasterUseAbilityLevelStatic(owner,modelpath,abilityid,1,duration, GetLocationX(loc), GetLocationY(loc))
         endfunction

         function CasterUseAbilityLevelStaticLoc takes player owner, string modelpath, integer abilityid, integer level,real duration, location loc returns unit
             return CasterUseAbilityLevelStatic(owner,modelpath,abilityid,level,duration, GetLocationX(loc), GetLocationY(loc))
         endfunction

         //====================================================================================================================================================================
         function CasterCastAbilityLevelGroup takes player owner, integer abilid, integer level,string order, group targetgroup, boolean instant returns nothing
          local group affected
          local unit tempunit
          local unit caster=null
             if bj_wantDestroyGroup then
                 set bj_wantDestroyGroup=false
                 set affected=targetgroup
             else
                 set affected=NewGroup()
                 call GroupAddGroup( targetgroup, affected)
             endif
             loop
                set tempunit=FirstOfGroup(affected)
                exitwhen tempunit == null
                if instant then
                    if caster==null then
                        set caster=GetACaster()
                        call SetUnitOwner( caster, owner, false)
                        call UnitAddAbility( caster, abilid)
                        call SetUnitAbilityLevel( caster, abilid,level)
                    endif
                    if udg_sourcehack != null then
                        call SetUnitX(caster,GetLocationX(udg_sourcehack))
                        call SetUnitY(caster,GetLocationY(udg_sourcehack))

                    else
                        call SetUnitX(caster,GetUnitX(tempunit))
                        call SetUnitY(caster,GetUnitY(tempunit))
                    endif

                    if S2I(order) != 0 then
                        call IssueTargetOrderById( caster, S2I(order), tempunit )
                    else
                        call IssueTargetOrder( caster, order, tempunit )
                    endif
                else
                    call CasterCastAbilityLevel( owner, abilid,level, order, tempunit, false)
                endif
                call GroupRemoveUnit(affected, tempunit)    
             endloop
             if caster != null then
                 call UnitRemoveAbility( caster, abilid)
                 call RecycleCaster(caster)
             endif
          call ReleaseGroup(affected)
          set affected=null
          set tempunit=null
          set caster=null
         endfunction

         function CasterCastAbilityGroup takes player owner, integer abilid, string order, group targetgroup, boolean instant returns nothing
             call CasterCastAbilityLevelGroup(owner,abilid,1,order,targetgroup,instant)
         endfunction

         //====================================================================================================================================================================
         function CasterAOE_IsFilterEnemy takes nothing returns boolean
             return IsUnitEnemy( GetFilterUnit(), bj_groupEnumOwningPlayer ) and ( GetWidgetLife(GetFilterUnit()) > 0.405)
         endfunction

         function CasterAOE_IsFilterAlly takes nothing returns boolean
             return IsUnitAlly( GetFilterUnit(), bj_groupEnumOwningPlayer ) and ( GetWidgetLife(GetFilterUnit()) > 0.405)
         endfunction

         //====================================================================================================================================================================
         function CasterCastAbilityLevelAOE takes player owner, integer abilid, integer level, string order, real x, real y, real radius, boolean goodeffect, boolean instant returns nothing
          local boolexpr b
          local group aoe=NewGroup()
             set bj_groupEnumOwningPlayer=owner
             if goodeffect then
                 set b=Condition(function CasterAOE_IsFilterAlly)
             else
                 set b=Condition(function CasterAOE_IsFilterEnemy)
             endif
             call CS_EnumUnitsInAOE(aoe, x,y, radius, b)
             set bj_wantDestroyGroup=true
             call CasterCastAbilityLevelGroup( owner, abilid, level, order, aoe, instant)
          call DestroyBoolExpr(b)
          set b=null
          set aoe=null
         endfunction

         function CasterCastAbilityAOE takes player owner, integer abilid, string order, real x, real y, real radius, boolean goodeffect, boolean instant returns nothing
             call CasterCastAbilityLevelAOE(owner,abilid,1,order,x,y,radius,goodeffect,instant)
         endfunction

         function CasterCastAbilityAOELoc takes player owner, integer abilid, string order, location center, real radius, boolean goodeffect, boolean instant returns nothing
             call CasterCastAbilityLevelAOE(owner, abilid,1, order, GetLocationX(center),  GetLocationY(center), radius, goodeffect, instant)
         endfunction

         function CasterCastAbilityLevelAOELoc takes player owner, integer abilid, integer level, string order, location center, real radius, boolean goodeffect, boolean instant returns nothing
             call CasterCastAbilityLevelAOE(owner, abilid,level, order, GetLocationX(center),  GetLocationY(center), radius, goodeffect, instant)
         endfunction

         //====================================================================================================================================================================
         globals
             timer cs_sourcehacktimer = CreateTimer()
             timer cs_delayhacktimer  = CreateTimer()
         endglobals

         function ResetSourceHack takes nothing returns nothing
             if (udg_sourcehack!=null) then
                 call RemoveLocation(udg_sourcehack)
                 set udg_sourcehack=null
             endif
         endfunction

         function CasterSetCastSource takes real x, real y returns nothing
             if (udg_sourcehack==null) then
                 set udg_sourcehack=Location(x,y)
             else
                 call MoveLocation(udg_sourcehack,x,y)
             endif
             call TimerStart(cs_sourcehacktimer,0.,false,function ResetSourceHack)
         endfunction

         function CasterSetCastSourceLoc takes location loc returns nothing
             call CasterSetCastSource( GetLocationX(loc), GetLocationY(loc) )
         endfunction

         function ResetDelayHack takes nothing returns nothing
             set udg_delayhack=0.
         endfunction

         function CasterSetRecycleDelay takes real Delay returns nothing
             set udg_delayhack=Delay
             call TimerStart(cs_delayhacktimer,0.,false,function ResetDelayHack)
         endfunction

         //====================================================================================================================================================================


         //Super DamageOptions structure!
         globals
            attacktype cs_dopt_Atype          = null
            damagetype cs_dopt_Dtype          = null
            unittype   cs_dopt_ExceptionUtype = null
            real       cs_dopt_ExceptionFct   = 1.0

            unittype   cs_dopt_OnlyUtype      = null
            unittype   cs_dopt_IgnoreUtype    = null



            integer    cs_dopt_EnemyAlly      = 0 //[ 0 = onlyenemies, 1= forceall, 2=onlyallies]
            integer    cs_dopt_dfab1    = 'null'
            real       cs_dopt_dfab1_fc = 1.0
            integer    cs_dopt_dfab2    = 'null'
            real       cs_dopt_dfab2_fc = 1.
            integer    cs_dopt_dfab3    = 'null'
            real       cs_dopt_dfab3_fc = 1.

            real       cs_dopt_Ally_fc  = 1.
         endglobals


         function DamageTypes takes attacktype attT, damagetype dmgT returns integer
         //    set udg_castervars[100] = CS_H2I(attT)
         //    set udg_castervars[101] = CS_H2I(dmgT)
             set cs_dopt_Atype=attT
             set cs_dopt_Dtype=dmgT
          return 1
         endfunction

         function DamageException takes unittype Exception, real ExceptionFactor returns integer
             set cs_dopt_ExceptionUtype=Exception
             set cs_dopt_ExceptionFct = ExceptionFactor
         //    set udg_castervars[102] = CS_H2I(Exception)
         //    set udg_castervars[103] = ExceptionFactor
          return 2
         endfunction

         function DamageOnlyTo takes unittype ThisUnitType returns integer
             set cs_dopt_OnlyUtype = ThisUnitType
         //    set udg_castervars[104] = CS_H2I(ThisUnitType)
          return 4
         endfunction

         constant function DontDamageSelf takes nothing returns integer
          return 8
         endfunction

         constant function DamageTrees takes nothing returns integer
          return 16
         endfunction

         constant function DamageOnlyVisibles takes nothing returns integer
          return 32
         endfunction

         function DamageOnlyEnemies takes nothing returns integer
             set cs_dopt_EnemyAlly=0
         // ouch, forgot what it was
          return 64
         endfunction

         function ForceDamageAllies takes nothing returns integer
             set cs_dopt_EnemyAlly=1
          return 64
         endfunction

         function DamageOnlyAllies takes nothing returns integer
             set cs_dopt_EnemyAlly=2
          return 64
         endfunction

         function DamageFactorAbility1 takes integer spellid, real factor returns integer
             set cs_dopt_dfab1=spellid
             set cs_dopt_dfab1_fc=factor
          return 128
         endfunction

         function DamageFactorAbility2 takes integer spellid, real factor returns integer
             set cs_dopt_dfab2=spellid
             set cs_dopt_dfab2_fc=factor

          return 256
         endfunction

         function DamageFactorAbility3 takes integer spellid, real factor returns integer
             set cs_dopt_dfab3=spellid
             set cs_dopt_dfab3_fc=factor

          return 512
         endfunction

         function DamageIgnore takes unittype ThisUnitType returns integer
             set cs_dopt_IgnoreUtype = ThisUnitType
         //    set udg_castervars[112] = CS_H2I(ThisUnitType)
          return 1024
         endfunction

         function DamageAlliedFactor takes real fct returns integer
               set cs_dopt_Ally_fc = fct
         //    set udg_castervars[113] = fct
          return 2048
         endfunction

         constant function ConsiderOnlyDeadUnits takes nothing returns integer
          return 4096
         endfunction

         constant function IgnoreDeadState takes nothing returns integer
          return 8192
         endfunction


         //===============================================================================================
         function IsDamageOptionIncluded takes integer DamageOptions, integer whichDamageOption returns boolean
          local integer i=8192
             if (DamageOptions==0) then
                 return false
             endif
             loop
                 exitwhen (i<=whichDamageOption)
                 if (DamageOptions>=i) then
                     set DamageOptions=DamageOptions-i
                 endif
                 set i=i/2
             endloop
          return (DamageOptions>=whichDamageOption)
         endfunction


         //=================================================================================================
         globals
             unit cs_dmg_caster=null
         endglobals

         function GetDamageFactor takes unit u,attacktype a, damagetype d returns real
          local real hp=GetWidgetLife(u)
          local real mana=GetUnitState(u,UNIT_STATE_MANA)
          local real r

             //Since a unit is in that point, we don't need checks.
             call SetUnitX(cs_dmg_caster,GetUnitX(u))
             call SetUnitY(cs_dmg_caster,GetUnitY(u))

             call SetUnitOwner(cs_dmg_caster,GetOwningPlayer(u),false)
             set r=hp
             if (hp<1) then
                 call SetWidgetLife(u,1)
                 set r=1
             endif
             call UnitDamageTarget(cs_dmg_caster,u,0.01,true,false,a,d,null)
             call SetUnitOwner(cs_dmg_caster,Player(15),false)
             if (mana>GetUnitState(u,UNIT_STATE_MANA)) then
                 //Unit had mana shield, return 1 and restore mana too.
                 call SetUnitState(u,UNIT_STATE_MANA,mana)
                 set r=1
             else
                 set r= (r-GetWidgetLife(u))*100
             endif
             call SetWidgetLife(u,hp)

          return r
         endfunction

         //======================================================================================================
         // Fix for the unit type bugs from blizzard, amphibious units aren't considered ground for some reason
         // so this considers any non flying unit as ground.
         //
         // Also heroes are resistant too, so in case UNIT_TYPE_RESISTANT is used it will return true in case the
         // unit is a hero too.
         //
         function CS_IsUnitType takes unit u, unittype ut returns boolean
             if (ut==UNIT_TYPE_GROUND) then
                 return not(IsUnitType(u,UNIT_TYPE_FLYING))
             elseif (ut==UNIT_TYPE_RESISTANT) then
                 return IsUnitType(u,ut) or IsUnitType(u,UNIT_TYPE_HERO)
             endif
          return IsUnitType(u,ut)
         endfunction

         function GetDamageFactorByOptions takes unit hurter, unit target, integer d returns real
          local real r=1
         
             if (d>=8192) then
                 set d=d-8192
             elseif (d>=4096) then
                 if (GetWidgetLife(target)>0.405) then
                     return 0.0
                 endif
                 set d=d-4096
             elseif (GetWidgetLife(target)<=0.405) then
                 return 0.0
             endif

             if d>=2048 then
                 if IsUnitAlly(target,GetOwningPlayer(hurter)) then
                     set r=r* cs_dopt_Ally_fc
                 endif
                 set d=d-2048
             endif
             if d>=1024 then
                 if CS_IsUnitType(target, cs_dopt_IgnoreUtype ) then
                     return 0.0
                 endif
                 set d=d-1024
             endif
             if d>=512 then
                 if GetUnitAbilityLevel(target, cs_dopt_dfab1 )>0 then
                     set r=r*cs_dopt_dfab1_fc
                 endif
                 set d=d-512
             endif
             if d>=256 then
                 if GetUnitAbilityLevel(target, cs_dopt_dfab2 )>0 then
                     set r=r*cs_dopt_dfab2_fc
                 endif
                 set d=d-256
             endif
             if d>=128 then
                 if GetUnitAbilityLevel(target, cs_dopt_dfab3 )>0 then
                     set r=r*cs_dopt_dfab3_fc
                 endif
                 set d=d-128
             endif
             if d>=64 then
                 if (cs_dopt_EnemyAlly==0) and IsUnitAlly(target,GetOwningPlayer(hurter)) then
                     return 0.0
                 elseif (cs_dopt_EnemyAlly==2) and IsUnitEnemy(target,GetOwningPlayer(hurter)) then
                     return 0.0
                 endif
                 set d=d-64
             endif
             if d>=32 then
                 set d=d-32
                 if not IsUnitVisible(target,GetOwningPlayer(hurter)) then
                     return 0.0
                 endif
             endif
             if d>=16 then
                 set d=d-16
             endif
             if d>=8 then
                 set d=d-8
                 if hurter==target then
                     return 0.0
                 endif
             endif
             if d>=4 then
                 set d=d-4
                 if not CS_IsUnitType( target,cs_dopt_OnlyUtype) then
                     return 0.0
                 endif
             endif
             if d>=2 then
                 set d=d-2
                 if CS_IsUnitType( target, cs_dopt_ExceptionUtype ) then
                     set r=r* cs_dopt_ExceptionFct
                 endif
             endif
             if d>=1 then
                 set d=d-1
                 set r=r*GetDamageFactor(target,cs_dopt_Atype,cs_dopt_Dtype)
             endif
          return r
         endfunction

         //======================================================================================================================
         // This used to be needed because in 1.17 UnitDamageTarget didn't consider the damagetype argument, this bug
         // was fixed in 1.18, and we no longer need this function, left for compatibility.
         //
         function DamageUnitByTypes takes unit hurter, unit target, real dmg, attacktype attT, damagetype dmgT returns boolean
             return UnitDamageTarget(hurter,target,dmg,true,false,attT,dmgT,null)
         endfunction

         //=============================================================================================================================
         function DamageUnitByOptions takes unit hurter, unit target, real dmg, integer DamageOptions returns boolean
          local real f=GetDamageFactorByOptions(hurter,target,DamageOptions)
             if (f==0) then
                 return false
             endif
          return UnitDamageTarget(hurter,target,dmg*f,true,false,null,null,null)
         endfunction

         //=============================================================================================================================
         function DamageUnit takes player hurter, real damage, unit victim returns boolean
             call SetUnitX(cs_dmg_caster,GetUnitX(victim))
             call SetUnitY(cs_dmg_caster,GetUnitY(victim))

             call SetUnitOwner(cs_dmg_caster,hurter,false)
             call DamageUnitByTypes(cs_dmg_caster,victim,damage,cs_DefaultAttackType,cs_DefaultDamageType)
             call SetUnitOwner(cs_dmg_caster,Player(15),false)

          return GetWidgetLife(victim)<=0 // I thought UnitDamageTarget returned true when it killed the unit, but nope, it returns true when it was able to do the damage.
         endfunction

         //====================================================================================================================================================================
         function UnitDamageUnitTimed_Child takes nothing returns nothing
          local real damage = udg_castervars[0]
          local real damageperiod= udg_castervars[2]
          local effect fx=bj_lastCreatedEffect
          local timer t=NewTimer()
          local unit hurter=udg_currenthurter
          local real next=0
          local integer i=0
          local real c
          local unit target=udg_currentcaster
          local damagetype dmgT=ConvertDamageType(R2I(udg_castervars[4]))
          local attacktype attT=ConvertAttackType(R2I(udg_castervars[3]))

             call TimerStart(t, udg_castervars[1]-0.01, false,null)
             loop
                 if TimerGetElapsed(t) >= next then
                     exitwhen not UnitDamageTarget(hurter, target, damage,true,false, attT, dmgT,null)
                     exitwhen GetWidgetLife(target)<=0.405
                     set i=i+1
                     set next=i*damageperiod
                 endif
                 exitwhen (TimerGetRemaining(t) <= 0) or GetWidgetLife(target)<=0.405
                 call TriggerSleepAction(0)
             endloop
          call DestroyEffect(fx)
          call ReleaseTimer(t)
          set fx=null
          set dmgT=null
          set attT=null
         endfunction

         function UnitDamageUnitTimed takes unit hurter, real damageps, real damageperiod, real duration, unit target, string modelpath, string attachPointName, attacktype attT, damagetype dmgT returns nothing
          local unit c=udg_currentcaster
             set bj_lastCreatedEffect=AddSpecialEffectTarget( modelpath, target,attachPointName )
             set udg_currentcaster=target
             set udg_castervars[0]=damageps
             set udg_castervars[1]=duration
             set udg_castervars[2]=damageperiod
             set udg_castervars[3]=CS_H2I(attT)
             set udg_castervars[4]=CS_H2I(dmgT)
             set udg_currenthurter=hurter
             call ExecuteFunc("UnitDamageUnitTimed_Child")
             set udg_currentcaster=c
          set c=null
         endfunction

         //=============================================================================================================
         // Left for compatibility
         //
         function DamageUnitTimedEx_Child takes nothing returns nothing
          local real damage = udg_castervars[0]
          local real damageperiod= udg_castervars[2]
          local effect fx=bj_lastCreatedEffect
          local timer t=NewTimer()
          local integer id=udg_currentabi
          local real next=0
          local integer i=0
          local real c
          local unit target=udg_currentcaster
             call TimerStart(t, udg_castervars[1]-0.01, false,null)
             loop
                 if TimerGetElapsed(t) >= next then
                     exitwhen DamageUnit( Player(id), damage, target)
                     set i=i+1
                     set next=i*damageperiod
                 endif
                 exitwhen (TimerGetRemaining(t) <= 0) or GetWidgetLife(target)<=0.405
                 call TriggerSleepAction(0)
             endloop
          call DestroyEffect(fx)
          call ReleaseTimer(t)
          set fx=null
         endfunction

         function DamageUnitTimedEx takes player owner, real damageps, real damageperiod, real duration, unit target, string modelpath, string attachPointName returns nothing
          local unit c=udg_currentcaster
             set bj_lastCreatedEffect=AddSpecialEffectTarget( modelpath, target,attachPointName )
             set udg_currentcaster=target
             set udg_castervars[0]=damageps
             set udg_castervars[1]=duration
             set udg_castervars[2]=damageperiod
             set udg_currentabi=GetPlayerId( owner )
             call ExecuteFunc("DamageUnitTimedEx_Child")
             set udg_currentcaster=c
          set c=null
         endfunction

         function DamageUnitTimed takes player owner, real damageps, real duration, unit target, string modelpath, string attachPointName returns nothing
             call DamageUnitTimedEx(owner , damageps, 1, duration, target, modelpath, attachPointName )
         endfunction

         //[
         private struct dostruct
             integer    value
             attacktype attt
             damagetype dmgt
             unittype   excp
             real       excf
             unittype   only
             integer    allied
             integer    dfab1
             real       dfab1_fc
             integer    dfab2
             real       dfab2_fc
             integer    dfab3
             real       dfab3_fc
             unittype   ign
             real       ally_fc
         endstruct

         // integer k used to point to a table in gamecache, this is the reason I am not using dostruct directly
         // the evil backwards compatibility... You shall find out why OOP guys like encapsullation so much...
         //
         // It's fun, it was first an integer pointing to a mission in gamecache, then it was a dynamic array
         // and now it is a struct... so much history.
         function SetDamageOptions_i takes integer k, integer DamageOptions returns nothing
          local integer d=DamageOptions
             set dostruct(k).value=d
             if (d>=8192) then
                 set d=d-8192
             endif
             if (d>=4096) then
                 set d=d-4096
             endif
             
             if d>=2048 then
                 set dostruct(k).ally_fc=cs_dopt_Ally_fc
                 set d=d-2048
             endif
             if d>=1024 then
                 set dostruct(k).ign = cs_dopt_IgnoreUtype
                 set d=d-1024
             endif
             if d>=512 then
                 set dostruct(k).dfab3=cs_dopt_dfab3
                 set dostruct(k).dfab3_fc=cs_dopt_dfab3_fc
                 set d=d-512
             endif
             if d>=256 then
                 set dostruct(k).dfab2=cs_dopt_dfab2
                 set dostruct(k).dfab2_fc=cs_dopt_dfab2_fc
                 set d=d-256
             endif
             if d>=128 then
                 set dostruct(k).dfab1=cs_dopt_dfab1
                 set dostruct(k).dfab1_fc=cs_dopt_dfab1_fc
                 set d=d-128
             endif
         //[0 integer value][1 integer attT][2 integer dmgT][3 integer excp][4 real excf][5 integer only]
         //[6 integer allied][7 integer ab1][8 real fc1][9 integer ab2][10 real fc2][11 integer ab3][12 real fc3]
         //[13 integer ign][14 real allf]

             if d >= 64 then
                 set d=d-64
                 set dostruct(k).allied=cs_dopt_EnemyAlly //[6=allied]
             endif
             if d >= 32 then
                 set d=d-32
             endif
             if d >= 16 then
                 set d=d-16
             endif
             if d >= 8 then
                 set d=d-8
             endif
             if d >= 4 then
                 set dostruct(k).only=cs_dopt_OnlyUtype
                 set d=d-4
             endif
             if d >= 2 then
                 set dostruct(k).excp= cs_dopt_ExceptionUtype
                 set dostruct(k).excf= cs_dopt_ExceptionFct
                 set d=d-2
             endif
             if d >= 1 then
                 set dostruct(k).attt=cs_dopt_Atype
                 set dostruct(k).dmgt=cs_dopt_Dtype
             endif
         endfunction


         // inline friendly:)
         function SetDamageOptions takes integer id, integer DamageOptions returns nothing
             call SetDamageOptions_i(id,DamageOptions)
         endfunction

         function CreateDamageOptions takes integer DamageOptions returns integer
          local integer n =integer(dostruct.create())

             call SetDamageOptions_i(n,DamageOptions)

          return n
         endfunction

         function DestroyDamageOptions takes integer id returns nothing
             call dostruct(id).destroy()
         endfunction

         function LoadDamageOptions takes integer id returns integer
          local integer opt=dostruct(id).value
          local integer v=opt

             if v>=8192 then
                 set v=v-8192
             endif
             if v>=4096 then
                 set v=v-4096
             endif
             if v>=2048 then
                 set cs_dopt_Ally_fc = dostruct(id).ally_fc
                 set v=v-2028
             endif
             if v>=1024 then
                 set cs_dopt_IgnoreUtype =  dostruct(id).ign
                 set v=v-1024
             endif
             if v>=512 then
                 set cs_dopt_dfab3   =dostruct(id).dfab3
                 set cs_dopt_dfab3_fc=dostruct(id).dfab3_fc
                 set v=v-512
             endif
             if v>=256 then
                 set cs_dopt_dfab2   =dostruct(id).dfab2
                 set cs_dopt_dfab2_fc=dostruct(id).dfab2_fc
                 set v=v-256
             endif
             if v>=128 then
                 set cs_dopt_dfab1   =dostruct(id).dfab1
                 set cs_dopt_dfab1_fc=dostruct(id).dfab1_fc
                 set v=v-128
             endif
             if v >= 64 then
                 set v=v-64
                 set cs_dopt_EnemyAlly= dostruct(id).allied
             endif
             if v >= 32 then
                 set v=v-32
             endif
             if v >= 16 then
                 set v=v-16
             endif
             if v >= 8 then
                 set v=v-8
             endif
             if v >= 4 then
                 set cs_dopt_OnlyUtype = dostruct(id).only
                 set v=v-4
             endif
             if v >= 2 then
                 set cs_dopt_ExceptionUtype= dostruct(id).excp
                 set cs_dopt_ExceptionFct=   dostruct(id).excf
                 set v=v-2
             endif
             if v >= 1 then
                 set cs_dopt_Atype= dostruct(id).attt
                 set cs_dopt_Dtype= dostruct(id).dmgt
             endif

          return opt
         endfunction

         //==================================================================================================
         function IsDestructableTree_withcs takes destructable d returns boolean

          local boolean b
          local boolean i=IsDestructableInvulnerable(d)

             call SetUnitX(cs_dmg_caster,GetWidgetX(d))
             call SetUnitY(cs_dmg_caster,GetWidgetY(d))

             if i then
                 call SetDestructableInvulnerable(d,false)
             endif
             call UnitAddAbility(cs_dmg_caster,cs_DamageTreeDetectorId)

             set b=(IssueTargetOrder(cs_dmg_caster,"eattree",d))
             call UnitRemoveAbility(cs_dmg_caster,cs_DamageTreeDetectorId)

             if i then
                 call SetDestructableInvulnerable(d,true)
             endif
          return b
         endfunction

         function IsDestructableTree takes destructable d returns boolean
          local string k=I2S(GetDestructableTypeId(d))
          local boolean b

             if HaveStoredBoolean(cs_cache,"trees",k) then
                 set b=GetStoredBoolean(cs_cache,"trees",k)
                 return b
             else
                 set b=IsDestructableTree_withcs(d)
                 call StoreBoolean(cs_cache,"trees",k,b)
             endif
          return b
         endfunction

         //===============================================================================================
         function DamageDestructablesInCircleEnum takes nothing returns nothing
          local destructable d=GetEnumDestructable()
          local unit u=udg_currentcaster
             if (GetWidgetLife(d)>0) and not(IsDestructableInvulnerable(d)) and ((Pow(GetDestructableX(d)-udg_castervars[200],2)+Pow(GetDestructableY(d)-udg_castervars[201],2)) <= udg_castervars[202]) then
                 call SetWidgetLife(d,GetWidgetLife(d)-udg_castervars[203])
             endif
          set udg_currentcaster=u
          set u=null
          set d=null
         endfunction

         function DamageDestructablesInCircle takes real x, real y, real radius, real dmg returns nothing
          local rect r=Rect(x - radius,y - radius,x + radius,y + radius)
             set udg_castervars[200]=x
             set udg_castervars[201]=y
             set udg_castervars[202]=radius*radius
             set udg_castervars[203]=dmg
             call EnumDestructablesInRect(r,null,function DamageDestructablesInCircleEnum)
          call RemoveRect(r)
          set r=null
         endfunction

         function DamageDestructablesInCircleLoc takes location loc, real radius, real dmg returns nothing
             call DamageDestructablesInCircle(GetLocationX(loc),GetLocationY(loc),radius,dmg)
         endfunction

         function DamageTreesInCircleEnum takes nothing returns nothing
          local destructable d=GetEnumDestructable()
             if (GetWidgetLife(d)>0) and not(IsDestructableInvulnerable(d)) and ((Pow(GetDestructableX(d)-udg_castervars[200],2)+Pow(GetDestructableY(d)-udg_castervars[201],2)) <= udg_castervars[202]) and (IsDestructableTree(d)) then
                 call KillDestructable(d)
             endif
          set d=null
         endfunction

         function DamageTreesInCircle takes real x, real y, real radius returns nothing
          local rect r=Rect(x - radius,y - radius,x + radius,y + radius)
             set udg_castervars[200]=x
             set udg_castervars[201]=y
             set udg_castervars[202]=radius*radius
             call EnumDestructablesInRect(r,null,function DamageTreesInCircleEnum)
          call RemoveRect(r)
          set r=null
         endfunction

         function DamageTreesInCircleLoc takes location loc, real radius returns nothing
             call DamageTreesInCircle(GetLocationX(loc),GetLocationY(loc),radius)
         endfunction

         function DamageUnitGroupEx takes unit hurter, real damage, group targetgroup, integer DamageOptions returns nothing
          local group affected
          local unit p
             if bj_wantDestroyGroup then
                 set bj_wantDestroyGroup=false
                 set affected=targetgroup
             else
                 set affected=NewGroup()
                 call GroupAddGroup( targetgroup, affected)
             endif
             loop
                 set p=FirstOfGroup(affected)
                 exitwhen p==null
                 call DamageUnitByOptions(hurter,p,damage,DamageOptions)
                 call GroupRemoveUnit(affected,p)
             endloop
          call ReleaseGroup(affected)
          set affected=null
          set p=null
         endfunction

         function DamageUnitsInAOEEx takes unit hurter, real damage, real x, real y, real radius, boolean affectallied, integer DamageOptions returns nothing
          local boolexpr b=null
          local group aoe=NewGroup()
          local integer d=DamageOptions
             set bj_groupEnumOwningPlayer=GetOwningPlayer(hurter)
             if d>=8192 then
                 set d=d-8192
             endif
             if d>=4096 then
                 set d=d-4096
             endif

             if d>=2048 then
                 set d=d-2048
             endif
             if d>=1024 then
                 set d=d-1024
             endif
             if d>=512 then
                 set d=d-512
             endif
             if d>=256 then
                 set d=d-256
             endif
             if d>=128 then
                 set d=d-128
             endif
             if d>=64 then
                 if     (cs_dopt_EnemyAlly==2) then
                     set b=Condition(function CasterAOE_IsFilterAlly)
                 elseif (cs_dopt_EnemyAlly==1) then
                 else
                     set b=Condition(function CasterAOE_IsFilterEnemy)
                 endif
                 set d=d-64
             elseif not(affectallied) then
                 set b=Condition(function CasterAOE_IsFilterEnemy)
             endif
             if d>=32 then
                 set d=d-32
             endif
             if d>=16 then
                 call DamageTreesInCircle(x,y,radius)
             endif
             call CS_EnumUnitsInAOE(aoe, x,y, radius, b)
             set bj_wantDestroyGroup=true
             call DamageUnitGroupEx( hurter, damage, aoe,DamageOptions)
             //call DestroyBoolExpr(b)
          set b=null
          set aoe=null
         endfunction

         function DamageUnitsInAOEExLoc takes unit hurter, real damage, location loc, real radius, boolean affectallied, integer DamageOptions returns nothing
             call DamageUnitsInAOEEx(hurter,damage, GetLocationX(loc), GetLocationY(loc), radius, affectallied,DamageOptions)
         endfunction

         function DamageUnitGroup takes player hurter, real damage, group targetgroup returns nothing
             call SetUnitOwner(cs_dmg_caster,hurter,false)
             call DamageUnitGroupEx(cs_dmg_caster,damage,targetgroup,0)
             call SetUnitOwner(cs_dmg_caster,Player(15),false)
         endfunction

         //====================================================================================================================================================================
         function DamageUnitsInAOE takes player hurter, real damage, real x, real y, real radius, boolean affectallied returns nothing
             call SetUnitOwner(cs_dmg_caster,hurter,false)
             call DamageUnitsInAOEEx(cs_dmg_caster,damage,x,y,radius,affectallied,0)
             call SetUnitOwner(cs_dmg_caster,Player(15),false)
         endfunction

         function DamageUnitsInAOELoc takes player hurter, real damage, location loc, real radius, boolean affectallied returns nothing
             call DamageUnitsInAOE( hurter, damage, GetLocationX(loc), GetLocationY(loc), radius, affectallied)
         endfunction

         //====================================================================================================================================================================
         function AddAreaDamagerForUnit_Child takes nothing returns nothing
          local real D
          local real damageps = udg_castervars[0]
          local real area = udg_castervars[2]
          local real damageperiod = udg_castervars[3]
          local real excd=udg_castervars[8]
          local boolean affectallies = (udg_castervars[4]>=1)
          local boolean onlyallies = (udg_castervars[4]==2)
          local boolean self = (udg_castervars[5]==1)
          local unit hurter=udg_currenthurter
          local unit fire = udg_currentcaster
          local player owner = GetOwningPlayer(fire)
          local timer t = NewTimer()
          local real next = 0
          local integer a = 0
          local group inrange = NewGroup()
          local string c
          local string art=bj_lastPlayedMusic
          local string attach=""
          local unit picked
          local boolean recicled=false
          local unittype only=null
          local unittype ign=null
          local unittype exce=null
          local attacktype attT
          local damagetype dmgT
          local boolean trees=(udg_castervars[11]==1)
          local boolean inv=(udg_castervars[12]==1)
          local integer a1=0
          local integer a2=0
          local integer a3=0
          local real f1=cs_dopt_dfab1_fc
          local real f2=cs_dopt_dfab2_fc
          local real f3=cs_dopt_dfab3_fc
          local real allf=udg_castervars[113]
          local effect array fx
          local integer deadcond=R2I(udg_castervars[114])
          local boolean deadeval=false
          local integer fxn=0
             set fx[0]=bj_lastCreatedEffect

             if f1!=1 then
                 set a1=cs_dopt_dfab1
             endif
             if f2!=1 then
                 set a2=cs_dopt_dfab2
             endif
             if f3!=1 then
                 set a3=cs_dopt_dfab3
             endif
             if udg_castervars[112]!=-1 then
                 set ign=ConvertUnitType(R2I(udg_castervars[112]))
             endif
             if udg_castervars[6]!=-1 then
                 set only=ConvertUnitType(R2I(udg_castervars[6]))
             endif
             if udg_castervars[7]!=-1 then
                 set exce=ConvertUnitType(R2I(udg_castervars[7]))    
             endif
             if udg_castervars[9]!=-1 then
                 set attT=ConvertAttackType(R2I(udg_castervars[9]))
             else
                 set attT=cs_DefaultAttackType
             endif
             if udg_castervars[10]!=-1 then
                 set dmgT=ConvertDamageType(R2I(udg_castervars[10]))
             else
                 set dmgT=cs_DefaultDamageType
             endif
             loop
                 set c=SubString(art,a,a+1)
                 exitwhen c=="!" or c==""
                 set attach=attach+c
                 set a=a+1
             endloop
             set art=SubString(art,a+1,10000)
             call TimerStart(t, udg_castervars[1]-0.01, false,null)
             set a=0
             loop
                 loop
                     exitwhen fxn<=0
                     call DestroyEffect(fx[fxn])
                     set fx[fxn]=null
                     set fxn=fxn-1
                 endloop
                 if IsUnitInGroup( fire, udg_casters) then
                     set recicled=true
                     call GroupRemoveUnit( udg_casters,fire)
                 endif
                 exitwhen recicled
                 if TimerGetElapsed(t) >= next then
                     set a=a+1
                     set next=a*damageperiod
                     call CS_EnumUnitsInAOE(inrange, GetUnitX(fire), GetUnitY(fire), area, null )
                     if trees then
                         call DamageTreesInCircle(GetUnitX(fire), GetUnitY(fire), area)
                     endif
                     loop
                         set picked=FirstOfGroup(inrange)
                         exitwhen picked==null
                         if (deadcond==0) then
                             set deadeval=(GetWidgetLife(picked)>0.405)
                         elseif(deadcond==1)then
                             set deadeval=(GetWidgetLife(picked)<=0.405)
                         else
                             set deadeval=true
                         endif
                         if (self or picked!=hurter) and not(GetWidgetLife(picked)<=0.405) and ( ((affectallies or onlyallies) and IsUnitAlly(picked, owner)) or (not(onlyallies) and IsUnitEnemy(picked, owner)) ) and (only==null or CS_IsUnitType(picked,only)) and (ign==null or not(CS_IsUnitType(picked,ign))) then
                             set D=damageps
                             if (allf!=1) and IsUnitAlly(picked, owner) then
                                 set D=D*allf
                             endif
                             if (exce!=null) and CS_IsUnitType(picked,exce) then
                                 set D=D*excd
                             endif
                             if inv and not(IsUnitVisible(picked,owner)) then
                                 set D=0
                             endif
                             if (a1!=0) and (GetUnitAbilityLevel(picked,a1)>0) then
                                 set D=D*f1
                             endif
                             if (a2!=0) and (GetUnitAbilityLevel(picked,a2)>0) then
                                 set D=D*f2
                             endif
                             if (a3!=0) and (GetUnitAbilityLevel(picked,a3)>0) then
                                 set D=D*f3
                             endif
                             if D!=0 then
                                 call DamageUnitByTypes(hurter,picked,D,attT,dmgT )
                                 if (art!="") and (art!=null) then
                                     set fxn=fxn+1
                                     set fx[fxn]=AddSpecialEffectTarget(art,picked,attach)
                                 endif
                             endif
                         endif
                         call GroupRemoveUnit(inrange,picked)
                     endloop
                 endif
                 exitwhen TimerGetRemaining(t)<=0
                 call TriggerSleepAction(0)
             endloop
          call ReleaseGroup(inrange)
          call DestroyEffect(fx[0])
          call TriggerSleepAction(2)
          call RecicleCaster(fire)
          call ReleaseTimer(t)
          set inrange=null
          set fire=null
          set owner=null
          set fx[0]=null
          set picked=null
          set hurter=null
          set only=null
          set ign=null
          set exce=null
          set attT=null
          set dmgT=null
         endfunction

         function AddAreaDamagerForUnit takes unit hurter, string modelpath, string targetart, string targetattach, real x, real y, real damage , real damageperiod, real duration, real area, boolean affectallies, integer DamageOptions returns unit
          local string s=bj_lastPlayedMusic
          local integer v=DamageOptions
             set bj_lastPlayedMusic=targetattach+"!"+targetart
             set udg_currentcaster=GetACaster()
             call SetUnitPosition( udg_currentcaster, x, y)
             set bj_lastCreatedEffect = AddSpecialEffectTarget( modelpath, udg_currentcaster,"origin" )
             set udg_castervars[0]=damage
             set udg_castervars[1]=duration
             set udg_castervars[2]=area
             set udg_castervars[3]=damageperiod
             
             if(v>=8192)then
                 set udg_castervars[114]=2
                 set v=v-8192
             elseif (v>=4096)then
                 set udg_castervars[114]=1
                 set v=v-4096
             else
                 set udg_castervars[114]=0
             endif

             if v>=2048 then
                 set v=v-2048
             else
                 set udg_castervars[113]=1
             endif
             if v >= 1024 then
                 set v=v-1024
             else
                 set udg_castervars[112]=-1
             endif
             if v >= 512 then
                 set v=v-512
             else
                 set udg_castervars[111]=0
             endif
             if v >= 256 then
                 set v=v-256
             else
                 set udg_castervars[109]=0
             endif
             if v >= 128 then
                 set v=v-128
             else
                 set udg_castervars[107]=0
             endif
             if v >= 64 then
                 set v=v-64
                 set udg_castervars[4]=cs_dopt_EnemyAlly
             else
                 set udg_castervars[4]=IntegerTertiaryOp(affectallies,1,0)
             endif
             if v >= 32 then
                 set udg_castervars[12]=1
                 set v=v-32
             else
                 set udg_castervars[12]=0
             endif
             if v >= 16 then
                 set udg_castervars[11]=1
                 set v=v-16
             else
                 set udg_castervars[11]=0
             endif
             if v >= 8 then
                 set udg_castervars[5]=0
                 set v=v-8
             else
                 set udg_castervars[5]=1
             endif
             if v >= 4 then
                 set udg_castervars[6]=CS_H2I(cs_dopt_OnlyUtype)
                 set v=v-4
             else
                 set udg_castervars[6]=-1
             endif
             if v >= 2 then
                 set udg_castervars[7]=CS_H2I(cs_dopt_ExceptionUtype)
                 set udg_castervars[8]=damage*cs_dopt_ExceptionFct
                 set v=v-2
             else
                 set udg_castervars[7]=-1
                 set udg_castervars[8]=-1
             endif
             if v >= 1 then
                 set udg_castervars[9]=  CS_H2I(cs_dopt_Atype)
                 set udg_castervars[10]=  CS_H2I(cs_dopt_Dtype)
             else
                 set udg_castervars[9]=-1
                 set udg_castervars[10]=-1
             endif
             set udg_currenthurter=hurter
             call SetUnitOwner( udg_currentcaster, GetOwningPlayer(hurter), true)
             call ExecuteFunc("AddAreaDamagerForUnit_Child")
             set bj_lastPlayedMusic=s
          return udg_currentcaster
         endfunction

         function AddAreaDamagerForUnitLoc takes unit hurter, string modelpath, string targetart, string targetattach, location loc, real damage , real damageperiod, real duration, real area, boolean affectallies, integer DamageOptions returns unit
          return AddAreaDamagerForUnit(hurter,modelpath,targetart,targetattach,GetLocationX(loc),GetLocationY(loc), damage , damageperiod, duration, area,affectallies, DamageOptions)
         endfunction

         function AddDamagingEffectEx takes player owner, string modelpath, string targetart, string targetattach, real x, real y, real damage , real damageperiod, real duration, real area, boolean affectallies returns unit
          local string s=bj_lastPlayedMusic
             set bj_lastPlayedMusic=targetattach+"!"+targetart
             set udg_currentcaster=GetACaster()
             call SetUnitPosition( udg_currentcaster, x, y)
             set bj_lastCreatedEffect = AddSpecialEffectTarget( modelpath, udg_currentcaster,"origin" )
             set udg_castervars[0]=damage
             set udg_castervars[1]=duration
             set udg_castervars[2]=area
             set udg_castervars[3]=damageperiod
             set udg_castervars[4]=IntegerTertiaryOp(affectallies,1,0)
             set udg_castervars[5]=1
             set udg_castervars[6]=-1
             set udg_castervars[7]=-1
             set udg_castervars[8]=-1
             set udg_castervars[9]=-1
             set udg_castervars[10]=-1
             set udg_castervars[107]=0
             set udg_castervars[109]=0
             set udg_castervars[111]=0
             set udg_castervars[112]=-1
             set udg_castervars[113]=1
             set udg_currenthurter=udg_currentcaster
             call SetUnitOwner( udg_currentcaster, owner, true)
             call ExecuteFunc("AddAreaDamagerForUnit_Child")
             set bj_lastPlayedMusic=s
          return udg_currentcaster
         endfunction

         function AddDamagingEffectExLoc takes player owner, string modelpath, string targetart, string targetattach, location loc, real damage , real damageperiod, real duration, real area, boolean affectallies returns unit
             return AddDamagingEffectEx( owner, modelpath, targetart, targetattach, GetLocationX(loc), GetLocationY(loc), damage , damageperiod, duration, area, affectallies )
         endfunction

         function AddDamagingEffect takes player owner, string modelpath, real x, real y, real damageps , real duration, real area, boolean affectallies returns unit
             return AddDamagingEffectEx( owner, modelpath, "", "", x, y, damageps , 1, duration, area, affectallies )
         endfunction

         function AddDamagingEffectLoc takes player owner, string modelpath, location loc, real damageps , real duration, real area, boolean affectallies returns unit
             return AddDamagingEffectEx( owner, modelpath, "", "", GetLocationX(loc), GetLocationY(loc), damageps ,1, duration, area, affectallies)
         endfunction

         //============================================================================================================
         function UnitMoveToAsProjectileAnySpeed_Move takes unit m, csprojectile k returns boolean
          local boolean tounit = k.tounit
          local unit tg
          local real x2
          local real y2
          local real z2
          local real x1=GetUnitX(m)
          local real y1=GetUnitY(m)
          local real z1=GetUnitFlyHeight(m)
          local real g
          local real d
          local real od
          local real v
          local real time
          local integer n
          local boolean done=false
          local effect fx

             if tounit then
                 set tg=k.target
                 if (GetWidgetLife(tg)<=0.405) then
                     set tounit=false
                     set k.tounit=false
                 else
                     set x2=GetUnitX(tg)
                     set y2=GetUnitY(tg)
                     set z2=GetUnitFlyHeight(tg)+k.z2o
                     set n=k.N
                     if (n==0) then
                         //Using the counter prevents us to save z2,x2,y2 too much times and saves speed
                         set k.z2=z2
                         set k.x2=x2 // Backup stuff just in case
                         set k.y2=y2
                     elseif (n==25) then
                         set n=0
                     else
                         set n=n+1
                     endif
                     set k.N=n
                 endif
                 set tg=null
             endif

             if not(tounit) then
                 set z2=k.z2
                 set x2=k.x2
                 set y2=k.y2
             endif

             set g=Atan2(y2-y1,x2-x1)
             call SetUnitFacing(m,g*bj_RADTODEG)


             set v=k.speed
             set d= v * cs_TIMER_CYCLE
             
             set od=SquareRoot(Pow(x1-x2,2) +  Pow(y1-y2,2))
             if( od  <=d )then
                 call SetUnitX(m,x2)
                 call SetUnitY(m,y2)
                 set done=true
             else
                 call SetUnitX(m,x1+d*Cos(g))
                 call SetUnitY(m,y1+d*Sin(g))
             endif



             set g=k.acel
             set time= od / v
             set d=v
             set v=(z2-z1+0.5*g*time*time)/time //z speed
             if (GetUnitTypeId(m)==cs_CasterUnitId) then
                 call SetUnitAnimationByIndex(m,R2I(Atan2(v,d)* bj_RADTODEG)+90) //Thanks infrane!
             endif
             call SetUnitFlyHeight(m,z1+v*cs_TIMER_CYCLE,0)
             set d=( Pow(GetUnitX(m)-x2,2) + Pow(GetUnitY(m)-y2,2) )
             if (done or (d<=400)) then //So the actual distance is less than or equal to 20
                 set done=true
                 set k.done=true
                 set fx=k.fx
                 if (fx!=null) then
                     call SetUnitAnimationByIndex(m,91)
                     call DestroyEffect(fx)
                     set fx=null
                 endif
             endif
          return done
         endfunction

         interface csmissile
             integer mtype=0
             unit m          //the missile
         endinterface
         globals
             constant integer cs_TYPE_COLLISIONMISSILE=2
             constant integer cs_TYPE_PROJECTILE=1
         endglobals


         struct cscollisionmissile extends csmissile
             integer state //state of the collision missile
             trigger t
                 triggeraction ac
             real collision
             real speed
             real aspeed     //angle speed
             real f          //facing of collisionmissile

             real maxd

             integer ttype=0             //target type
                  static constant integer ttype_widget=2
                  static constant integer ttype_point=1
                  static constant integer ttype_none=0

             real   tx       //homing target x
             real   ty       //homing target y
             widget tw       //homing target widget

             boolean pfx=false   //periodic fx mode
             real    pfx_current //current pfx (timer)
             real    pfx_dur     //duration of a periodic effect
             string  pfx_path    //path for the periodix fx

             boolean new  //Was it a new collision missile or must be recycled?
             effect  fx

             integer tag=0 //custom tag for the user.
         endstruct

         function CollisionMissile_Destroyer takes unit m, cscollisionmissile k, trigger T returns nothing
          local trigger tr = T
          local triggeraction ta = k.ac

             if (k.fx!=null) then
                 call DestroyEffect(k.fx)
             endif
             

             if (k.new) then
                 call ExplodeUnitBJ(m)
             else
                 call RecicleCasterAfterCastEx(m,4,0,true)
             endif
             
             call TriggerRemoveAction(tr,ta)
             //call TriggerRemoveAction(T,GetArrayTriggerAction(k,18)) //[18=triggeraction]
             
             call k.destroy()
             
             //call Hostage(CS_H2I(tr))
           
             call DestroyTrigger(tr)
             //call CleanAttachedVars(T)
             //call DestroyTrigger(T)

          set tr = null
          set ta = null

         endfunction



         function GetTriggerCollisionMissile takes nothing returns unit
             return s__csmissile_m[GetCSData(GetTriggeringTrigger()) ]
         endfunction



         function CollisionMissile_Move takes unit m, cscollisionmissile k returns boolean
          local integer state= k.state
          local boolean done
          local real d
          local real F
          local real asp
          local real x
          local real nx
          local real y
          local real ny
          local integer tt
          local widget wd
         
          local trigger TTT

         
             if (state==2) then
                 set TTT=k.t
                 call TriggerExecute(TTT)
                 set TTT=null
                 set k.state=3
                 return false
             elseif (state==3) then
                  call CollisionMissile_Destroyer(m,k,k.t)
                  return true
             else
                 if (state==1) then
                     call TriggerRegisterUnitInRange(k.t,m,k.collision,null)
                     set k.state=0
                 endif
                 set d=k.speed * cs_TIMER_CYCLE
                 set F=k.f
                 set asp=k.aspeed
                 set x=GetUnitX(m)
                 set y=GetUnitY(m)
                 if (asp!=0) then
                     set tt=k.ttype
                     if (tt==cscollisionmissile.ttype_point) or (tt==cscollisionmissile.ttype_widget ) then
                         if (tt==cscollisionmissile.ttype_point) then
                             set nx=k.tx
                             set ny=k.ty
                             set F=Angles_MoveAngleTowardsAngle(F,Atan2(ny-y,nx-x)*bj_RADTODEG, asp * cs_TIMER_CYCLE)
                         else
                             set wd=k.tw
                             if (GetWidgetLife(wd)<=0.405) then
                                 set k.ttype=cscollisionmissile.ttype_none
                                 set nx=x+0.001
                                 set ny=y+0.001
                                 set F=F+ asp * cs_TIMER_CYCLE
                             else
                                 set nx=GetWidgetX(wd)
                                 set ny=GetWidgetY(wd)
                                 set F=Angles_MoveAngleTowardsAngle(F,Atan2(ny-y,nx-x)*bj_RADTODEG, asp * cs_TIMER_CYCLE)
                             endif
                            set wd=null
                         endif
                     else
                         set F=F+ asp * cs_TIMER_CYCLE
                     endif
                     set k.f=F
                     call SetUnitFacing(m,F)
                 endif
                 set F=F*bj_DEGTORAD
                 set nx=x+d*Cos(F)
                 set ny=y+d*Sin(F)
                 set d=k.maxd-d
                 set k.maxd=d
                 set done=(d<=0)
                 if (not done) then
                     if not(CS_MoveUnit(m,nx,ny)) then
                         set done=true
                     elseif (k.pfx) then
                         set F=  k.pfx_current+cs_TIMER_CYCLE
                         if (F>=k.pfx_dur) then
                             call DestroyEffect(AddSpecialEffectTarget(k.pfx_path, m, "origin"  ))
                             set k.pfx_current=0.
                         else
                             set k.pfx_current=F
                         endif
                     endif
                 endif
             endif
             if done then
                 call DisableTrigger(k.t)
                 call DestroyEffect(k.fx)
                 set k.fx=null
                 set k.state=2
                 return false
             endif
          return false
         endfunction

         function CasterSystemMovementTimer takes nothing returns nothing
          local timer ti
          local integer n=cs_missilecount
          local integer i=1
          local unit p

          local csmissile k


             loop
                 exitwhen (i>n)
                 set k=cs_missiles[i]

                     if (k.mtype==cs_TYPE_COLLISIONMISSILE) then
                     
                         set p=k.m

                         if not(CollisionMissile_Move(p,k)) then
                             set i=i+1                  
                         else
                             set cs_missiles[i]=cs_missiles[n]
                             set n=n-1
                         endif
                     elseif (k.mtype==cs_TYPE_PROJECTILE) then
                         set p=k.m
                         if not(UnitMoveToAsProjectileAnySpeed_Move(p,k )) then
                             set i=i+1
                         else
                             set cs_missiles[i]=cs_missiles[n]
                             set n=n-1
                         endif
                     else
                         set i=i+1
                         call BJDebugMsg("Caster System: Unexpected Error (1) Wrong Array:"+I2S(k)+" ; "+I2S(k.mtype))
                     endif

             endloop

             if (n==0) then
                 call PauseTimer(cs_movementtimer)
                 set cs_movementtimer_active=false
             endif
             set cs_missilecount=n
             
          set p=null
         endfunction

         struct csprojectile extends csmissile
             boolean tounit //Is it directed towards a unit?
             unit    target //if so, what target?
             real    z2
             real    x2
             real    y2

             real    speed
             real    acel

             boolean done=false
             effect  fx

             real    z2o    // offset for z2, useful for flyers
             integer N=0
         endstruct


         function UnitMoveToAsProjectileAnySpeed_Effect takes unit m, effect fx, real speed, real arc, real x2, real y2, unit target, real z2 returns nothing
         //
         //   The internal projectile system used by all the projectile functions
         //
          local timer t //=GetTableTimer("CasterSystem","MOVEMENT_TIMER")


          local string km
          local csprojectile k

             set km=I2S(CS_H2I(m))
             set k=GetTableInt("MOVEMENT_TABLES",km)
             if (k>0) then
                 set k.done=true
             endif
             set k=csprojectile.create()
             set k.m=m

             call StoreInteger(cs_cache,"MOVEMENT_TABLES",km,k)
         

             set cs_missilecount=cs_missilecount+1
             set cs_missiles[cs_missilecount]=k
             
             if (not cs_movementtimer_active) then  
                 call TimerStart(cs_movementtimer,cs_TIMER_CYCLE,true,function CasterSystemMovementTimer)
                 set cs_movementtimer_active=true
             endif

             set k.mtype=cs_TYPE_PROJECTILE

             if (target!=null) then
                 set k.tounit=true
                 set k.target=target
                 set k.x2=GetUnitX(target)
                 set k.y2=GetUnitY(target)
                 set k.z2o=z2
             else
                 set k.tounit=false
                 set k.x2=x2
                 set k.y2=y2
             endif

             set k.z2=z2
             set k.speed=speed

             set k.acel=arc*8000
             if (fx!=null) then
                 set k.fx=fx
                set fx=null
             endif
             loop
                 exitwhen k.done
                 call TriggerSleepAction(0)
             endloop
             call FlushStoredInteger(cs_cache,"MOVEMENT_TABLES",km)
             call k.destroy()

         endfunction

         function UnitMoveToAsProjectileAnySpeed takes unit m, real speed, real arc, real x2, real y2, unit target, real z2 returns nothing
         //Left for compat
             call UnitMoveToAsProjectileAnySpeed_Effect(m,null,speed,arc,x2,y2,target,z2)
         endfunction


         //========================================================================================================================
         function UnitMoveToAsProjectileGen takes unit m, real arc, real x2, real y2, unit target, real z2 returns nothing
         //
         //   The internal projectile system used by all the projectile functions
         //
          local real x1=GetUnitX(m)
          local real y1=GetUnitY(m)
          local real acel=arc*1600
          local real speed=GetUnitMoveSpeed(m)
          local real z1=GetUnitFlyHeight(m)
          local real d
          local real d1
          local real d2
          local real t
          local real vel
          local real dif=0
          local boolean tounit= (target!=null)
          local boolean b=false
          local boolean mode=false
             if tounit then
                 set x2=GetUnitX(target)
                 set y2=GetUnitY(target)
                 set z2=GetUnitFlyHeight(target)+z2
             endif
             set mode=(z2>z1)
             set d=SquareRoot(Pow(x2-x1,2)+Pow(y2-y1,2))
             set d1=1000000
             set d2=0
             set t=d/speed
             if t==0 then
                 set t=0.001
             endif
             set vel=(z2-z1+0.5*acel*t*t)/t
             call SetUnitFacing( m, Atan2BJ(y2 - y1, x2 - x2) )
             call IssuePointOrder( m, "move", x2,y2)
             set t=0
             loop
                 set d2=d1
                 if tounit then
                     if (GetWidgetLife(target)<=0.405) then
                         set tounit=false
                     else
                         set x2=GetUnitX(target)
                         set y2=GetUnitY(target)
                     endif
                 endif
                 set d1=SquareRoot(Pow(x2-GetUnitX(m),2)+Pow(y2-GetUnitY(m),2))
                 exitwhen b or d1==0
                 set b=(d1<=speed*(t-dif))
                 exitwhen (mode and b) or (GetUnitCurrentOrder(m) != OrderId("move"))
                 if tounit then
                     call IssuePointOrder( m, "move", x2,y2)
                 endif
                 set dif=t
                 if dif==0.001 then
                    set t=0.1
                 else
                     set t= (d-d1)/speed
                 endif
                 set t= 2*t-dif
                 call SetUnitFlyHeight( m, z1+(vel*t-0.5*acel*t*t), RAbsBJ( vel-acel*(t+dif)/2) )
                 set t=(t+dif)/2
                 call TriggerSleepAction(0)
             endloop
             if tounit then
                 set x2=GetUnitX(target)
                 set y2=GetUnitY(target)
             endif
             call SetUnitFlyHeight( m,z2,0)
             call SetUnitX(m,x2)
             call SetUnitY(m,y2)
         endfunction

         function UnitMoveToAsProjectile takes unit m, real arc, real x2, real y2, real z2 returns nothing
             call UnitMoveToAsProjectileGen(m, arc,x2,y2,null,z2)
         endfunction

         //============================================================================================================
         function ProjectileLaunchEx takes player owner, string modelpath, real scale, integer red, integer green, integer blue, integer alpha, real speed, real arc,real x1, real y1, real z1, real x2, real y2, real z2 returns nothing
          local unit m=CreateCaster( Atan2BJ(y2 - y1, x2 - x1),x1,y1 )
          local effect fx=null

             call SetUnitScale( m, scale, scale, scale)
             call SetUnitVertexColor(m, red, green, blue, alpha)

             call SetUnitFlyHeight( m, z1, 0)
             set fx= AddSpecialEffectTarget( modelpath, m,"origin" )
             call SetUnitOwner( m, owner, true)

             if (speed<=522) then
                 call SetUnitMoveSpeed(m, speed)
                 call UnitMoveToAsProjectile(m, arc, x2, y2, z2)
                 call DestroyEffect(fx)
             else
                 call UnitMoveToAsProjectileAnySpeed_Effect(m,fx,speed,arc,x2,y2,null,z2)
             endif
             call ExplodeUnitBJ(m)
          set owner=null
          set fx=null
          set m=null
         endfunction

         function ProjectileLaunchExLoc takes player owner, string modelpath, real scale, integer red, integer green, integer blue, integer alpha, real speed, real arc, location loc1, real z1, location loc2, real z2 returns nothing
             call ProjectileLaunchEx( owner, modelpath, scale, red, green, blue, alpha, speed, arc,GetLocationX(loc1), GetLocationY(loc1), z1, GetLocationX(loc2), GetLocationY(loc2), z2)
         endfunction


     

     
  20. Dat-C3

    Dat-C3

    Joined:
    Mar 15, 2012
    Messages:
    2,435
    Resources:
    10
    Models:
    1
    Maps:
    5
    Spells:
    3
    Tutorials:
    1
    Resources:
    10
    part2
    Code (vJASS):


         //============================================================================================================
         function ProjectileLaunch takes string modelpath, real speed, real arc,real x1, real y1, real z1, real x2, real y2, real z2 returns nothing
             call ProjectileLaunchEx( Player(15), modelpath, 1, 255, 255, 255, 255, speed, arc,x1,y1,z1,x2,y2,z2)
         endfunction

         function ProjectileLaunchLoc takes string modelpath, real speed, real arc, location loc1, real z1, location loc2, real z2 returns nothing
             call ProjectileLaunchExLoc( Player(15), modelpath, 1,255,255,255,255,speed,arc,loc1,z1,loc2,z2)
         endfunction

         //============================================================================================================
         function DamagingProjectileLaunchAOE_Child takes nothing returns nothing
          local unit m=udg_currentcaster
          local effect fx=bj_lastCreatedEffect
          local real x2=udg_castervars[0]
          local real y2=udg_castervars[1]
          local real aoeradius=udg_castervars[3]
          local real damage=udg_castervars[4]
          local boolean affectallied=bj_isUnitGroupInRectResult
          local integer V=CreateDamageOptions(R2I(udg_castervars[5]))
          local unit hurter=udg_currenthurter
          local real speed=udg_castervars[6]
             if (speed<=522) then
                 call SetUnitMoveSpeed(m, speed)
                 call UnitMoveToAsProjectile(m, bj_meleeNearestMineDist, udg_castervars[0], udg_castervars[1], udg_castervars[2])
                 call DestroyEffect(fx)
             else
                 call UnitMoveToAsProjectileAnySpeed_Effect(m,fx,speed,bj_meleeNearestMineDist, udg_castervars[0], udg_castervars[1],null, udg_castervars[2])
             endif

             call DamageUnitsInAOEEx(hurter,damage,x2,y2,aoeradius,affectallied,LoadDamageOptions(V))
             call DestroyDamageOptions(V)
             call ExplodeUnitBJ(m)
          set m=null
          set fx=null
         endfunction

         function DamagingProjectileLaunchAOE takes unit hurter, string modelpath, real speed, real arc, real x1, real y1, real z1, real x2, real y2, real z2, real aoeradius, real damage, boolean affectallied, integer DamageOptions returns unit
          local unit m=CreateCaster( Atan2BJ(y2 - y1, x2 - x1) ,x1,y1)

             call SetUnitFlyHeight( m, z1, 0)
             set udg_currentcaster=m
             set bj_lastCreatedEffect=AddSpecialEffectTarget( modelpath, m,"origin" )
             call SetUnitOwner( m, GetOwningPlayer(hurter), true)
             set bj_meleeNearestMineDist = arc
             set udg_castervars[0] = x2
             set udg_castervars[1] = y2
             set udg_castervars[2] = z2
             set udg_castervars[3] =aoeradius
             set udg_castervars[4] =damage
             set udg_castervars[5] =DamageOptions
             set udg_castervars[6] =speed
             set udg_currenthurter=hurter
             set bj_isUnitGroupInRectResult=affectallied
             call ExecuteFunc("DamagingProjectileLaunchAOE_Child")
          set m=null
          return udg_currentcaster
         endfunction

         function DamagingProjectileLaunchAOELoc takes unit hurter, string modelpath, real speed, real arc, location loc1, real z1, location loc2, real z2, real aoeradius, real damage, boolean affectallied, integer DamageOptions returns unit
             return DamagingProjectileLaunchAOE(hurter,modelpath,speed,arc,GetLocationX(loc1),GetLocationY(loc1),z1,GetLocationX(loc2),GetLocationY(loc2),z2, aoeradius, damage, affectallied, DamageOptions )
         endfunction

         function ProjectileLaunchDamage takes player owner, string modelpath, real speed, real arc, real x1, real y1, real z1, real x2, real y2, real z2, real aoeradius, real damage, boolean affectallied returns unit
          local unit m=CreateCaster( Atan2BJ(y2 - y1, x2 - x1) ,x1,y1 )

             call SetUnitFlyHeight( m, z1, 0)
             set udg_currentcaster=m
             set bj_lastCreatedEffect=AddSpecialEffectTarget( modelpath, m,"origin" )
             call SetUnitOwner( m, owner, true)
             set bj_meleeNearestMineDist = arc
             set udg_castervars[0] = x2
             set udg_castervars[1] = y2
             set udg_castervars[2] = z2
             set udg_castervars[3] =aoeradius
             set udg_castervars[4] =damage
             set udg_castervars[5] =0
             set udg_castervars[6]= speed

             set bj_isUnitGroupInRectResult=affectallied
             set udg_currenthurter=m
             call ExecuteFunc("DamagingProjectileLaunchAOE_Child")
          set m=null
          return udg_currentcaster
         endfunction

         function ProjectileLaunchDamageLoc takes player owner, string modelpath, real speed, real arc, location loc1, real z1, location loc2, real z2, real aoeradius, real damage, boolean affectallied returns unit
             return ProjectileLaunchDamage( owner, modelpath, speed, arc, GetLocationX(loc1), GetLocationY(loc1), z1, GetLocationX(loc2), GetLocationY(loc2), z2, aoeradius, damage, affectallied)
         endfunction

         //============================================================================================================
         function ProjectileLaunchKill_Child takes nothing returns nothing
          local unit m=udg_currentcaster
          local effect fx=bj_lastCreatedEffect
          local real x2=udg_castervars[0]
          local real y2=udg_castervars[1]
          local real speed=udg_castervars[3]

             if (speed<=522) then
                 call SetUnitMoveSpeed( m, speed)
                 call UnitMoveToAsProjectile(m, bj_meleeNearestMineDist, udg_castervars[0], udg_castervars[1], udg_castervars[2])
                 call DestroyEffect( fx)
             else
                 call UnitMoveToAsProjectileAnySpeed_Effect(m,fx,speed, bj_meleeNearestMineDist, udg_castervars[0], udg_castervars[1], null, udg_castervars[2])
             endif

             call ExplodeUnitBJ(m)

          set m=null
          set fx=null
         endfunction

         function ProjectileLaunchKill takes player owner, string modelpath, real speed, real arc, real x1, real y1, real z1, real x2, real y2, real z2 returns unit
          local unit m=CreateCaster( Atan2BJ(y2 - y1, x2 - x1),x1,y1 )


             call SetUnitFlyHeight( m, z1, 0)
             set udg_currentcaster=m
             set bj_lastCreatedEffect=AddSpecialEffectTarget( modelpath, m,"origin" )
             call SetUnitOwner( m, owner, true)
             set bj_meleeNearestMineDist = arc
             set udg_castervars[0] = x2
             set udg_castervars[1] = y2
             set udg_castervars[2] = z2
             set udg_castervars[3] = speed
             call ExecuteFunc("ProjectileLaunchKill_Child")
          set m=null
          return udg_currentcaster
         endfunction

         function ProjectileLaunchKillLoc takes player owner, string modelpath, real speed, real arc, location loc1, real z1, location loc2, real z2 returns unit
             return ProjectileLaunchKill( owner, modelpath, speed, arc, GetLocationX(loc1), GetLocationY(loc1), z1, GetLocationX(loc2), GetLocationY(loc2), z2)
         endfunction

         //====================================================================================================================================================================
         function UnitMoveToUnitAsProjectile takes unit m, real arc, unit target, real zoffset returns nothing
             call UnitMoveToAsProjectileGen(m, arc,0,0,target,zoffset)
         endfunction

         //====================================================================================================================================================================
         function ProjectileLaunchToUnitEx takes player owner, string modelpath, real scale, integer red, integer green, integer blue, integer alpha, real speed, real arc, real x1, real y1, real z1, unit target, real zoffset returns nothing
          local unit m=CreateCaster( Atan2BJ(GetUnitY(target) - y1, GetUnitX(target) - x1),x1,y1 )
          local effect fx=null

             call SetUnitFlyHeight( m, z1, 0)
             call SetUnitScale( m, scale, scale, scale)
             call SetUnitVertexColor(m, red, green, blue, alpha)
             set fx=AddSpecialEffectTarget( modelpath, m,"origin" )
             call SetUnitOwner( m , owner, true)

             if (speed<=522) then
                 call SetUnitMoveSpeed( m, speed)
                 call UnitMoveToUnitAsProjectile(m,arc,target, zoffset)
                 call DestroyEffect(fx)
             else
                 call UnitMoveToAsProjectileAnySpeed_Effect(m,fx,speed, arc,0,0,target,zoffset)
             endif

             call ExplodeUnitBJ(m)
          set m=null
          set fx=null
         endfunction

         function ProjectileLaunchToUnitExLoc takes player owner, string modelpath, real scale, integer red, integer green, integer blue, integer alpha, real speed, real arc, location loc1, real z1, unit target, real zoffset returns nothing
             call ProjectileLaunchToUnitEx( owner, modelpath, scale, red, green, blue, alpha, speed, arc, GetLocationX(loc1),GetLocationY(loc1), z1, target, zoffset)
         endfunction

         function ProjectileLaunchToUnit takes string modelpath, real speed, real arc,real x1, real y1, real z1, unit target, real zoffset returns nothing
             call ProjectileLaunchToUnitEx( Player(15), modelpath, 1, 255,255,255,255,speed,arc,x1,y1,z1,target,zoffset)
         endfunction

         function ProjectileLaunchToUnitLoc takes string modelpath, real speed, real arc, location loc1, real z1, unit target, real zoffset returns nothing
             call ProjectileLaunchToUnitExLoc( Player(15), modelpath, 1, 255,255,255,255, speed, arc, loc1, z1, target,zoffset)
         endfunction

         //====================================================================================================================================================================
         function DamagingProjectileLaunchTarget_Child takes nothing returns nothing
          local unit m=udg_currentcaster
          local unit target=bj_meleeNearestMine
          local effect fx=bj_lastCreatedEffect
          local real damage=udg_castervars[4]
          local damagetype dmgT=ConvertDamageType(R2I(udg_castervars[6]))
          local attacktype attT=ConvertAttackType(R2I(udg_castervars[5]))
          local unit hurter=udg_currenthurter
          local real speed=udg_castervars[7]
             if (speed<=522) then
                 call SetUnitMoveSpeed( m, speed)
                 call UnitMoveToUnitAsProjectile(m, bj_meleeNearestMineDist, target, udg_castervars[2])
                 call DestroyEffect( fx)
             else
                 call UnitMoveToAsProjectileAnySpeed_Effect(m,fx,speed, bj_meleeNearestMineDist,0,0,target,udg_castervars[2])
             endif

             call DamageUnitByTypes(hurter,target,damage,attT,dmgT)
             call ExplodeUnitBJ(m)
          set m=null
          set hurter=null
          set target=null
          set fx=null
          set dmgT=null
          set attT=null
         endfunction

         function DamagingProjectileLaunchTarget takes unit hurter, string modelpath, real speed, real arc, real x1, real y1, real z1, unit target, real zoffset, real damage, attacktype attT, damagetype dmgT returns unit
          local unit m=CreateCaster( Atan2BJ(GetUnitY(target) - y1, GetUnitX(target) - x1),x1,y1 )

             set udg_castervars[7]=speed
             call SetUnitFlyHeight( m, z1, 0)
             set udg_currentcaster=m
             set bj_lastCreatedEffect=AddSpecialEffectTarget( modelpath, m,"origin" )
             call SetUnitOwner( m, GetOwningPlayer(hurter), true)
             set bj_meleeNearestMineDist = arc
             set udg_castervars[2]= zoffset
             set bj_meleeNearestMine=target
             set udg_castervars[4]=damage
             set udg_castervars[5]=CS_H2I(attT)
             set udg_castervars[6]=CS_H2I(dmgT)
             set udg_currenthurter=hurter
             call ExecuteFunc("DamagingProjectileLaunchTarget_Child")
          set m=null
          return udg_currentcaster
         endfunction

         function DamagingProjectileLaunchTargetLoc takes unit hurter, string modelpath, real speed, real arc, location loc, real z1, unit target, real zoffset, real damage, attacktype attT, damagetype dmgT returns unit
             return DamagingProjectileLaunchTarget(hurter,modelpath,speed,arc,GetLocationX(loc),GetLocationY(loc), z1, target, zoffset, damage, attT, dmgT)
         endfunction

         function ProjectileLaunchToUnitDamage takes player owner, string modelpath, real speed, real arc, real x1, real y1, real z1, unit target, real zoffset, real damage returns unit
          local unit m=CreateCaster( Atan2BJ(GetUnitY(target) - y1, GetUnitX(target) - x1),x1,y1 )

             set udg_castervars[7]=speed
             call SetUnitFlyHeight( m, z1, 0)
             set udg_currentcaster=m
             set bj_lastCreatedEffect=AddSpecialEffectTarget( modelpath, m,"origin" )
             call SetUnitOwner( m, owner, true)
             set bj_meleeNearestMineDist = arc
             set udg_castervars[2]= zoffset
             set bj_meleeNearestMine=target
             set udg_castervars[4]=damage
             set udg_castervars[5]=CS_H2I(cs_DefaultAttackType)
             set udg_castervars[6]=CS_H2I(cs_DefaultDamageType)
             set udg_currenthurter=m
             call ExecuteFunc("DamagingProjectileLaunchTarget_Child")
          set m=null
          return udg_currentcaster
         endfunction

         function ProjectileLaunchToUnitDamageLoc takes player owner, string modelpath, real speed, real arc, location loc1, real z1, unit target, real zoffset, real damage returns unit
             return ProjectileLaunchToUnitDamage( owner, modelpath, speed, arc,GetLocationX(loc1),GetLocationY(loc1),z1,target,zoffset,damage)
         endfunction



        //==============================================================================================================================================================================
         // Caster System Class: CollisionMissile
         //
         function CollisionMissile_Destroy takes unit m returns nothing
          local cscollisionmissile k=GetUnitUserData(m)
         

             if (k.fx!=null) then
                 call DestroyEffect(k.fx)
                 set k.fx=null
             endif

             //For convenience, always wait for next tic to destroy the thing. But destroy the effect so
             //players don't ever notice it.
             set k.state=2
             call DisableTrigger(k.t)

         endfunction

         function CollisionMissile_Create takes string MissileModelPath, real x, real y, real dirangle, real speed, real AngleSpeed, real MaxDist,  real height, boolean UseNewCaster, real Collision, code OnImpact returns unit
          local timer t
          local cscollisionmissile k
          local trigger R

          local unit m


             set k=cscollisionmissile.create()
         
             if UseNewCaster then
                 set m=CreateCaster(dirangle,x,y)
                 set k.new=true
             else
                 set m=GetACaster()
                 call SetUnitFacing(m,dirangle)
                 call SetUnitPosition(m,CS_SafeX(x),CS_SafeY(y))
                 set k.new=false
             endif
             set cs_missilecount=cs_missilecount+1
             set cs_missiles[cs_missilecount]=k
             
             if (not cs_movementtimer_active) then  
                 call TimerStart(cs_movementtimer,cs_TIMER_CYCLE,true,function CasterSystemMovementTimer)
                 set cs_movementtimer_active=true
             endif

             call SetUnitUserData(m,k)

             set k.mtype=cs_TYPE_COLLISIONMISSILE
           
             set k.speed=speed
             set k.aspeed=AngleSpeed

             set k.f=dirangle

             set k.maxd=MaxDist

             call SetUnitFlyHeight(m,height,0)



             set R=CreateTrigger()

             set k.collision=Collision

             set k.state=1
             set k.t=R
             call SetCSData(R,k)
             
             set k.fx = AddSpecialEffectTarget(MissileModelPath,m,"origin")
             set k.m=m
             set k.ac=TriggerAddAction(R,OnImpact)

          set R=null
          set udg_currentcaster=m
          set m=null

          return udg_currentcaster
         endfunction

         function CollisionMissile_CreateLoc takes string MissileModelPath, location loc, real dirangle, real speed, real AngleSpeed, real MaxDist,  real height, boolean UseNewCaster, real Collision, code OnImpact returns unit
             return CollisionMissile_Create(MissileModelPath,GetLocationX(loc),GetLocationY(loc),dirangle,speed,AngleSpeed,MaxDist,height,UseNewCaster,Collision,OnImpact)
         endfunction
         //! CollisionMissile_CreateLoc(MissileModelPath,loc,dirangle,speed,AngleSpeed,MaxDist,height,UseNewCaster,Collision,OnImpact) CollisionMissile_Create(MissileModelPath,GetLocationX(loc),GetLocationY(loc),dirangle,speed,AngleSpeed,MaxDist,height,UseNewCaster,Collision,OnImpact)

         //=========================================================================================================================================================
         function CollisionMissile_SetAngleSpeed takes unit m, real newAspeed returns nothing
          local cscollisionmissile k=GetUnitUserData(m)
             set k.aspeed=newAspeed
         endfunction

         //=========================================================================================================================================================
         function CollisionMissile_SetSpeed takes unit m, real newspeed returns nothing
          local cscollisionmissile k=GetUnitUserData(m)
             set k.speed=newspeed
         endfunction


         //=========================================================================================================================================================
         function CollisionMissile_SetTargetPoint takes unit m, real tx, real ty returns nothing
          local cscollisionmissile k= GetUnitUserData(m)
             set k.tx=tx
             set k.ty=ty
             set k.ttype=cscollisionmissile.ttype_point
         endfunction
         function CollisionMissile_SetTargetPointLoc takes unit m, location tloc returns nothing
             call CollisionMissile_SetTargetPoint(m,GetLocationX(tloc),GetLocationY(tloc))
         endfunction

         //=========================================================================================================================================================
         function CollisionMissile_SetTarget takes unit m, widget Target returns nothing
          local cscollisionmissile k= GetUnitUserData(m)
             set k.tw=Target
             set k.ttype=cscollisionmissile.ttype_widget
         endfunction

         //=========================================================================================================================================================
         function CollisionMissile_ForgetTarget takes unit m returns nothing
             set cscollisionmissile(GetUnitUserData(m)).ttype=cscollisionmissile.ttype_none
         endfunction
         


         //=========================================================================================================================================================
         function CollisionMissile_SetDirAngle takes unit m, real f returns nothing
             set cscollisionmissile(GetUnitUserData(m)).f=f
             call SetUnitFacing(m,f)
         endfunction

         //=========================================================================================================================================================
         function CollisionMissile_ResetMaxDist takes unit m, real maxdist returns nothing
             set cscollisionmissile(GetUnitUserData(m)).maxd=maxdist
         endfunction

         //=========================================================================================================================================================
         function CollisionMissile_PeriodicFX takes unit m, string fx, real dur returns nothing
         // [1 integer state][2 trigger T][3 real collision][4 real speed][5 real F][6 real aspeed][7 integer TType]
         // [8 real Tx][9 real Ty][10 widget Tw][11 real F][12 real maxd][13 boolean pfx][14 real pfx_current][15 real pfx_dur][16 pfx_path]
         // [17 fx][18 ac][19 boolean new][20 m]

          local cscollisionmissile k= cscollisionmissile(GetUnitUserData(m))
             set k.pfx=true
             set k.pfx_path=fx
             set k.pfx_dur=dur
             set k.pfx_current=0.
         endfunction

         //=========================================================================================================================================================
         function CollisionMissile_SetTag takes unit m, integer tag returns nothing
             set cscollisionmissile(GetUnitUserData(m)).tag=tag
         endfunction

         //=========================================================================================================================================================
         function CollisionMissile_GetTag takes unit m returns integer
             return cscollisionmissile(GetUnitUserData(m)).tag
         endfunction


         //**************************************************************************************************
         //*
         //* Caster System Special Events:
         //*
         //*
         //**************************************************************************************************



         globals
             private boolean eventhandlers_passives=false
             private trigger events_probablytemp_learntrig=null
             private triggeraction events_probablytemp_learntriga=null
         endglobals

         //==================================================================================================
         // Event: OnAbilityLearn
         //
         function Event_OnLearn1 takes nothing returns nothing

          local integer s=GetLearnedSkill()
          local string k=I2S(s)
            if HaveStoredString( cs_cache, "events_onlearn",k) then
                call ExecuteFunc( GetStoredString( cs_cache, "events_onlearn",k) )
            endif

         endfunction

         function Event_OnLearn2 takes nothing returns nothing

          local integer s=GetLearnedSkill()
          local string k=I2S(s)
            if HaveStoredString( cs_cache, "events_onlearn",k) then
                call StoreInteger(cs_cache,"events_variables","unit",CS_H2I(GetTriggerUnit()))
                call StoreInteger(cs_cache,"events_variables","current",s)
                call ExecuteFunc( GetStoredString( cs_cache, "events_onlearn",k) )
            endif

         endfunction

         function InitLearnEvent takes gamecache g, integer i returns nothing
          local trigger t=CreateTrigger()
          local integer j=0
             loop
                 call TriggerRegisterPlayerUnitEvent(t, Player(j),EVENT_PLAYER_HERO_SKILL, null)
                 set j=j+1
                 exitwhen j==bj_MAX_PLAYER_SLOTS
             endloop
             if (i==1) then
                 set events_probablytemp_learntrig=t
                 set events_probablytemp_learntriga=TriggerAddAction(t, function Event_OnLearn1)
             else
                 call TriggerAddAction(t, function Event_OnLearn2)
             endif
             call StoreInteger(g,"eventhandlers","learn",i)
             
          set t=null
         endfunction

         function OnAbilityLearn takes integer abilid, string funcname returns nothing


             if (not HaveStoredInteger(cs_cache,"eventhandlers","learn")) then
                 call InitLearnEvent(cs_cache,1)
             endif

             call StoreString(cs_cache,"events_onlearn", I2S(abilid), funcname)


         endfunction

         //==================================================================================================
         // Event: OnAbilityGet
         //
         globals
             private unit acquiringunit
             private integer acquiredabil
         endglobals
         function GetAbilityAcquiringUnit takes nothing returns unit
             return acquiringunit
         endfunction

         function GetAcquiredAbilityId takes nothing returns integer
             return acquiredabil
         endfunction


         function UnitAddAbility_ConsiderEvent takes unit whichUnit, integer abilid, integer level returns nothing
          local string k=I2S(abilid)
             call UnitAddAbility(whichUnit,abilid)
             call SetUnitAbilityLevel(whichUnit,abilid,level)
             if (HaveStoredString(cs_cache,"events_onlearn",k)) then
                 set acquiringunit = whichUnit
                 set acquiredabil = abilid
                 call ExecuteFunc(GetStoredString(cs_cache,"events_onlearn",k))
             endif
         endfunction


         function Event_OnPassive_Browse takes unit u, string k returns nothing
          local integer n=GetStoredInteger(cs_cache,"events_passives","n")
          local integer un=0
          local integer i=1
          local integer s

             loop
                 exitwhen (i>n)
                 set s=GetStoredInteger(cs_cache,"events_passives",I2S(i))
                 if (GetUnitAbilityLevel(u,s)>0) then
                     if (un==0) then
                         set un=1
                         call StoreInteger(cs_cache,"events_variables","unit",CS_H2I(u))
                     else
                         set un=un+1
                     endif
                     call StoreInteger(cs_cache,"events_unit_passive"+I2S(un),k,s)
                     call StoreInteger(cs_cache,"events_variables","current",s)
                     call ExecuteFunc(GetStoredString(cs_cache,"events_onlearn",I2S(s)))
                 endif
                 set i=i+1
             endloop
             if (un==0) then
                 set un=-1
             endif
             call StoreInteger(cs_cache,"events_unit_passives",k,un)
         endfunction

         function Event_OnPassive_Do takes  unit u, string k, integer n returns nothing
          local integer i=1
          local integer s
             call StoreInteger(cs_cache,"events_variables","unit",CS_H2I(u))
             loop
                 exitwhen (i>n)
                 set s=GetStoredInteger(cs_cache,"events_unit_passive"+I2S(i),k)
                 if (GetUnitAbilityLevel(u,s)>0) then
                     call StoreInteger(cs_cache,"events_variables","current",s)
                     call ExecuteFunc(GetStoredString(cs_cache,"events_onlearn",I2S(s)))
                 endif
                 set i=i+1
             endloop
         endfunction


         function Event_OnPassive_EnterRect takes nothing returns nothing

          local unit u=GetTriggerUnit()
          local string k=I2S(GetUnitTypeId(u))
          local integer n=GetStoredInteger(cs_cache,"events_unit_passives",k)
             if (n>0) then
                 call Event_OnPassive_Do(u,k,n)
             elseif (n==0) then
                 call Event_OnPassive_Browse(u,k)
             endif      

          set u=null
         endfunction

         function Event_OnPassive_NoCasters takes nothing returns boolean
             return (GetUnitTypeId(GetTriggerUnit())!=cs_CasterUnitId)
         endfunction
         function Event_OnPassive_InitEnum takes nothing returns nothing
          local trigger t
          local integer n=GetStoredInteger(cs_cache,"events_passives","n")
          local integer i=1
          local integer array p
          local string array s
          local unit u
          local group a=NewGroup()
          local boolean saved
             call ReleaseTimer(GetExpiredTimer())
             loop
                 exitwhen (i>n)
                 set p[i]=GetStoredInteger(cs_cache,"events_passives",I2S(i))
                 set s[i]=GetStoredString(cs_cache,"events_onlearn", I2S(p[i]))
                 set i=i+1
             endloop
             call GroupEnumUnitsInRect(a,bj_mapInitialPlayableArea,null)
             loop
                 set u=FirstOfGroup(a)
                 exitwhen (u==null)
                 set i=1
                 set saved=false

                 loop
                     exitwhen (i>n)
                     if (GetUnitAbilityLevel(u,p[i])>0) then
                         if (not saved) then
                             set saved=true
                             call StoreInteger(cs_cache,"events_variables","unit",CS_H2I(u))
                         endif
                         call StoreInteger(cs_cache,"events_variables","current",p[i])
                         call ExecuteFunc(s[i])
                     endif
                     set i=i+1
                 endloop
                 call GroupRemoveUnit(a,u)
             endloop  
             set t=CreateTrigger()
             call TriggerRegisterEnterRectSimple(t,bj_mapInitialPlayableArea)
             call TriggerAddAction(t,function Event_OnPassive_EnterRect)
             call TriggerAddCondition(t,Condition(function Event_OnPassive_NoCasters))
             call ReleaseGroup(a)

          set t=null
          set a=null
         endfunction


         function InitPassiveEvent takes nothing returns nothing
          local trigger t
             call TimerStart(NewTimer(),0,false,function Event_OnPassive_InitEnum)
             set eventhandlers_passives=true

             if (not HaveStoredInteger(cs_cache,"eventhandlers","learn")) then
                 call InitLearnEvent(cs_cache,2)
             else
                 set t=events_probablytemp_learntrig
                 call TriggerRemoveAction(t,events_probablytemp_learntriga)
                 call TriggerAddAction(t, function Event_OnLearn2)
                 call StoreInteger(cs_cache,"eventhandlers","learn",2)
                set t=null
             endif
         endfunction


         function OnAbilityGet takes integer abilid, string funcname returns nothing
          local integer n=GetStoredInteger(cs_cache,"events_passives","n")+1

             if (not eventhandlers_passives) then
                 call InitPassiveEvent()
             endif

             call StoreString( cs_cache,"events_onlearn", I2S(abilid), funcname)
             call StoreInteger(cs_cache,"events_passives","n",n)
             call StoreInteger(cs_cache,"events_passives",I2S(n),abilid)  
         endfunction

         //==================================================================================================
         // Event: OnAbilityEffect
         //
         function Event_OnEffect takes nothing returns nothing
          local string k=I2S(GetSpellAbilityId())

             if HaveStoredString(cs_cache, "events_oneffect",k) then
                 call ExecuteFunc( GetStoredString(cs_cache, "events_oneffect",k))
             endif
         endfunction

         function InitEffectEvent takes gamecache g returns nothing
          local trigger t=CreateTrigger()
          local integer i = 0
             loop
                 call TriggerRegisterPlayerUnitEvent(t, Player(i),EVENT_PLAYER_UNIT_SPELL_EFFECT, null)
                 set i=i+1
                 exitwhen i==bj_MAX_PLAYER_SLOTS
             endloop
             call TriggerAddAction(t,function Event_OnEffect)
             call StoreInteger(g,"eventhandlers","effect",1)
          set t=null
         endfunction

         function OnAbilityEffect takes integer abilid, string funcname returns nothing

             if (not HaveStoredInteger(cs_cache,"eventhandlers","effect")) then
                 call InitEffectEvent(cs_cache)
             endif
             call StoreString(cs_cache,"events_oneffect",I2S(abilid),funcname)
         endfunction

         //==================================================================================================
         // Event: OnAbilityCast
         //
         function Event_OnCast takes nothing returns nothing
          local string k=I2S(GetSpellAbilityId())
             if HaveStoredString(cs_cache, "events_oncast",k) then
                 call ExecuteFunc( GetStoredString(cs_cache, "events_oncast",k))
             endif

         endfunction

         function InitCastEvent takes nothing returns nothing
          local trigger t=CreateTrigger()
          local integer i = 0
             loop
                 call TriggerRegisterPlayerUnitEvent(t, Player(i),EVENT_PLAYER_UNIT_SPELL_CAST, null)
                 set i=i+1
                 exitwhen i==bj_MAX_PLAYER_SLOTS
             endloop
             call TriggerAddAction(t,function Event_OnCast)
             call StoreInteger(cs_cache,"eventhandlers","cast",1)
          set t=null
         endfunction

         function OnAbilityPreCast takes integer abilid, string funcname returns nothing
             if (not HaveStoredInteger(cs_cache,"eventhandlers","cast")) then
                 call InitCastEvent()
             endif
             call StoreString(cs_cache,"events_oncast",I2S(abilid),funcname)
         endfunction

         //==================================================================================================
         // Event: OnAbilityEndCast
         //
         function Event_OnEndCast takes nothing returns nothing
          local string k=I2S(GetSpellAbilityId())

             if HaveStoredString(cs_cache, "events_onendcast",k) then
                 call ExecuteFunc( GetStoredString(cs_cache, "events_onendcast",k))
             endif

         endfunction

         function InitEndCastEvent takes nothing returns nothing
          local trigger t=CreateTrigger()
          local integer i = 0
             loop
                 call TriggerRegisterPlayerUnitEvent(t, Player(i),EVENT_PLAYER_UNIT_SPELL_ENDCAST, null)
                 set i=i+1
                 exitwhen i==bj_MAX_PLAYER_SLOTS
             endloop
             call TriggerAddAction(t,function Event_OnEndCast)
             call StoreInteger(cs_cache,"eventhandlers","endcast",1)
          set t=null
         endfunction

         function OnAbilityEndCast takes integer abilid, string funcname returns nothing

             if (not HaveStoredInteger(cs_cache,"eventhandlers","endcast")) then
                 call InitEndCastEvent()
             endif
             call StoreString(cs_cache,"events_onendcast",I2S(abilid),funcname)

         endfunction


         //==================================================================================================
         // Spell Helpers
         //
         function IsPointWater takes real x, real y returns boolean
             return IsTerrainPathable(x,y,PATHING_TYPE_WALKABILITY) and not(IsTerrainPathable(x,y,PATHING_TYPE_AMPHIBIOUSPATHING))
         endfunction

         function IsPointWaterLoc takes location loc returns boolean
             return IsPointWater(GetLocationX(loc),GetLocationY(loc))
         endfunction

         //==================================================================================================
         function IsUnitSpellImmune takes unit u returns boolean
             return IsUnitType(u,UNIT_TYPE_MAGIC_IMMUNE)
         endfunction

         function IsUnitImmuneToPhisical takes unit u returns boolean
             return (GetDamageFactor(u,ATTACK_TYPE_CHAOS,DAMAGE_TYPE_DEMOLITION)==0)
         endfunction

         function IsUnitInvulnerable takes unit u returns boolean
             return (GetDamageFactor(u,ATTACK_TYPE_CHAOS,DAMAGE_TYPE_UNIVERSAL)==0)
         endfunction

         //## Utility functions ##
         //====================================================================================================
         // Mimic an interface error message
         //     ForPlayer : The player to show the error
         //     msg       : The error
         //
         function CS_Error takes player ForPlayer, string msg returns nothing
          local sound error=CreateSoundFromLabel( "InterfaceError",false,false,false,10,10)
             if (GetLocalPlayer() == ForPlayer) then
                 if (msg!="") and (msg!=null) then
                     call ClearTextMessages()
                     call DisplayTimedTextToPlayer( ForPlayer, 0.52, -1.00, 2.00, "|cffffcc00"+msg+"|r" )
                 endif
                 call StartSound( error )
             endif
          call KillSoundWhenDone( error)
          set error=null
         endfunction

         //## Safe item hiding system ##
         //===============================
         // Hides an item, it keeps it safe while leaving other units unable to use it
         // (unless an (attached) variable / table field points to it and user does
         // something with it) - THIS IS HIGHLY DISCOURAGED
         //
         // * Don't use it with tomes that increase hero stats
         // * Make triggers with item acquire/lose events ignore when a
         //   Caster is triggering unit.
         //
         globals
             private group CSItemStorage_gr=null
         endglobals

         //If your map got more than 8191 items, you are crazy.
         private struct itemholder
             unit s
             item it
         endstruct

         function CS_HideItem takes item  i returns integer
          local unit s
          local group gr=CSItemStorage_gr
          local itemholder r

             if (gr==null) then
                 set gr=NewGroup()
                 set CSItemStorage_gr=gr
             endif
             set s=FirstOfGroup(gr)    
             if (s==null) then
                 set s=CreateCaster(0,0,0)
                 call UnitAddAbility(s,cs_DummyInventory_Id)
                 if (UnitInventorySize(s)<bj_MAX_INVENTORY) then
                     call  BJDebugMsg("CASTER SYSTEM ERROR: Please use a correct ability for cs_DummyInventory_Id ")
                     loop //crash the thread
                     endloop
                 endif

                 call GroupAddUnit(gr,s)
             endif
             call UnitAddItem(s,i)
             set r=itemholder.create()
             set r.it=i
             set r.s=s

             if(UnitInventorySize(s)==UnitInventoryCount(s)) then
                 call GroupRemoveUnit(gr,s)
             endif
          set s=null
          set gr=null
          return integer(r)
         endfunction


         //===============================
         // Restores an item
         //
         globals
              private item returnitem
         endglobals
         function CS_RestoreItem takes integer hiddenindex, real x, real y returns item
          local group gr=CSItemStorage_gr
          local itemholder r=itemholder(hiddenindex)
          local unit s=r.s
          local item i=r.it
          local integer c
             call r.destroy()
         
             call UnitRemoveItem(s,i)
             set c=UnitInventoryCount(s)
             if (c==0) then
                 call UnitRemoveAbility(s,cs_DummyInventory_Id)
                 call GroupRemoveUnit(gr,s)
                 call ExplodeUnitBJ(s)
             else
                 call GroupAddUnit(gr,s)
             endif
             call SetItemPosition(i,x,y)
             set returnitem=i
          set i=null
          set s=null
          return returnitem
         endfunction

         function CS_RestoreItemLoc takes integer hiddenindex, location loc returns item
             return CS_RestoreItem(hiddenindex,GetLocationX(loc),GetLocationY(loc))
         endfunction


         //=============================================================================================================
         // More convenient than CS_HideItem not compatible with CS_HideItem / CS_RestoreItem(loc)
         //
         function CS_SetItemVisible takes item it, boolean flag returns nothing
          local itemholder r
          local unit s
          local string k=I2S(CS_H2I(it))
          local group gr
          local integer x
             if (flag) then
                 if (HaveStoredInteger(cs_cache,"CSItemStorage",k )) then
                     //DO SHOW:
                     set r=itemholder(GetStoredInteger(cs_cache,"CSItemStorage",k))
                     set s=r.s
                     set gr=CSItemStorage_gr
                     if (gr==null) then
                         set gr=NewGroup()
                         set CSItemStorage_gr=gr
                     endif
                     call FlushStoredInteger(cs_cache,"CSItemStorage",k)
                     call UnitRemoveItem(s,it)
                     call SetItemVisible(it,true) //Just in case
                     set x=GetUnitUserData(s)-1
                     if (x==0) then
                         call UnitRemoveAbility(s,cs_DummyInventory_Id)
                         call GroupRemoveUnit(gr,s)
                         call ExplodeUnitBJ(s)
                     else
                         call SetUnitUserData(s,x)
                         call GroupAddUnit(gr,s)
                     endif
                     call r.destroy()
                    set s=null
                    set gr=null
                 else //What? Trying to show an item that was not hidden using this method?
                 endif
                 

             elseif (HaveStoredInteger(cs_cache,"CSItemStorage",k )) then
                 //What? Trying to hide an item that was already hidden by this method?

             else //DO HIDE:
                 set gr=CSItemStorage_gr
                 if (gr==null) then
                     set gr=NewGroup()
                     set CSItemStorage_gr=gr
                 endif
                 set s=FirstOfGroup(gr)
                 
                 if (s==null) then
                     set s=CreateCaster(0,0,0)
                     call UnitAddAbility(s,cs_DummyInventory_Id)
                     if (UnitInventorySize(s)<bj_MAX_INVENTORY) then
                         call  BJDebugMsg("CASTER SYSTEM ERROR: Please use a correct ability for cs_DummyInventory_Id ")
                         set x=x
                     endif
                     call SetUnitUserData(s,0) //UserData will now hold total items
                     call GroupAddUnit(gr,s)
                 endif
                 call UnitAddItem(s,it)
                 set r=itemholder.create()
                 set r.s=s
                 set r.it=it
                 call StoreInteger(cs_cache,"CSItemStorage",k,integer(r))
                 set x=GetUnitUserData(s)+1
                 call SetUnitUserData(s,x)
                 if (x==bj_MAX_INVENTORY) then
                     call GroupRemoveUnit(gr,s)
                 endif
              set s=null
              set gr=null
             endif
         endfunction

         function CS_IsItemVisible takes item it returns boolean
            return not HaveStoredInteger(cs_cache,"CSItemStorage",I2S(CS_H2I(it)) )
         endfunction


         //=============================================================================================================
         // Obsolette functions: (Left for compatibility)
         //
         constant function WaterDetectorId takes nothing returns integer
         return 'Asb2'
         endfunction
         function SpellEffectModelPath takes integer abilityid, effecttype t returns string
         return GetAbilityEffectById(abilityid,t, 0)
         endfunction
         constant function Caster_DefaultAttackType takes nothing returns attacktype
         return cs_DefaultAttackType
         endfunction
         constant function Caster_DefaultDamageType takes nothing returns damagetype
         return cs_DefaultDamageType
         endfunction
         constant function Caster_UnitId takes nothing returns integer
         return cs_CasterUnitId
         endfunction
         constant function DamageTreeDetectorId takes nothing returns integer
         return cs_DamageTreeDetectorId
         endfunction
         constant function ChangeableFlyingHeightAllowerId takes nothing returns integer
         return cs_FlyingHeightHack
         endfunction
         constant function CS_MaxCollisionSize takes nothing returns real
         return cs_MaxUnitCollisionSize
         endfunction
         constant function CS_Cycle takes nothing returns real
         return cs_TIMER_CYCLE
         endfunction
         constant function CS_InventoryId takes nothing returns integer
         return cs_DummyInventory_Id
         endfunction
         constant function CS_RectLimitOffSet takes nothing returns real
         return cs_RectLimitOffSet
         endfunction
         function CS_IsUnitVisible takes unit u, player p returns boolean
              return IsUnitVisible(u,p)
         endfunction

    endlibrary