Weird Syntax Error

wraithseeker

Tired.
Reaction score
122
JASS:


library Knockback initializer Init requires DestructableLib, IsTerrainWalkable, GroupUtils, PUI

globals
    private constant real    TIME         = 0.03                     // The timer interval.
    private constant real    CHAINRADIUS  = 100.00                   // The radius a unit can get chained when near the unit target.
    private constant real    SPEEDFACTOR  = 0.75                     // How much speed will be reduced when a unit chains another unit.
    private constant real    RADIUS       = 128.00                   // The radius to check tree.
    private constant real    HEIGHTLEVEL  = 200.00                   // The default height level that stops chaining or killing trees when in the air.
    private constant real    FACTOR       = 0.3333                   // Or 0.25 for smoothness.
    private constant string  GROUND       = "MDX\\Dust.mdx"          // The effect for ground.
    private constant string  WATER        = "MDX\\SlideWater.mdx"    // The effect for water.
    private constant string  COLLISION    = "MDX\\DustAndRocks.mdx"  // The effect when at cliff
    private constant string  FLYING       = "MDX\\TornadoMissile.mdx"// The effect when flying
    private constant string  ATTACHPOINT  = "origin"                 // The attachment point for effects
endglobals

globals
    private constant integer INVULNERABLE   = 'Avul'               
    private constant integer FLYID          = 'Amrf' 
    private rect     TreeRect               = null
    private boolexpr TreeCheck              = null
    private boolexpr ChainFilter            = null
    private unit     Target                 = null
    private unit     Source                 = null
    private real MapMaxX                    = 0
    private real MapMaxY                    = 0
    private real MapMinX                    = 0
    private real MapMinY                    = 0
    private Knock D
endglobals

private function CheckTrees takes nothing returns boolean
    return IsDestructableTree(GetFilterDestructable())
endfunction

private function Trees takes nothing returns nothing
    call KillDestructable(GetEnumDestructable())
endfunction

private function ChainCheck takes nothing returns boolean
    return Target != GetFilterUnit() and IsUnitEnemy(GetFilterUnit(),GetOwningPlayer(Source)) and IsUnitType(GetFilterUnit(), UNIT_TYPE_GROUND) == true and IsUnitType(GetFilterUnit(), UNIT_TYPE_MECHANICAL) == false and GetWidgetLife(GetFilterUnit()) > 0.405 and GetUnitAbilityLevel(GetFilterUnit(),INVULNERABLE) <= 0
endfunction

function ParabolaZ takes real h, real d, real x returns real
  return (4 * h / d) * (d - x) * (x / d)
endfunction

private function IsPointOutside takes real x, real y returns boolean
    return (x > MapMaxX or y > MapMaxY or x < MapMinX or y < MapMinY)
endfunction

public struct Knock
    private static timer Timer = CreateTimer()
    private static Knock array D
    private static integer Count = 0
 //! runtextmacro PUI()
    unit        source          = null
    unit        target          = null
    integer     mode            = 0
    group       hit             = null
    real        cos             = 0
    real        sin             = 0 
    real        speed           = 0
    real        decrement       = 0
    real        distance        = 0
    real        positionZ       = 0
    effect      effects         = null
    boolean     terrain         = false
    boolean     trees           = false
    boolean     chain           = false
    boolean     fly             = false
    
   private method TerrainCheck takes nothing returns integer
        local real x = GetUnitX(.target)
        local real y = GetUnitY(.target)
    
        if IsTerrainWalkable(x + 50.00 * .cos,y + 50.00 * .sin) == false then
            return 3
        else
            if IsTerrainPathable(x,y,PATHING_TYPE_FLOATABILITY) then
                return 1
            elseif not IsTerrainPathable(x,y,PATHING_TYPE_WALKABILITY) then
                return 2
            endif
        endif 
        
        return 0
    endmethod
        
static method create takes unit source, unit target, real angle, real speed, real decrement, boolean tree,boolean chain, boolean fly returns Knock
    local Knock d = Knock.allocate()
    if target == null or source == null or speed == null or decrement == null then
        debug call BJDebugMsg("Invalid Values!")
        call d.destroy()
    endif
    set d.source        = source
    set d.target        = target
    set d.trees         = tree
    set d.fly           = fly
    set d.chain         = chain
    set d.hit           = NewGroup()
    set d.speed         = speed * TIME
    set d.decrement     = decrement * TIME
    set d.sin           = Sin(angle)
    set d.cos           = Cos(angle)
    set d.distance      = -1 * speed * speed / (2 * -decrement / TIME)
    set d.positionZ     = 0
    
    if d.fly then
        call SetUnitPathing(d.target,false)
        call UnitAddAbility(d.target,FLYID)
        call UnitRemoveAbility(d.target,FLYID)
        set d.effects = AddSpecialEffectTarget(FLYING,d.target,ATTACHPOINT)
    endif
    
    set d.mode = d.TerrainCheck()
    if d.mode == 1 then
        set d.effects = AddSpecialEffectTarget(GROUND,d.target,ATTACHPOINT)
    elseif d.mode == 2 then
        set d.effects = AddSpecialEffectTarget(WATER,d.target,ATTACHPOINT)
    elseif d.mode == 3 then
        set d.effects = AddSpecialEffectTarget(COLLISION,d.target,ATTACHPOINT)
    endif
    set Knock[target] = d
    if Knock.Count == 0 then
        call TimerStart(Knock.Timer,TIME,true,Knock.Periodic)
    endif
    set Knock.D[Knock.Count] = d
    set Knock.Count = Knock.Count + 1
    return d
    endmethod
    
private method onDestroy takes nothing returns nothing
    call DestroyEffect(.effects)
    call ReleaseGroup(.hit)
    call SetUnitFlyHeight(.target,0,0)
    call SetUnitPathing(.target,true)
endmethod
        
private method action takes nothing returns boolean
    local unit    t    = null
    local real    x    = 0.00
    local real    y    = 0.00
    local real    cx   = 0.00
    local real    cy   = 0.00
    local integer mode = 0
    local Knock d
    set mode = .mode
    set x = GetUnitX(.target)
    set y = GetUnitY(.target)
    set height = GetUnitFlyHeight(.target)
    set .positionZ = .positionZ + .speed
        
    if height >= HEIGHTLEVEL then
        set .chain = false
        set .trees = false
    endif
        
    if .speed <= 0 or IsPointOutside(x,y) then
        return true
    endif
    
    if .trees then
        call SetRect(TreeRect,x-RADIUS,y-RADIUS,x+RADIUS,y+RADIUS)
        call EnumDestructablesInRect(TreeRect,TreeCheck,function Trees)
    endif
        
    if .fly then
        call SetUnitFlyHeight(.target,ParabolaZ(FACTOR*.distance,.distance,.positionZ),0)
    endif
        
    set .mode = .TerrainCheck()
    if .mode == 1 and (mode == 2 or mode == 3) then
        call DestroyEffect(.effects)
        set .effects = AddSpecialEffectTarget(GROUND,.target,ATTACHPOINT)
    elseif .mode == 2 and (mode == 1 or mode == 3) then
        call DestroyEffect(.effects)
        set .effects = AddSpecialEffectTarget(WATER,.target,ATTACHPOINT)
    elseif .mode == 3 and (mode == 1 or mode == 2) then
        call DestroyEffect(.effects)
        set .effects = AddSpecialEffectTarget(COLLISION,.target,ATTACHPOINT)
    endif
        
    if .chain == true then
        call GroupEnumUnitsInRange(ENUM_GROUP,x,y,CHAINRADIUS,ChainFilter)
        loop
            set t = FirstOfGroup(ENUM_GROUP)
            exitwhen t == null
            if not IsUnitInGroup(t,.hit) then
                set cx = GetUnitX(t)
                set cy = GetUnitY(t)
                call GroupAddUnit(.hit,t)
                set d = Knock.create(.source,t,Atan2(cy-y,cx-x),(.speed/TIME)*SPEEDFACTOR,(.decrement/TIME),.trees,.chain,.fly)
                call GroupAddUnit(.hit,.target)
                set .D[.Count] = d
                set .Count = .Count + 1
            endif
            call GroupRemoveUnit(ENUM_GROUP,t)
        endloop
