Chain Create System

Dirac

22710180
Reaction score
147
Hello guys i present you the chain system (requires T32) a system that creates a chain between 2 points

static method create takes unit source, unit target, string fx, real rate returns thistype

The problem is, it causes a lot of lag after a while, also that it's array size is HUGE so it can sustain more than 8 instances at the time. Help me fix it
JASS:
library Chain uses T32
    globals
        private timer TIMER = CreateTimer()
        private constant real TIMEOUT = 0.03125
        private integer DUMMY = 'h000'
    endglobals
    
    struct chain
        unit target
        real rate
        string fx
        unit array shackle[1000]
        effect array shacklefx[1000]
        integer shacklecount
        real sourceheight
        real targetheight
        integer list
        
        private method periodic takes nothing returns nothing
            local real array x
            local real array y
            local real a
            local integer i = 2
            set x[0] = GetUnitX(.shackle[.shacklecount])
            set y[0] = GetUnitY(.shackle[.shacklecount])
            set x[1] = GetUnitX(.shackle[.shacklecount+1])
            set y[1] = GetUnitY(.shackle[.shacklecount+1])
            //This is the part where shackles are created if the last one is separated from the caster
            loop
                exitwhen .rate > SquareRoot((x[1]-x[0])*(x[1]-x[0])+(y[1]-y[0])*(y[1]-y[0]))
                set a = Atan2(y[0]-y[1],x[0]-x[1])
                set .shacklecount = .shacklecount+1
                set .shackle[.shacklecount+1]= .shackle[.shacklecount]
                set .shackle[.shacklecount] = CreateUnit(GetOwningPlayer(.shackle[.shacklecount+1]),DUMMY,x[0]-.rate*Cos(a),y[0]-.rate*Sin(a),bj_RADTODEG*a)
                set .shacklefx[.shacklecount] = AddSpecialEffectTarget(.fx,.shackle[.shacklecount],"origin")
                set x[0] = GetUnitX(.shackle[.shacklecount])
                set y[0] = GetUnitY(.shackle[.shacklecount])
            endloop
            //This is where shackles are moved depending on the one that follows them in the chain. All but the first one
            loop
                exitwhen i > .shacklecount
                set x[2] = GetUnitX(.shackle<i>)
                set y[2] = GetUnitY(.shackle<i>)
                set x[3] = GetUnitX(.shackle[i-1])
                set y[3] = GetUnitY(.shackle[i-1])
                set a = Atan2(y[3]-y[2],x[3]-x[2])
                call SetUnitX(.shackle<i>,x[2]+(SquareRoot((x[2]-x[3])*(x[2]-x[3])+(y[2]-y[3])*(y[2]-y[3]))-.rate)*Cos(a))
                call SetUnitY(.shackle<i>,y[2]+(SquareRoot((x[2]-x[3])*(x[2]-x[3])+(y[2]-y[3])*(y[2]-y[3]))-.rate)*Sin(a))
                call SetUnitFacing(.shackle<i>,bj_RADTODEG*a)
                call UnitAddAbility(.shackle<i>,&#039;Amrf&#039;)
                call SetUnitFlyHeight(.shackle<i>,(((.sourceheight-.targetheight)*(i-1))/(.shacklecount-1))+.targetheight,0.)
                call UnitRemoveAbility(.shackle<i>,&#039;Amrf&#039;)
                set i = i+1
            endloop
            //The first shackle moves depending to the target&#039;s location
            set x[4] = GetUnitX(.shackle[1])
            set y[4] = GetUnitY(.shackle[1])
            set x[5] = GetUnitX(.target)
            set y[5] = GetUnitY(.target)
            set a = Atan2(y[4]-y[5],x[4]-x[5])
            call SetUnitX(.shackle[1],x[5]+.rate*Cos(a))
            call SetUnitY(.shackle[1],y[5]+.rate*Sin(a))
             call SetUnitFacing(.shackle[1],180+bj_RADTODEG*a)
        endmethod
        
        implement T32x
        
        method SetSourceHeight takes real a returns nothing
            set .sourceheight = a
        endmethod
        
        method SetTargetHeight takes real a returns nothing
            set .targetheight = a
        endmethod
        
        method destroy takes nothing returns nothing
            local integer i = 1
            loop
                exitwhen i &gt; .shacklecount
                call DestroyEffect(.shacklefx<i>)
                call RemoveUnit(.shackle<i>)
                set i = i+1
            endloop
            set .shacklecount = 0
            call .deallocate()
        endmethod
        
        static method create takes unit source, unit target, string fx, real rate returns thistype
            local thistype this = thistype.allocate()
            local real a = Atan2(GetUnitY(target)-GetUnitY(source),GetUnitX(target)-GetUnitX(source))
            set this.shacklecount = 1
            set this.shackle[this.shacklecount+1] = source
            set this.target = target
            set this.rate = rate
            set this.fx = fx
            set this.sourceheight = 50.
            set this.targetheight = 50.
            set this.shackle[this.shacklecount] = CreateUnit(GetOwningPlayer(source),DUMMY,GetUnitX(target)-rate*Cos(a),GetUnitY(target)-rate*Sin(a),a*bj_RADTODEG)
            set this.shacklefx[this.shacklecount] = AddSpecialEffectTarget(fx,this.shackle[this.shacklecount],&quot;origin&quot;)
            call UnitAddAbility(this.shackle[this.shacklecount],&#039;Amrf&#039;)
            call SetUnitFlyHeight(this.shackle[this.shacklecount],this.targetheight,0.)
            call UnitRemoveAbility(this.shackle[this.shacklecount],&#039;Amrf&#039;)
            call this.startPeriodic()
            return this
        endmethod
    endstruct
endlibrary</i></i></i></i></i></i></i></i></i></i>


Non T32 version
JASS:
library Chain
    globals
        private timer TIMER = CreateTimer()
        private constant real TIMEOUT = 0.03125
        private integer array DATA
        private integer DATACOUNT = 0
        private integer DUMMY = &#039;h000&#039;
    endglobals
    
    struct chain
        unit target
        real rate
        string fx
        unit array shackle[1000]
        effect array shacklefx[1000]
        integer shacklecount
        real sourceheight
        real targetheight
        integer list
        
        private method periodic takes nothing returns nothing
            local real array x
            local real array y
            local real a
            local integer i = 2
            set x[0] = GetUnitX(.shackle[.shacklecount])
            set y[0] = GetUnitY(.shackle[.shacklecount])
            set x[1] = GetUnitX(.shackle[.shacklecount+1])
            set y[1] = GetUnitY(.shackle[.shacklecount+1])
            //This is the part where shackles are created if the last one is separated from the caster
            loop
                exitwhen .rate &gt; SquareRoot((x[1]-x[0])*(x[1]-x[0])+(y[1]-y[0])*(y[1]-y[0]))
                set a = Atan2(y[0]-y[1],x[0]-x[1])
                set .shacklecount = .shacklecount+1
                set .shackle[.shacklecount+1]= .shackle[.shacklecount]
                set .shackle[.shacklecount] = CreateUnit(GetOwningPlayer(.shackle[.shacklecount+1]),DUMMY,x[0]-.rate*Cos(a),y[0]-.rate*Sin(a),bj_RADTODEG*a)
                set .shacklefx[.shacklecount] = AddSpecialEffectTarget(.fx,.shackle[.shacklecount],&quot;origin&quot;)
                set x[0] = GetUnitX(.shackle[.shacklecount])
                set y[0] = GetUnitY(.shackle[.shacklecount])
            endloop
            //This is where shackles are moved depending on the one that follows them in the chain. All but the first one
            loop
                exitwhen i &gt; .shacklecount
                set x[2] = GetUnitX(.shackle<i>)
                set y[2] = GetUnitY(.shackle<i>)
                set x[3] = GetUnitX(.shackle[i-1])
                set y[3] = GetUnitY(.shackle[i-1])
                set a = Atan2(y[3]-y[2],x[3]-x[2])
                call SetUnitX(.shackle<i>,x[2]+(SquareRoot((x[2]-x[3])*(x[2]-x[3])+(y[2]-y[3])*(y[2]-y[3]))-.rate)*Cos(a))
                call SetUnitY(.shackle<i>,y[2]+(SquareRoot((x[2]-x[3])*(x[2]-x[3])+(y[2]-y[3])*(y[2]-y[3]))-.rate)*Sin(a))
                call SetUnitFacing(.shackle<i>,bj_RADTODEG*a)
                call UnitAddAbility(.shackle<i>,&#039;Amrf&#039;)
                call SetUnitFlyHeight(.shackle<i>,(((.sourceheight-.targetheight)*(i-1))/(.shacklecount-1))+.targetheight,0.)
                call UnitRemoveAbility(.shackle<i>,&#039;Amrf&#039;)
                set i = i+1
            endloop
            //The first shackle moves depending to the target&#039;s location
            set x[4] = GetUnitX(.shackle[1])
            set y[4] = GetUnitY(.shackle[1])
            set x[5] = GetUnitX(.target)
            set y[5] = GetUnitY(.target)
            set a = Atan2(y[4]-y[5],x[4]-x[5])
            call SetUnitX(.shackle[1],x[5]+.rate*Cos(a))
            call SetUnitY(.shackle[1],y[5]+.rate*Sin(a))
             call SetUnitFacing(.shackle[1],180+bj_RADTODEG*a)
        endmethod
        
        private static method iterate takes nothing returns nothing
            local integer i = 1
            local chain d
            loop
                exitwhen i &gt; DATACOUNT
                set d = DATA<i>
                call d.periodic()
                set i = i+1
            endloop
        endmethod
        
        method SetSourceHeight takes real a returns nothing
            set .sourceheight = a
        endmethod
        
        method SetTargetHeight takes real a returns nothing
            set .targetheight = a
        endmethod
        
        method destroy takes nothing returns nothing
            local integer i = 1
            loop
                exitwhen i &gt; .shacklecount
                call DestroyEffect(.shacklefx<i>)
                call RemoveUnit(.shackle<i>)
                set i = i+1
            endloop
            set .shacklecount = 0
            set DATA[.list] = DATA[DATACOUNT]
            set DATACOUNT = DATACOUNT - 1
            call .deallocate()
        endmethod
        
        static method create takes unit source, unit target, string fx, real rate returns thistype
            local thistype this = thistype.allocate()
            local real a = Atan2(GetUnitY(target)-GetUnitY(source),GetUnitX(target)-GetUnitX(source))
            set this.shacklecount = 1
            set this.shackle[this.shacklecount+1] = source
            set this.target = target
            set this.rate = rate
            set this.fx = fx
            set this.sourceheight = 50.
            set this.targetheight = 50.
            set this.shackle[this.shacklecount] = CreateUnit(GetOwningPlayer(source),DUMMY,GetUnitX(target)-rate*Cos(a),GetUnitY(target)-rate*Sin(a),a*bj_RADTODEG)
            set this.shacklefx[this.shacklecount] = AddSpecialEffectTarget(fx,this.shackle[this.shacklecount],&quot;origin&quot;)
            call UnitAddAbility(this.shackle[this.shacklecount],&#039;Amrf&#039;)
            call SetUnitFlyHeight(this.shackle[this.shacklecount],this.targetheight,0.)
            call UnitRemoveAbility(this.shackle[this.shacklecount],&#039;Amrf&#039;)
            set DATACOUNT = DATACOUNT+1
            set DATA[DATACOUNT] = this
            set this.list = DATACOUNT
            if DATACOUNT == 1 then
                call TimerStart(TIMER,TIMEOUT,true,function chain.iterate)
            endif
            return this
        endmethod
    endstruct
endlibrary</i></i></i></i></i></i></i></i></i></i></i>
 

tooltiperror

Super Moderator
Reaction score
231
>you might need to use the timedloop system rather than t32
And might I ask why?
 

Dirac

22710180
Reaction score
147
There is no example code, i'm just complaining that my system causes a lot of lag.

Also, setting the array size to 1000 inside the struct causes obviously lots of problems, what would be the optimal way to trigger it? What i need is to store +1000 units per struct instance and one special effect per unit
 

Narks

Vastly intelligent whale-like being from the stars
Reaction score
90
1000 units? no wonder it lags
 

kingkingyyk3

Visitor (Welcome to the Jungle, Baby!)
Reaction score
216
:D ?
JASS:

//+-------------------------------------------------------------+
//|                                           v1.02             | 
//|    CHAIN by Kingkingyk3                                     |
//|                                                             |
//+-------------------------------------------------------------+
//|
//|   local Chain d = Chain.create()
//|   call d.AddChainEx( x1, y1, z1, x2, y2, z2, chainDist )
//|   call d.MoveChainEx( x1, y1, z1, x2, y2, z2, chainDist )
//|   call d.terminate()
//|
//|   set d.modelPath = &quot;modelPath&quot;
//|  
//+--------------------------------------------------------------+
library Chain requires xefx
    
    // x
    // d - distance
    // h - z1
    // m - z2 

    struct Chain
        xefx fx
        private effect eff
        private thistype prev
        private thistype next
        private integer count
        string path
        real scale
        real gapSize
        
        static method create takes nothing returns thistype
            local thistype this = .allocate()
            set this.prev = this
            set this.next = this
            return this
        endmethod
        
        method AddChainEx takes real x1, real y1, real z1, real x2, real y2, real z2, real gapSize returns nothing
            local real dx = x2 - x1
            local real dy = y2 - y1
            local real angle
            local real dist
            local integer tick
            local thistype new
            local real range
            local real x
            local real y
            local real height
            local real heighti 
            
            if dx+dy == 0. or gapSize &lt;= 0. then
                return
            endif
            
            set angle = Atan2(dy,dx)
            set dist = SquareRoot(dx * dx + dy * dy)
            set tick = R2I(dist / gapSize)
            if tick == 0 then
                return
            endif
            set height = z2
            set heighti = (z2 - z1) / tick
            
            set .count = tick
            
            loop
            exitwhen tick == 0
                set new = thistype.create()
                
                set this.prev.next = new
                set new.prev = this.prev
                set new.next = this
                set this.prev = new
                
                set .gapSize = gapSize
                
                set range = gapSize * tick
                set x = x1 + range * Cos(angle)
                set y = y1 + range * Sin(angle)
                set height = height - heighti
                
                set new.fx = xefx.create(x,y,angle)
                set new.fx.fxpath = .path
                set new.fx.scale  = .scale
                set new.fx.z = height
                
                set tick = tick - 1
            endloop
        endmethod

        method MoveChainEx takes real x1, real y1, real z1, real x2, real y2, real z2 returns nothing
            local real dx = x2 - x1
            local real dy = y2 - y1
            local real angle
            local real dist
            local integer tick
            local thistype origin = this
            local real range
            local real x
            local real y
            local integer extend
            local thistype new
            local real height
            local real heighti

            if dx+dy == 0. or gapSize &lt;= 0. then
                return
            endif
            
            set angle = Atan2(dy,dx)
            set dist = SquareRoot(dx * dx + dy * dy)
            set tick = R2I(dist / gapSize)
            if tick == 0 then
                return
            endif
            set height = z2
            set heighti = (z2 - z1) / tick
            
            loop
                set this = this.next
            exitwhen this == origin
                set tick = tick - 1
                set range = origin.gapSize * tick
                
                set x = x1 + range * Cos(angle)
                set y = y1 + range * Sin(angle)
                set height = height - heighti
                
                set .fx.x = x
                set .fx.y = y
                set .fx.xyangle = angle
                set .fx.z = height
                set .fx.zangle = Atan2( z2-z1, dist )

            endloop
            
            if tick &gt; 0 then
                loop
                exitwhen tick == 0
                    set new = thistype.create()
                    
                    set this.prev.next = new
                    set new.prev = this.prev
                    set new.next = this
                    set this.prev = new
                    
                    set range = origin.gapSize * tick
                    set x = x1 + range * Cos(angle)
                    set y = y1 + range * Sin(angle)
                    set height = height - heighti
                    
                    set new.fx = xefx.create(x,y,angle)
                    set new.fx.fxpath = .path
                    set new.fx.z = height
                    
                    set tick = tick - 1
                    set .count = .count + 1
                endloop
            elseif tick &lt; 0 then
                set tick = -tick
                set this = origin
                loop
                    set this = this.prev
                exitwhen tick == 0
                    set this.next.prev = this.prev
                    set this.prev.next = this.next
                    call .fx.hiddenDestroy()
                    call .deallocate()
                    set origin.count = origin.count - 1
                    set tick = tick - 1
                endloop
            endif
        endmethod
        
        method terminate takes nothing returns nothing
            local thistype origin = this
            loop
                set this = this.next
            exitwhen this == origin
                call .fx.destroy()
                call .deallocate()
            endloop
            call .deallocate()
        endmethod
        
        method operator modelPath= takes string s returns nothing
            local thistype origin = this
            loop
                set this = this.next
                exitwhen this == origin
                set .fx.fxpath = s
            endloop
            set .path = s
        endmethod
        
        method operator modelScale= takes real newScale returns nothing
            local thistype origin = this
            loop
                set this = this.next
                exitwhen this == origin
                set this.fx.scale = newScale
            endloop
            set this.scale = newScale
        endmethod
    endstruct
    
    
endlibrary
 

Dirac

22710180
Reaction score
147
thanks for the system king. You forgot to mention that you must set d.modelSize to 1. or the chain wont be visible, also the d.MoveChainEx dosn't take chainDist for a value. I modified it so it would
 

kingkingyyk3

Visitor (Welcome to the Jungle, Baby!)
Reaction score
216
Just modify it as you wish.
The system is rather old, as I wrote it long time ago.
 
General chit-chat
Help Users
  • No one is chatting at the moment.

      The Helper Discord

      Members online

      No members online now.

      Affiliates

      Hive Workshop NUON Dome World Editor Tutorials

      Network Sponsors

      Apex Steel Pipe - Buys and sells Steel Pipe.
      Top