endmethod
    
private method Periodic takes nothing returns nothing
    local integer i = 0
    loop
        exitwhen i < 0
        if .D<i>.actions() then
            set .Count = .Count - 1
            if .Count &gt; 0 then
                set .D<i> = .D[.Count]
                set i = i - 1
            else
                call PauseTimer(.Timer)
        endif
        set i = i + 1
        endloop
endmethod

endstruct

function KnockbackStop takes unit target returns boolean
    local Knock d = Knock[target]
    if d != 0 then
        call d.release()
        set Knock.Count = Knock.Count - 1
        if Knock.Count &gt; 0 then
             set Knocker<i> = Knocker[Count]
        else
            call PauseTimer(Knock.Timer)
        endif
        return true
    endif
    return false
endfunction

function IsKnockedBack takes unit target returns boolean
    return Knock[target] != 0
endfunction

private function Init takes nothing returns nothing
    set Timer       = CreateTimer()
    set TreeRect    = Rect(0.00,0.00,1.00,1.00)
    set TreeCheck   = Filter(function CheckTrees)
    set ChainFilter = Filter(function ChainCheck)
    set MapMaxX     = GetRectMaxX(bj_mapInitialPlayableArea)
    set MapMaxY     = GetRectMaxY(bj_mapInitialPlayableArea)
    set MapMinX     = GetRectMinX(bj_mapInitialPlayableArea)
    set MapMinY     = GetRectMinY(bj_mapInitialPlayableArea)     
endfunction

endlibrary</i></i></i>


The one highlighted gives a syntax error saying D is not a member of my struct.

JASS:
set .D[.Count] = this


Any clues?
 

Tom Jones

N/A
Reaction score
437
Private members can only be accessed inside the struct they are declared. I'm guessing you're extending a struct to the knock type and expecting to be able to use D?
 

wraithseeker

Tired.
Reaction score
122
Let me update the code although I don't understand what you're talking though.

Problem is still the same issue.
 

Flare

Stops copies me!
Reaction score
662
Let me update the code although I don't understand what you're talking though.

Problem is still the same issue.
Count is a private member of the struct, it can only be set/referenced from within the struct (child structs can't reference the parent's private members either AFAIK), much the same as private members of a scope/library cannot be accessed from outside that scope or library
 

wraithseeker

Tired.
Reaction score
122
It wouldn't affect it, I am not extending something currently.

Update

JASS:




library Knockback initializer Init requires DestructableLib, IsTerrainWalkable, GroupUtils, PUI

globals
    private constant real    TIME         = 0.03                     // The timer interval.
    private constant real    CHAINRADIUS  = 100.00                   // The radius a unit can get chained when near the unit target.
    private constant real    SPEEDFACTOR  = 0.75                     // How much speed will be reduced when a unit chains another unit.
    private constant real    RADIUS       = 128.00                   // The radius to check tree.
    private constant real    HEIGHTLEVEL  = 200.00                   // The default height level that stops chaining or killing trees when in the air.
    private constant real    FACTOR       = 0.3333                   // Or 0.25 for smoothness.
    private constant string  GROUND       = &quot;MDX\\Dust.mdx&quot;          // The effect for ground.
    private constant string  WATER        = &quot;MDX\\SlideWater.mdx&quot;    // The effect for water.
    private constant string  COLLISION    = &quot;MDX\\DustAndRocks.mdx&quot;  // The effect when at cliff
    private constant string  FLYING       = &quot;MDX\\TornadoMissile.mdx&quot;// The effect when flying
    private constant string  ATTACHPOINT  = &quot;origin&quot;                 // The attachment point for effects
endglobals

globals
    private constant integer INVULNERABLE   = &#039;Avul&#039;               
    private constant integer FLYID          = &#039;Amrf&#039; 
    private rect     TreeRect               = null
    private boolexpr TreeCheck              = null
    private boolexpr ChainFilter            = null
    private unit     Target                 = null
    private unit     Source                 = null
    private real MapMaxX                    = 0
    private real MapMaxY                    = 0
    private real MapMinX                    = 0
    private real MapMinY                    = 0
    private Knock D
endglobals

private function CheckTrees takes nothing returns boolean
    return IsDestructableTree(GetFilterDestructable())
endfunction

private function Trees takes nothing returns nothing
    call KillDestructable(GetEnumDestructable())
endfunction

private function ChainCheck takes nothing returns boolean
    return Target != GetFilterUnit() and IsUnitEnemy(GetFilterUnit(),GetOwningPlayer(Source)) and IsUnitType(GetFilterUnit(), UNIT_TYPE_GROUND) == true and IsUnitType(GetFilterUnit(), UNIT_TYPE_MECHANICAL) == false and GetWidgetLife(GetFilterUnit()) &gt; 0.405 and GetUnitAbilityLevel(GetFilterUnit(),INVULNERABLE) &lt;= 0
endfunction

function ParabolaZ takes real h, real d, real x returns real
  return (4 * h / d) * (d - x) * (x / d)
endfunction

private function IsPointOutside takes real x, real y returns boolean
    return (x &gt; MapMaxX or y &gt; MapMaxY or x &lt; MapMinX or y &lt; MapMinY)
endfunction

struct Knock
 //! runtextmacro PUI()
    private static timer Timer = CreateTimer()
    private static Knock array D
    private static integer Count = 0
    unit        source          = null
    unit        target          = null
    integer     mode            = 0
    group       hit             = null
    real        cos             = 0
    real        sin             = 0 
    real        speed           = 0
    real        decrement       = 0
    real        distance        = 0
    real        positionZ       = 0
    effect      effects         = null
    boolean     terrain         = false
    boolean     trees           = false
    boolean     chain           = false
    boolean     fly             = false
    
   private method TerrainCheck takes nothing returns integer
        local real x = GetUnitX(.target)
        local real y = GetUnitY(.target)
    
        if IsTerrainWalkable(x + 50.00 * .cos,y + 50.00 * .sin) == false then
            return 3
        else
            if IsTerrainPathable(x,y,PATHING_TYPE_FLOATABILITY) then
                return 1
            elseif not IsTerrainPathable(x,y,PATHING_TYPE_WALKABILITY) then
                return 2
            endif
        endif 
        
        return 0
    endmethod
    
    
method KnockbackStop takes unit target returns boolean
    local Knock d = Knock[target]
    local integer i = Knock.Count - 1
    if d != 0 then
        call d.release()
        if Knock.Count &gt; 0 then
             set Knock.D<i> = Knock.D[Knock.Count]
        else
            call PauseTimer(Knock.Timer)
        endif
        return true
    endif
    return false
endmethod
        
static method create takes unit source, unit target, real angle, real speed, real decrement, boolean tree,boolean chain, boolean fly returns Knock
    local Knock d = Knock.allocate()
    if target == null or source == null or speed == 0.00 or decrement == 0.00 then
        debug call BJDebugMsg(&quot;Invalid Values!&quot;)
        call d.destroy()
    endif
    set d.source        = source
    set d.target        = target
    set d.trees         = tree
    set d.fly           = fly
    set d.chain         = chain
    set d.hit           = NewGroup()
    set d.speed         = speed * TIME
    set d.decrement     = decrement * TIME
    set d.sin           = Sin(angle)
    set d.cos           = Cos(angle)
    set d.distance      = -1 * speed * speed / (2 * -decrement / TIME)
    set d.positionZ     = 0.
    
    if d.fly then
        call SetUnitPathing(d.target,false)
        call UnitAddAbility(d.target,FLYID)
        call UnitRemoveAbility(d.target,FLYID)
        set d.effects = AddSpecialEffectTarget(FLYING,d.target,ATTACHPOINT)
    endif
    
    set d.mode = d.TerrainCheck()
    if d.mode == 1 then
        set d.effects = AddSpecialEffectTarget(GROUND,d.target,ATTACHPOINT)
    elseif d.mode == 2 then
        set d.effects = AddSpecialEffectTarget(WATER,d.target,ATTACHPOINT)
    elseif d.mode == 3 then
        set d.effects = AddSpecialEffectTarget(COLLISION,d.target,ATTACHPOINT)
    endif
    set Knock[target] = d
    if Knock.Count == 0 then
        call TimerStart(Knock.Timer,TIME,true,function Knock.Periodic)
    endif
    set Knock.D[Knock.Count] = d
    set Knock.Count = Knock.Count + 1
    return d
    endmethod
    
private method onDestroy takes nothing returns nothing
    call DestroyEffect(.effects)
    call ReleaseGroup(.hit)
    call SetUnitFlyHeight(.target,GetUnitDefaultFlyHeight(.target),0)
    call SetUnitPathing(.target,true)
endmethod
        
private method action takes nothing returns boolean
    local unit    t    = null
    local real    x    = 0.00
    local real    y    = 0.00
    local real    cx   = 0.00
    local real    cy   = 0.00
    local integer mode = 0
    local real height = 0.00
    local Knock d
    set mode = .mode
    set x = GetUnitX(.target)
    set y = GetUnitY(.target)
    set height = GetUnitFlyHeight(.target)
    set .positionZ = .positionZ + .speed
    set x = x + .speed * .cos
    set y = y + .speed * .sin
        
    if height &gt;= HEIGHTLEVEL then
        set .chain = false
        set .trees = false
    endif
        
    if .speed &lt;= 0 or IsPointOutside(x,y) then
        return true
    endif
    
     call SetUnitPosition(.target,x,y)
     
    if .trees then
        call SetRect(TreeRect,x-RADIUS,y-RADIUS,x+RADIUS,y+RADIUS)
        call EnumDestructablesInRect(TreeRect,TreeCheck,function Trees)
    endif
        
    if .fly then
        call SetUnitFlyHeight(.target,ParabolaZ(FACTOR*.distance,.distance,.positionZ),0)
    endif
        
    set .mode = .TerrainCheck()
    if .mode == 1 and (mode == 2 or mode == 3) then
        call DestroyEffect(.effects)
        set .effects = AddSpecialEffectTarget(GROUND,.target,ATTACHPOINT)
    elseif .mode == 2 and (mode == 1 or mode == 3) then
        call DestroyEffect(.effects)
        set .effects = AddSpecialEffectTarget(WATER,.target,ATTACHPOINT)
    elseif .mode == 3 and (mode == 1 or mode == 2) then
        call DestroyEffect(.effects)
        set .effects = AddSpecialEffectTarget(COLLISION,.target,ATTACHPOINT)
    endif
        
    if .chain == true then
        call GroupEnumUnitsInRange(ENUM_GROUP,x,y,CHAINRADIUS,ChainFilter)
        loop
            set t = FirstOfGroup(ENUM_GROUP)
            exitwhen t == null
            if not IsUnitInGroup(t,.hit) then
                set cx = GetUnitX(t)
                set cy = GetUnitY(t)
                call GroupAddUnit(.hit,t)
                set d = Knock.create(.source,t,Atan2(cy-y,cx-x),(.speed/TIME)*SPEEDFACTOR,(.decrement/TIME),.trees,.chain,.fly)
                call GroupAddUnit(d.hit,.target)
                set Knock.D[Knock.Count] = d
                set Knock.Count = Knock.Count + 1
            endif
            call GroupRemoveUnit(ENUM_GROUP,t)
        endloop
    endif
     set .speed = .speed - .decrement
        return false
endmethod
    
private static method Periodic takes nothing returns nothing
    local integer i = 0
    loop
        exitwhen i &gt;= Knock.Count
        if Knock.D<i>.action() then
            set Knock.Count = Knock.Count - 1
            if Knock.Count &gt; 0 then
                set Knock.D<i> = Knock.D[Knock.Count]
                set i = i - 1
            else
                call PauseTimer(.Timer)
            endif
        endif
        set i = i + 1
        endloop
endmethod

endstruct

function IsKnockedBack takes unit target returns boolean
    return Knock[target] != 0
endfunction

private function Init takes nothing returns nothing
    set TreeRect    = Rect(0.00,0.00,1.00,1.00)
    set TreeCheck   = Filter(function CheckTrees)
    set ChainFilter = Filter(function ChainCheck)
    set MapMaxX     = GetRectMaxX(bj_mapInitialPlayableArea)
    set MapMaxY     = GetRectMaxY(bj_mapInitialPlayableArea)
    set MapMinX     = GetRectMinX(bj_mapInitialPlayableArea)
    set MapMinY     = GetRectMinY(bj_mapInitialPlayableArea)     
endfunction

endlibrary</i></i></i>


Do you all know why in my Timer, Knock array, and integer count, I have to put a Knock. infront of them instead of just doing a .?

Do you all know why my unit isn't getting knockbacked properly?
 

Tom Jones

N/A
Reaction score
437
a) In your create and Periodic function, this isn't declared.
b) How would we even stand a chance of knowing that?
 

wraithseeker

Tired.
Reaction score
122
A) Does it have to be the same one?

In parabolasystem, we used identifier F and then used this after in periodic and action function.

B) well I used EKB test map to test by replacing the system code with the new one. So download EKB and replace the code over and you'll see how buggy it is.
 

Tom Jones

N/A
Reaction score
437
a)
JASS:
struct data
    static integer i = 4
    string s

    method A takes nothing returns nothing
        //JassHelper will automatically pass this to the method.
        local integer a = .i     //Valid syntax.
        local integer b = data.i //Also valid, and the same as the above.
        

        set .s = &quot;whatever&quot;
    endmethod
    
    static method B takes nothing returns nothing
        //JassHelper will not pass this to us, we have to declare it:
        local data this = //somehow get an instance of the struct here.
        
        set .s = &quot;whatever&quot;
    endmethod
    
    static method create takes nothing returns data
        //JassHelper will not pass this to us, we have to declare it:
        local data this = data.allocate()
        
        set .s = &quot;whatever&quot;
        return this
    endmethod
endstruct

function ...
    local integer i = 0
    local data s
    
    loop
        exitwhen i == data.i //Valid syntax, the member is static.
        set s = data.create()
        set i = i+1
    endloop
    ...
endfunction


b) What's EKB :confused:
 

wraithseeker

Tired.
Reaction score
122
You mean if I put local Knock d = data.allocate() there, JassHelper will get confused?

ParabolaSystem is under page 2 in the resource section, I don't know why it doesn't work and such.

Chatting on MSN would be faster, do you have one?

B)Extended Knockback System,under Systems and demo maps.
 

Tom Jones

N/A
Reaction score
437
I reserve my MSN for private use.

I'll try to elaborate. this is a variable name for a struct instance. The difference from using this and, let's say s, is that JassHelper will automatically fill in this inside struct declarations if no other variable name is present in front of the struct syntax. Obviously, since this is just another variable name, we have to declare it.

On to static members. These can be referenced by either using a struct instance name and then the struct syntax (d.aStaticMember) or by using the name of the struct (data.aStaticMember).

Now back to:
Do you all know why in my Timer, Knock array, and integer count, I have to put a Knock. infront of them instead of just doing a .?
This is why .MemberName gives you a syntax error, this isn't declared.
 

wraithseeker

Tired.
Reaction score
122
JASS:
private static method Periodic takes nothing returns nothing
    local integer i = 0
    local Knock this
    loop
        exitwhen i &gt;= .Count
        if .D<i>.action() then
            set .Count = .Count - 1
            if Knock.Count &gt; 0 then
                set Knock.D<i> = Knock.D[Knock.Count]
                set i = i - 1
            else
                  call PauseTimer(.Timer)
            endif
        endif
        set i = i + 1
        endloop
endmethod</i></i>


Syntax error at the .D.Actions call saying D is not a member of Knock. I decleared this already but still doesn't work.

If I remember correctly, methods declear your struct like this automaticly
JASS:

local [Structname] this


Edit: now I figured that the struct gets destroyed every periodic function , any ideas?

Current code

JASS:


library Knockback initializer Init requires DestructableLib, IsTerrainWalkable, GroupUtils, PUI

globals
    private constant real    TIME         = 0.03                     // The timer interval.
    private constant real    CHAINRADIUS  = 100.00                   // The radius a unit can get chained when near the unit target.
    private constant real    SPEEDFACTOR  = 0.75                     // How much speed will be reduced when a unit chains another unit.
    private constant real    RADIUS       = 128.00                   // The radius to check tree.
    private constant real    HEIGHTLEVEL  = 200.00                   // The default height level that stops chaining or killing trees when in the air.
    private constant real    FACTOR       = 0.3333                   // Or 0.25 for smoothness.
    private constant string  GROUND       = &quot;MDX\\Dust.mdx&quot;          // The effect for ground.
    private constant string  WATER        = &quot;MDX\\SlideWater.mdx&quot;    // The effect for water.
    private constant string  COLLISION    = &quot;MDX\\DustAndRocks.mdx&quot;  // The effect when at cliff
    private constant string  FLYING       = &quot;MDX\\TornadoMissile.mdx&quot;// The effect when flying
    private constant string  ATTACHPOINT  = &quot;origin&quot;                 // The attachment point for effects
endglobals

globals
    private constant integer INVULNERABLE   = &#039;Avul&#039;               
    private constant integer FLYID          = &#039;Amrf&#039; 
    private rect     TreeRect               = null
    private boolexpr TreeCheck              = null
    private boolexpr ChainFilter            = null
    private unit     Target                 = null
    private unit     Source                 = null
    private real MapMaxX                    = 0
    private real MapMaxY                    = 0
    private real MapMinX                    = 0
    private real MapMinY                    = 0
    private Knock D
endglobals

private function CheckTrees takes nothing returns boolean
    return IsDestructableTree(GetFilterDestructable())
endfunction

private function Trees takes nothing returns nothing
    call KillDestructable(GetEnumDestructable())
endfunction

private function ChainCheck takes nothing returns boolean
    return Target != GetFilterUnit() and IsUnitEnemy(GetFilterUnit(),GetOwningPlayer(Source)) and IsUnitType(GetFilterUnit(), UNIT_TYPE_GROUND) == true and IsUnitType(GetFilterUnit(), UNIT_TYPE_MECHANICAL) == false and GetWidgetLife(GetFilterUnit()) &gt; 0.405 and GetUnitAbilityLevel(GetFilterUnit(),INVULNERABLE) &lt;= 0
endfunction

function ParabolaZ takes real h, real d, real x returns real
  return (4 * h / d) * (d - x) * (x / d)
endfunction

private function IsPointOutside takes real x, real y returns boolean
    return (x &gt; MapMaxX or y &gt; MapMaxY or x &lt; MapMinX or y &lt; MapMinY)
endfunction

struct Knock
 
    private static timer Timer = CreateTimer()
    private static Knock array D
    private static integer Count = 0
    //! runtextmacro PUI()
    unit        source          = null
    unit        target          = null
    integer     mode            = 0
    group       hit             = null
    real        cos             = 0
    real        sin             = 0 
    real        speed           = 0
    real        decrement       = 0
    real        distance        = 0
    real        positionZ       = 0
    effect      effects         = null
    boolean     terrain         = false
    boolean     trees           = false
    boolean     chain           = false
    boolean     fly             = false
    
   method TerrainCheck takes nothing returns integer
        local real x = GetUnitX(.target)
        local real y = GetUnitY(.target)
    
        if IsTerrainWalkable(x + 50.00 * .cos,y + 50.00 * .sin) == false then
            return 3
        else
            if IsTerrainPathable(x,y,PATHING_TYPE_FLOATABILITY) then
                return 1
            elseif not IsTerrainPathable(x,y,PATHING_TYPE_WALKABILITY) then
                return 2
            endif
        endif 
        
        return 0
    endmethod
    
    
method KnockbackStop takes unit target returns boolean
    local Knock d = Knock[target]
    local integer i = Knock.Count - 1
    if d != 0 then
        call d.release()
        if Knock.Count &gt; 0 then
             set Knock.D<i> = Knock.D[Knock.Count]
        else
            call PauseTimer(Knock.Timer)
        endif
        return true
    endif
    return false
endmethod
        
static method create takes unit source, unit target, real angle, real speed, real decrement, boolean tree,boolean chain, boolean fly returns Knock
    local Knock d = Knock.allocate()
    if target == null or source == null or speed == 0.00 or decrement == 0.00 then
        debug call BJDebugMsg(&quot;Invalid Values!&quot;)
        call d.destroy()
    endif
    set d.source        = source
    set d.target        = target
    set d.trees         = tree
    set d.fly           = fly
    set d.chain         = chain
    set d.hit           = NewGroup()
    set d.speed         = speed * TIME
    set d.decrement     = decrement * TIME
    set d.sin           = Sin(angle)
    set d.cos           = Cos(angle)
    set d.distance      = -1 * speed * speed / (2 * -decrement / TIME)
    set d.positionZ     = 0.
    
    if d.fly then
        call SetUnitPathing(d.target,false)
        call UnitAddAbility(d.target,FLYID)
        call UnitRemoveAbility(d.target,FLYID)
        set d.effects = AddSpecialEffectTarget(FLYING,d.target,ATTACHPOINT)
    endif
    
    set d.mode = d.TerrainCheck()
    if d.mode == 1 then
        set d.effects = AddSpecialEffectTarget(GROUND,d.target,ATTACHPOINT)
    elseif d.mode == 2 then
        set d.effects = AddSpecialEffectTarget(WATER,d.target,ATTACHPOINT)
    elseif d.mode == 3 then
        set d.effects = AddSpecialEffectTarget(COLLISION,d.target,ATTACHPOINT)
    endif
    set Knock[target] = d
    if Knock.Count == 0 then
        call TimerStart(d.Timer,TIME,true,function Knock.Periodic)
    endif
    set d.D[d.Count] = d
    set d.Count = d.Count + 1
    return d
    endmethod
    
private method onDestroy takes nothing returns nothing
    call DestroyEffect(.effects)
    call ReleaseGroup(.hit)
    call SetUnitFlyHeight(.target,GetUnitDefaultFlyHeight(.target),0)
    call SetUnitPathing(.target,true)
    call BJDebugMsg(&quot;destroyed&quot;)
endmethod
        
private method action takes nothing returns boolean
    local Knock d = 0
    local unit    t    = null
    local real    x    = 0.00
    local real    y    = 0.00
    local real    cx   = 0.00
    local real    cy   = 0.00
    local integer mode = 0
    local real height = 0.00
    set mode = .mode
    set x = GetUnitX(.target)
    set y = GetUnitY(.target)
    set height = GetUnitFlyHeight(.target)
    set .positionZ = .positionZ + .speed
   call BJDebugMsg(R2S(.speed))
        
    if height &gt;= HEIGHTLEVEL then
        set .chain = false
        set .trees = false
    endif
        
    if .speed &lt;= 0 or IsPointOutside(x,y) then
        call .release()
        call BJDebugMsg(&quot;STOPPING&quot;)
        return true
    endif
    
         set x = x + .speed * .cos
    set y = y + .speed * .sin
     call SetUnitPosition(.target,x,y)
     
    if .trees then
        call SetRect(TreeRect,x-RADIUS,y-RADIUS,x+RADIUS,y+RADIUS)
        call EnumDestructablesInRect(TreeRect,TreeCheck,function Trees)
    endif
        
    if .fly then
        call SetUnitFlyHeight(.target,ParabolaZ(FACTOR*.distance,.distance,.positionZ),0)
    endif
        
    set .mode = .TerrainCheck()
    if .mode == 1 and (mode == 2 or mode == 3) then
        call DestroyEffect(.effects)
        set .effects = AddSpecialEffectTarget(GROUND,.target,ATTACHPOINT)
    elseif .mode == 2 and (mode == 1 or mode == 3) then
        call DestroyEffect(.effects)
        set .effects = AddSpecialEffectTarget(WATER,.target,ATTACHPOINT)
    elseif .mode == 3 and (mode == 1 or mode == 2) then
        call DestroyEffect(.effects)
        set .effects = AddSpecialEffectTarget(COLLISION,.target,ATTACHPOINT)
    endif
        
    if .chain == true then
        call GroupEnumUnitsInRange(ENUM_GROUP,x,y,CHAINRADIUS,ChainFilter)
        loop
            set t = FirstOfGroup(ENUM_GROUP)
            exitwhen t == null
            if not IsUnitInGroup(t,.hit) then
                set cx = GetUnitX(t)
                set cy = GetUnitY(t)
                call GroupAddUnit(.hit,t)
                set d = Knock.create(.source,t,Atan2(cy-y,cx-x),(.speed/TIME)*SPEEDFACTOR,(.decrement/TIME),.trees,.chain,.fly)
                call GroupAddUnit(d.hit,.target)
                set Knock.D[Knock.Count] = d
                set Knock.Count = Knock.Count + 1
            endif
            call GroupRemoveUnit(ENUM_GROUP,t)
        endloop
    endif
     set .speed = .speed - .decrement
    return false
endmethod
    
private static method Periodic takes nothing returns nothing
    local integer i = 0
    local Knock this
    loop
        exitwhen i &gt;= .Count
        if Knock.D<i>.action() then
            set .Count = Knock.Count - 1
            if Knock.Count &gt; 0 then
                set Knock.D<i> = Knock.D[Knock.Count]
                set i = i - 1
            else
                  call PauseTimer(.Timer)
                  set Knock.Count = 0
            endif
        endif
        set i = i + 1
        endloop
endmethod

endstruct

function IsKnockedBack takes unit target returns boolean
    return Knock[target] != 0
endfunction

private function Init takes nothing returns nothing
    set TreeRect    = Rect(0.00,0.00,1.00,1.00)
    set TreeCheck   = Filter(function CheckTrees)
    set ChainFilter = Filter(function ChainCheck)
    set MapMaxX     = GetRectMaxX(bj_mapInitialPlayableArea)
    set MapMaxY     = GetRectMaxY(bj_mapInitialPlayableArea)
    set MapMinX     = GetRectMinX(bj_mapInitialPlayableArea)
    set MapMinY     = GetRectMinY(bj_mapInitialPlayableArea)     
endfunction

endlibrary</i></i></i>
 

Pyrogasm

There are some who would use any excuse to ban me.
Reaction score
134
Jesus. You do not understand static methods, do you? The point of a static method is that it does not reference a specific instance of a struct. In a regular method, ".D" is the same is "this.D", and "this" is the instance of the struct the method is currently being called for.

Static methods are nothing more than functions inside the struct. They do not take an instance, and you cannot make them take an instance. Thus, the ".<varname>" syntax is completely invalid. Rather, you must use "<structtype variable>.<varname>", or if you want to access static members, use "Knock.<varname>".

You cannot use "this" as the name of a variable (along with a few others, though I don't know what they are off the top of my head). It's protected, and JASSHelper shouldn't allow it. Aside from it not even being correctly used, I don't see why you needed to create a variable called "this" in the first place.
 

Kenny

Back for now.
Reaction score
202
@ Pyrogasm:

From what i gather, are you saying that this:

JASS:
static method update takes nothing returns nothing
    local integer i = 1
            
    loop
        exitwhen i &gt; .D_total
                
        if .D<i>.dur &lt;= 0.00 then
            call .D<i>.destroy()
            set .D<i> = .D[.D_total]
            set .D_total = .D_total - 1
            set i = i - 1
        else
            set .D<i>.dur = .D<i>.dur - INTERVAL
        endif
                
        set i = i + 1
    endloop
            
    if .D_total &lt;= 0 then
        call PauseTimer(.Timer)
        set .D_total = 0
    endif
endmethod

</i></i></i></i></i>


Does not/should not work?
 

Pyrogasm

There are some who would use any excuse to ban me.
Reaction score
134
It should, but in his case it does not work, for some odd reason. In theory, static members should be able to be accessed with ".<Membername>", but he's getting syntax errors doing that, so therefore the name of the struct is needed.

And besides, doesn't it make more sense to put the struct name first anyway, to signify that it's a static member?
 

Kenny

Back for now.
Reaction score
202
Your right. I'm just lazy so when it comes to typing, i take the easy way out, even though using the struct name does make more sense. I guess I've just gotten so use to it the easy way :p. But I'm not sure why his isn't working.
 

wraithseeker

Tired.
Reaction score
122
A update on the code

JASS:

library Knockback initializer Init requires DestructableLib, IsTerrainWalkable, GroupUtils, PUI

globals
    private constant real    TIME         = 0.03                     // The timer interval.
    private constant real    CHAINRADIUS  = 100.00                   // The radius a unit can get chained when near the unit target.
    private constant real    SPEEDFACTOR  = 0.75                     // How much speed will be reduced when a unit chains another unit.
    private constant real    RADIUS       = 128.00                   // The radius to check tree.
    private constant real    HEIGHTLEVEL  = 200.00                   // The default height level that stops chaining or killing trees when in the air.
    private constant real    FACTOR       = 0.3333                   // Or 0.25 for smoothness.
    private constant string  GROUND       = &quot;MDX\\Dust.mdx&quot;          // The effect for ground.
    private constant string  WATER        = &quot;MDX\\SlideWater.mdx&quot;    // The effect for water.
    private constant string  COLLISION    = &quot;MDX\\DustAndRocks.mdx&quot;  // The effect when at cliff
    private constant string  FLYING       = &quot;MDX\\TornadoMissile.mdx&quot;// The effect when flying
    private constant string  ATTACHPOINT  = &quot;origin&quot;                 // The attachment point for effects
endglobals

globals
    private constant integer INVULNERABLE   = &#039;Avul&#039;               
    private constant integer FLYID          = &#039;Amrf&#039; 
    private rect     TreeRect               = null
    private boolexpr TreeCheck              = null
    private boolexpr ChainFilter            = null
    private unit     Target                 = null
    private unit     Source                 = null
    private real MapMaxX                    = 0
    private real MapMaxY                    = 0
    private real MapMinX                    = 0
    private real MapMinY                    = 0
    private Knock D
endglobals

private function CheckTrees takes nothing returns boolean
    return IsDestructableTree(GetFilterDestructable())
endfunction

private function Trees takes nothing returns nothing
    call KillDestructable(GetEnumDestructable())
endfunction

private function ChainCheck takes nothing returns boolean
    return Target != GetFilterUnit() and IsUnitEnemy(GetFilterUnit(),GetOwningPlayer(Source)) and IsUnitType(GetFilterUnit(), UNIT_TYPE_GROUND) == true and IsUnitType(GetFilterUnit(), UNIT_TYPE_MECHANICAL) == false and GetWidgetLife(GetFilterUnit()) &gt; 0.405 and GetUnitAbilityLevel(GetFilterUnit(),INVULNERABLE) &lt;= 0
endfunction

function ParabolaZ takes real h, real d, real x returns real
  return (4 * h / d) * (d - x) * (x / d)
endfunction

private function IsPointOutside takes real x, real y returns boolean
    return (x &gt; MapMaxX or y &gt; MapMaxY or x &lt; MapMinX or y &lt; MapMinY)
endfunction

struct Knock
    private static timer Timer = CreateTimer()
    private static Knock array D
    private static integer Count = 0
      //! runtextmacro PUI()
    unit        source          = null
    unit        target          = null
    integer     mode            = 0
    group       hit             = null
    real        cos             = 0
    real        sin             = 0 
    real        speed           = 0
    real        decrement       = 0
    real        distance        = 0
    real        positionZ       = 0
    effect      effects         = null
    boolean     terrain         = false
    boolean     trees           = false
    boolean     chain           = false
    boolean     fly             = false
    
   method TerrainCheck takes nothing returns integer
        local real x = GetUnitX(.target)
        local real y = GetUnitY(.target)
    
        if IsTerrainWalkable(x + 50.00 * .cos,y + 50.00 * .sin) == false then
            return 3
        else
            if IsTerrainPathable(x,y,PATHING_TYPE_FLOATABILITY) then
                return 1
            elseif not IsTerrainPathable(x,y,PATHING_TYPE_WALKABILITY) then
                return 2
            endif
        endif 
        
        return 0
    endmethod
    
    
method KnockbackStop takes unit target returns boolean
    local Knock d = Knock[target]
    local integer i = Knock.Count - 1
    if d != 0 then
        call d.release()
        if Knock.Count &gt; 0 then
             set Knock.D<i> = Knock.D[Knock.Count]
        else
            call PauseTimer(Knock.Timer)
        endif
        return true
    endif
    return false
endmethod
        
static method create takes unit source, unit target, real angle, real speed, real decrement, boolean tree,boolean chain, boolean fly returns Knock
    local Knock d = Knock.allocate()
    if target == null or source == null or speed == 0.00 or decrement == 0.00 then
        debug call BJDebugMsg(&quot;Invalid Values!&quot;)
       // call d.destroy()
    endif
    set d.source        = source
    set d.target        = target
    set d.trees         = tree
    set d.fly           = fly
    set d.chain         = chain
    set d.hit           = NewGroup()
    set d.speed         = speed * TIME
    set d.decrement     = decrement * TIME
    set d.sin           = Sin(angle)
    set d.cos           = Cos(angle)
    set d.distance      = -1 * speed * speed / (2 * -decrement / TIME)
    set d.positionZ     = 0.
    
    if d.fly then
        call SetUnitPathing(d.target,false)
        call UnitAddAbility(d.target,FLYID)
        call UnitRemoveAbility(d.target,FLYID)
        set d.effects = AddSpecialEffectTarget(FLYING,d.target,ATTACHPOINT)
    endif
    
    set d.mode = d.TerrainCheck()
    if d.mode == 1 then
        set d.effects = AddSpecialEffectTarget(GROUND,d.target,ATTACHPOINT)
    elseif d.mode == 2 then
        set d.effects = AddSpecialEffectTarget(WATER,d.target,ATTACHPOINT)
    elseif d.mode == 3 then
        set d.effects = AddSpecialEffectTarget(COLLISION,d.target,ATTACHPOINT)
    endif
    set Knock[target] = d
    if Knock.Count == 0 then
        call TimerStart(d.Timer,TIME,true,function Knock.Periodic)
    endif
    set d.D[d.Count] = d
    set d.Count = d.Count + 1
    return d
    endmethod
    
private method onDestroy takes nothing returns nothing
    call DestroyEffect(.effects)
    call ReleaseGroup(.hit)
    call SetUnitFlyHeight(.target,GetUnitDefaultFlyHeight(.target),0)
    call SetUnitPathing(.target,true)
    call BJDebugMsg(&quot;destroyed&quot;)
endmethod
        
private method action takes nothing returns boolean
    local Knock d
    local unit    t    = null
    local real    x    = 0.00
    local real    y    = 0.00
    local real    cx   = 0.00
    local real    cy   = 0.00
    local integer mode = 0
    local real height = 0.00
    set mode = .mode
    set x = GetUnitX(.target)
    set y = GetUnitY(.target)
    set height = GetUnitFlyHeight(.target)
    set .positionZ = .positionZ + .speed
        
    if height &gt;= HEIGHTLEVEL then
        set .chain = false
        set .trees = false
    endif
        
    if .speed &lt;= 0 or IsPointOutside(x,y) then
        //call .release()
       // call BJDebugMsg(&quot;STOPPING&quot;)
        return true
    endif
    
         set x = x + .speed * .cos
    set y = y + .speed * .sin
     call SetUnitPosition(.target,x,y)
     
    if .trees then
        call SetRect(TreeRect,x-RADIUS,y-RADIUS,x+RADIUS,y+RADIUS)
        call EnumDestructablesInRect(TreeRect,TreeCheck,function Trees)
    endif
        
    if .fly then
        call SetUnitFlyHeight(.target,ParabolaZ(FACTOR*.distance,.distance,.positionZ),0)
    endif
        
    set .mode = .TerrainCheck()
    if .mode == 1 and (mode == 2 or mode == 3) then
        call DestroyEffect(.effects)
        set .effects = AddSpecialEffectTarget(GROUND,.target,ATTACHPOINT)
    elseif .mode == 2 and (mode == 1 or mode == 3) then
        call DestroyEffect(.effects)
        set .effects = AddSpecialEffectTarget(WATER,.target,ATTACHPOINT)
    elseif .mode == 3 and (mode == 1 or mode == 2) then
        call DestroyEffect(.effects)
        set .effects = AddSpecialEffectTarget(COLLISION,.target,ATTACHPOINT)
    endif
        
    if .chain == true then
        call GroupEnumUnitsInRange(ENUM_GROUP,x,y,CHAINRADIUS,ChainFilter)
        loop
            set t = FirstOfGroup(ENUM_GROUP)
            exitwhen t == null
            if not IsUnitInGroup(t,.hit) then
                set cx = GetUnitX(t)
                set cy = GetUnitY(t)
                call GroupAddUnit(.hit,t)
                set d = Knock.create(.source,t,Atan2(cy-y,cx-x),(.speed/TIME)*SPEEDFACTOR,(.decrement/TIME),.trees,.chain,.fly)
                call GroupAddUnit(d.hit,.target)
                set Knock.D[Knock.Count] = d
                set Knock.Count = Knock.Count + 1
            endif
            call GroupRemoveUnit(ENUM_GROUP,t)
        endloop
    endif
     set .speed = .speed - .decrement
    return false
endmethod
    
private static method Periodic takes nothing returns nothing
    local integer i = 0
    loop
        exitwhen i &gt;= .Count
        if Knock.D<i>.action() then
            set .Count = Knock.Count - 1
            if Knock.Count &gt; 0 then
                set Knock.D<i> = Knock.D[Knock.Count]
                set i = i - 1
            else
                  call PauseTimer(.Timer)
                  set Knock.Count = 0
            endif
        endif
        set i = i + 1
        endloop
endmethod

endstruct

function IsKnockedBack takes unit target returns boolean
    return Knock[target] != 0
endfunction

private function Init takes nothing returns nothing
    set TreeRect    = Rect(0.00,0.00,1.00,1.00)
    set TreeCheck   = Filter(function CheckTrees)
    set ChainFilter = Filter(function ChainCheck)
    set MapMaxX     = GetRectMaxX(bj_mapInitialPlayableArea)
    set MapMaxY     = GetRectMaxY(bj_mapInitialPlayableArea)
    set MapMinX     = GetRectMinX(bj_mapInitialPlayableArea)
    set MapMinY     = GetRectMinY(bj_mapInitialPlayableArea)     
endfunction

endlibrary</i></i></i>


Same error and such.
 

saw792

Is known to say things. That is all.
Reaction score
280
JASS:
library Knockback initializer Init requires DestructableLib, IsTerrainWalkable, GroupUtils, PUI

globals
    private constant real    TIME         = 0.03                     // The timer interval.
    private constant real    CHAINRADIUS  = 100.00                   // The radius a unit can get chained when near the unit target.
    private constant real    SPEEDFACTOR  = 0.75                     // How much speed will be reduced when a unit chains another unit.
    private constant real    RADIUS       = 128.00                   // The radius to check tree.
    private constant real    HEIGHTLEVEL  = 200.00                   // The default height level that stops chaining or killing trees when in the air.
    private constant real    FACTOR       = 0.3333                   // Or 0.25 for smoothness.
    private constant string  GROUND       = &quot;MDX\\Dust.mdx&quot;          // The effect for ground.
    private constant string  WATER        = &quot;MDX\\SlideWater.mdx&quot;    // The effect for water.
    private constant string  COLLISION    = &quot;MDX\\DustAndRocks.mdx&quot;  // The effect when at cliff
    private constant string  FLYING       = &quot;MDX\\TornadoMissile.mdx&quot;// The effect when flying
    private constant string  ATTACHPOINT  = &quot;origin&quot;                 // The attachment point for effects
endglobals

globals
    private constant integer INVULNERABLE   = &#039;Avul&#039;               
    private constant integer FLYID          = &#039;Amrf&#039; 
    private rect     TreeRect               = null
    private boolexpr TreeCheck              = null
    private boolexpr ChainFilter            = null
    private unit     Target                 = null
    private unit     Source                 = null
    private real MapMaxX                    = 0
    private real MapMaxY                    = 0
    private real MapMinX                    = 0
    private real MapMinY                    = 0
    private Knock D
endglobals

private function CheckTrees takes nothing returns boolean
    return IsDestructableTree(GetFilterDestructable())
endfunction

private function Trees takes nothing returns nothing
    call KillDestructable(GetEnumDestructable())
endfunction

private function ChainCheck takes nothing returns boolean
    return Target != GetFilterUnit() and IsUnitEnemy(GetFilterUnit(),GetOwningPlayer(Source)) and IsUnitType(GetFilterUnit(), UNIT_TYPE_GROUND) == true and IsUnitType(GetFilterUnit(), UNIT_TYPE_MECHANICAL) == false and GetWidgetLife(GetFilterUnit()) &gt; 0.405 and GetUnitAbilityLevel(GetFilterUnit(),INVULNERABLE) &lt;= 0
endfunction

function ParabolaZ takes real h, real d, real x returns real
  return (4 * h / d) * (d - x) * (x / d)
endfunction

private function IsPointOutside takes real x, real y returns boolean
    return (x &gt; MapMaxX or y &gt; MapMaxY or x &lt; MapMinX or y &lt; MapMinY)
endfunction

struct Knock
    private static timer Timer = CreateTimer()
    private static group knocking = null
      //! runtextmacro PUI()
    unit        source          = null
    unit        target          = null
    integer     mode            = 0
    group       hit             = null
    real        cos             = 0
    real        sin             = 0 
    real        speed           = 0
    real        decrement       = 0
    real        distance        = 0
    real        positionZ       = 0
    effect      effects         = null
    boolean     terrain         = false
    boolean     trees           = false
    boolean     chain           = false
    boolean     fly             = false
    
   method TerrainCheck takes nothing returns integer
        local real x = GetUnitX(.target)
        local real y = GetUnitY(.target)
    
        if IsTerrainWalkable(x + 50.00 * .cos,y + 50.00 * .sin) == false then
            return 3
        else
            if IsTerrainPathable(x,y,PATHING_TYPE_FLOATABILITY) then
                return 1
            elseif not IsTerrainPathable(x,y,PATHING_TYPE_WALKABILITY) then
                return 2
            endif
        endif 
        
        return 0
    endmethod
    
    
method KnockbackStop takes unit target returns boolean
    local Knock d = Knock[target]
    if d != 0 then
        call d.release()
        if FirstOfGroup(Knock.knocking) != null then
            call GroupRemoveUnit(Knock.knocking, target)
        else
            call PauseTimer(Knock.Timer)
        endif
        return true
    endif
    return false
endmethod
        
static method create takes unit source, unit target, real angle, real speed, real decrement, boolean tree,boolean chain, boolean fly returns Knock
    local Knock d = Knock.allocate()
    if target == null or source == null or speed == 0.00 or decrement == 0.00 then
        debug call BJDebugMsg(&quot;Invalid Values!&quot;)
        call d.destroy()
    endif
    set d.source        = source
    set d.target        = target
    set d.trees         = tree
    set d.fly           = fly
    set d.chain         = chain
    set d.hit           = NewGroup()
    set d.speed         = speed * TIME
    set d.decrement     = decrement * TIME
    set d.sin           = Sin(angle)
    set d.cos           = Cos(angle)
    set d.distance      = -1 * speed * speed / (2 * -decrement / TIME)
    set d.positionZ     = 0.
    
    if d.fly then
        call SetUnitPathing(d.target,false)
        call UnitAddAbility(d.target,FLYID)
        call UnitRemoveAbility(d.target,FLYID)
        set d.effects = AddSpecialEffectTarget(FLYING,d.target,ATTACHPOINT)
    endif
    
    set d.mode = d.TerrainCheck()
    if d.mode == 1 then
        set d.effects = AddSpecialEffectTarget(GROUND,d.target,ATTACHPOINT)
    elseif d.mode == 2 then
        set d.effects = AddSpecialEffectTarget(WATER,d.target,ATTACHPOINT)
    elseif d.mode == 3 then
        set d.effects = AddSpecialEffectTarget(COLLISION,d.target,ATTACHPOINT)
    endif
    set Knock[target] = d
    if FirstOfGroup(Knock.knocking) == null then
        call TimerStart(d.Timer,TIME,true,function Knock.Periodic)
    endif
    call GroupAddUnit(Knock.knocking, target)
    return d
endmethod
    
private method onDestroy takes nothing returns nothing
    call DestroyEffect(.effects)
    call ReleaseGroup(.hit)
    call SetUnitFlyHeight(.target,GetUnitDefaultFlyHeight(.target),0)
    call SetUnitPathing(.target,true)
    call BJDebugMsg(&quot;destroyed&quot;)
endmethod
        
private static method action takes nothing returns nothing
    local Knock d
    local Knock this = Knock[GetEnumUnit()]
    local unit    t    = null
    local real    x    = 0.00
    local real    y    = 0.00
    local real    cx   = 0.00
    local real    cy   = 0.00
    local integer mode = 0
    local real height = 0.00
    set Target = .target
    set mode = .mode
    set x = GetUnitX(.target)
    set y = GetUnitY(.target)
    set height = GetUnitFlyHeight(.target)
    set .positionZ = .positionZ + .speed
        
    if height &gt;= HEIGHTLEVEL then
        set .chain = false
        set .trees = false
    endif
        
    if .speed &lt;= 0 or IsPointOutside(x,y) then
        call GroupRemoveUnit(Knock.knocking, .target)
        call .release()
        call BJDebugMsg(&quot;STOPPING&quot;)
        return
    endif
    
    set x = x + .speed * .cos
    set y = y + .speed * .sin
    call SetUnitPosition(.target,x,y)
     
    if .trees then
        call SetRect(TreeRect,x-RADIUS,y-RADIUS,x+RADIUS,y+RADIUS)
        call EnumDestructablesInRect(TreeRect,TreeCheck,function Trees)
    endif
        
    if .fly then
        call SetUnitFlyHeight(.target,ParabolaZ(FACTOR*.distance,.distance,.positionZ),0)
    endif
        
    set .mode = .TerrainCheck()
    if .mode == 1 and (mode == 2 or mode == 3) then
        call DestroyEffect(.effects)
        set .effects = AddSpecialEffectTarget(GROUND,.target,ATTACHPOINT)
    elseif .mode == 2 and (mode == 1 or mode == 3) then
        call DestroyEffect(.effects)
        set .effects = AddSpecialEffectTarget(WATER,.target,ATTACHPOINT)
    elseif .mode == 3 and (mode == 1 or mode == 2) then
        call DestroyEffect(.effects)
        set .effects = AddSpecialEffectTarget(COLLISION,.target,ATTACHPOINT)
    endif

    if .chain == true then
        call GroupEnumUnitsInRange(ENUM_GROUP,x,y,CHAINRADIUS,ChainFilter)
        loop
            set t = FirstOfGroup(ENUM_GROUP)
            exitwhen t == null
            if not IsUnitInGroup(t,.hit) then
                set cx = GetUnitX(t)
                set cy = GetUnitY(t)
                call GroupAddUnit(.hit,t)
                set d = Knock.create(.source,t,Atan2(cy-y,cx-x),(.speed/TIME)*SPEEDFACTOR,(.decrement/TIME),.trees,.chain,.fly)
                call GroupAddUnit(d.hit,.target)
                call GroupAddUnit(Knock.knocking, t)
            endif
            call GroupRemoveUnit(ENUM_GROUP,t)
        endloop
    endif
     set .speed = .speed - .decrement
endmethod
    
private static method Periodic takes nothing returns nothing
    call ForGroup(Knock.knocking, function Knock.action)
    if FirstOfGroup(Knock.knocking) == null then
      call PauseTimer(.Timer)
    endif
endmethod

private static method onInit takes nothing returns nothing
    set Knock.knocking = NewGroup()
endmethod

endstruct

function IsKnockedBack takes unit target returns boolean
    return Knock[target] != 0
endfunction

private function Init takes nothing returns nothing
    set TreeRect    = Rect(0.00,0.00,1.00,1.00)
    set TreeCheck   = Filter(function CheckTrees)
    set ChainFilter = Filter(function ChainCheck)
    set MapMaxX     = GetRectMaxX(bj_mapInitialPlayableArea)
    set MapMaxY     = GetRectMaxY(bj_mapInitialPlayableArea)
    set MapMinX     = GetRectMinX(bj_mapInitialPlayableArea)
    set MapMinY     = GetRectMinY(bj_mapInitialPlayableArea)     
endfunction

endlibrary


The problem you were having was that you were combining a static timer loop with PUI unit attachment, which just wasn't working. PUI was calling .destroy on many struct instances which were non-existent as you had shuffled the location of them within the array. I replaced your static timer loop with a ForGroup() call and a group of units currently being knocked.
 
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