need help with Linked tower spell

Evan1993

Ultra Cool Member
Reaction score
30
The screen shot shows how its bugged, I've spent some time trying to find whats wrong with it. I'm sure its something very easy that I'm just missing....

I can attach the map if that will help anyone fix it.

Heres the code.
JASS:

scope ChainTower


globals //' Spell settings

    real BaseAOE = 500
    real AOEPerLevel = 100
    spell array ChainTowers
    integer total = -1 //used to tell if the trigger has been run or not.
    trigger gg_trg_Power_generator
    timer DmgInterval = CreateTimer()
endglobals

struct linkcollection

    lightning array l[20]
    integer lcount = 0
    integer rcount = 0
    unit u1 = null
    unit array u2[20]
  method add takes unit u1, unit u2, integer index returns nothing
      set this.u1 = u1
      set this.u2[index] = u2
      set this.l[index] = AddLightningEx("MBUR", true, GetUnitX(u1), GetUnitY(u1), 200, GetUnitX(u2), GetUnitY(u2), 200)
  endmethod
  
  method onDestroy takes nothing returns nothing
  local integer i = 0
  call DisplayTextToPlayer(Player(0),0,0,"Destroying Ligtning Count: " + I2S(.lcount))
  
  
  loop
  exitwhen i > .lcount
  call DisplayTextToPlayer(Player(0),0,0,"Removing gfx: " + I2S(i))
  call DestroyLightning(.l<i>)
  set i = i + 1
  endloop
  set .u1 = null
  endmethod
  
endstruct

struct spell
    linkcollection array links [20]
    group towers = null
    integer linkcount = 0
    unit generator = null
    unit caster = null

  method onDestroy takes nothing returns nothing//&#039; Clean up.
    local integer i = 1
    local unit x
    
    loop
        exitwhen i &gt; .linkcount
        call DisplayTextToPlayer(Player(0),0,0,&quot;Destroying Link: &quot; + I2S(i))
        call .links<i>.destroy()
        set i = i + 1
    endloop
    
    loop
        exitwhen FirstOfGroup(.towers) == null
        set x = FirstOfGroup(.towers)
        call KillUnit(x)
        call GroupRemoveUnit(.towers, x)
    endloop
    
    call KillUnit(.generator)
    set .towers = null
    set .generator = null
    set x = null
    
 endmethod
 
endstruct
private function damage takes nothing returns nothing
    local spell dat
    local group hurt = CreateGroup()
    local unit victim
    local integer i = 0 
    local integer i2 = 0
    local integer i3 = 0
    loop
    exitwhen i &gt; total 
    set dat = ChainTowers<i>
    
    loop
    exitwhen i3 &gt; dat.linkcount
    
        loop//&#039;*** LINK LOOP
        exitwhen i2 &gt; dat.links[i3].lcount
            
            //if dat.links[i2].u2[i2] != null then
                debug if (i2 &gt; 0 and i3 &gt; 0) and dat.links[i2].u2[i2] == null then
                    debug call DisplayTextToPlayer(Player(0),0,0,&quot;u2 Null on lightning: &quot; + I2S(i2) + &quot; Link: &quot; + I2S(i3) )
                    debug if dat.links[i2].u1 == null and (i2 &gt; 0 and i3 &gt; 0) then
                        debug call SetUnitVertexColor(dat.links[i2].u1,0,0,0,255)
                        debug call DisplayTextToPlayer(Player(0),0,0,&quot;u1 Null on lightning: &quot; + I2S(i2) + &quot; Link: &quot; + I2S(i3) )
                    debug endif
                debug endif
                set hurt = GroupEnumUnitsInLine(GetUnitLoc(dat.links[i2].u1), GetUnitLoc(dat.links[i2].u2[i2]), 0 )

                loop//&#039; UNIT GROUP LOOP
                exitwhen FirstOfGroup(hurt) == null
                        set victim = FirstOfGroup(hurt)
                        call SetUnitVertexColor(victim,255,0,0,255)
                        call GroupRemoveUnit(hurt,victim)
                endloop//&#039; END UNIT GROUP LOOP   
            //endif
            set i2 = i2 + 1
        endloop //&#039;** END LINK LOOP
        set i2 = 0
        set i3 = i3 + 1
    endloop
    set i = i + 1
    endloop
endfunction

//&#039; Power generator
function Trig_Power_generator_Conditions takes nothing returns boolean
    return GetSpellAbilityId() == &#039;ACbz&#039;
endfunction

function Trig_Power_generator_Actions takes nothing returns nothing
    local integer i = -1
    local location loc = GetSpellTargetLoc()
    local spell dat
    local unit gen
    local boolean end = false
    if total == -1 then
        call TimerStart(DmgInterval, 0.50,true, function damage)
        set total = 0
    endif
    
    loop
        exitwhen i &gt; total 
        set i = i + 1 // i starts at -1
        set dat = ChainTowers<i>
        
        if dat.caster == GetSpellAbilityUnit() then
            set end = true
            call dat.destroy()
        endif
        
    endloop

    set dat = spell.create()
    set dat.generator = CreateUnitAtLoc(GetOwningPlayer(GetSpellAbilityUnit()), &#039;ncfs&#039;, loc, bj_UNIT_FACING)
    set dat.caster = GetSpellAbilityUnit()
    
    if end == false then
        set ChainTowers[total + 1] = dat
        set total = total + 1
        //debug call DisplayTextToPlayer(Player(0),0,0, I2S(total))
    endif
    
endfunction

//===========================================================================
function InitTrig_Power_generator takes nothing returns nothing
    set gg_trg_Power_generator = CreateTrigger(  )
    call TriggerRegisterAnyUnitEventBJ( gg_trg_Power_generator, EVENT_PLAYER_UNIT_SPELL_EFFECT )
    call TriggerAddCondition( gg_trg_Power_generator, Condition( function Trig_Power_generator_Conditions ) )
    call TriggerAddAction( gg_trg_Power_generator, function Trig_Power_generator_Actions )
endfunction




function DieCond takes nothing returns boolean
    return GetUnitTypeId(GetTriggerUnit()) == &#039;nlps&#039;
endfunction

function Die_Actions takes nothing returns nothing
    local integer i = -1
    local boolean end = false
    local spell dat
    local unit x
    
    loop
        exitwhen i &gt; total 
        set i = i + 1
        set dat = ChainTowers<i>
        
        loop
            exitwhen FirstOfGroup(dat.towers) == null or end == true
            set x = FirstOfGroup(dat.towers)
            
            //if x == GetDyingUnit() then
             //   set end = true
           //     call DestroyLightning( dat.lightnings[GetUnitUserData(x)])
          //  endif
            
        endloop

    endloop
    
endfunction

//===========================================================================
function InitTrig_Die takes nothing returns nothing
    local trigger die = CreateTrigger(  )
    call TriggerRegisterAnyUnitEventBJ( die, EVENT_PLAYER_UNIT_DEATH )
    call TriggerAddCondition( die, Condition( function DieCond ) )
    call TriggerAddAction( die, function Die_Actions )
endfunction






function Conditions takes nothing returns boolean
    return GetSpellAbilityId() == &#039;ANr3&#039;
endfunction

function Actions takes nothing returns nothing
    local location l = GetSpellTargetLoc()
    local real x = GetLocationX(l)
    local real y = GetLocationY(l)
    local integer i = 0 
    local unit u = CreateUnit(GetOwningPlayer(GetSpellAbilityUnit()), &#039;nlps&#039;, x,y,bj_UNIT_FACING)
    local unit t
    local real AOE = (BaseAOE + (AOEPerLevel * GetUnitAbilityLevel(u,&#039;ANr3&#039;)))
    local group g= CreateGroup()
    local spell dat = spell.create()
    local boolean error = true
    local integer sid = 0
    
    // Find which struct has the data for this instance of the spell.
    loop 
    exitwhen i &gt; total 

        if dat.caster == GetSpellAbilityUnit() then
            set dat = ChainTowers<i>
            set error = false
        endif
    
    set i = i + 1
    endloop
    //Pick all the units near the tower. (So they can be linked)
    call GroupEnumUnitsInRangeOfLoc(g, l, AOE, null)
    //Initialize link struct, add to the link count.
    set dat.linkcount = dat.linkcount + 1
    set dat.links[dat.linkcount] = linkcollection.create()

    loop
        exitwhen FirstOfGroup(g) == null
        set t = FirstOfGroup(g)
            if (t != u) and (GetOwningPlayer(t) == GetOwningPlayer(u))  and ( (GetUnitTypeId(t) == &#039;ncfs&#039;)  or (GetUnitTypeId(t) == &#039;nlps&#039;)) then
                set dat.links[dat.linkcount].lcount = dat.links[dat.linkcount].lcount + 1 // Add to the &quot;lighnting&quot; count.
                debug call DisplayTextToPlayer(Player(0),0,0,&quot;Created lightning #: &quot; + I2S(dat.links[dat.linkcount].lcount) + &quot; on link #:&quot; + I2S(dat.linkcount) )
                call SetUnitVertexColor(t,0,0,255,255)
                //link them.
                call dat.links[dat.linkcount].add(u,t,dat.links[dat.linkcount].lcount)
                //yucky debug below.
                debug call CreateTextTagLocBJ( &quot;dat.links[&quot; + I2S(dat.links[dat.linkcount].lcount) + &quot;].u1&quot;, GetUnitLoc(u), 0, 10, 100, 100, 100, 0 )
                debug call CreateTextTagLocBJ( &quot;dat.links[&quot; + I2S(dat.links[dat.linkcount].lcount) + &quot;].u2[&quot; +I2S(dat.links[dat.linkcount].lcount) + &quot;]&quot;, GetUnitLoc(t), 0, 10, 100, 100, 100, 0 )
            endif
            
        call GroupRemoveUnit(g,t)
    endloop
    //add the tower we created to the tower group for the spell struct.
    if dat.towers == null then
        set dat.towers = CreateGroup()
    endif
    call GroupAddUnit(dat.towers, u)
    
endfunction

//===========================================================================
function InitTrig_Chain_Towers takes nothing returns nothing
    set gg_trg_Chain_Towers = CreateTrigger(  )
    call InitTrig_Power_generator()
    call TriggerRegisterAnyUnitEventBJ( gg_trg_Chain_Towers, EVENT_PLAYER_UNIT_SPELL_EFFECT )
    call TriggerAddCondition( gg_trg_Chain_Towers, Condition( function Conditions ) )
    call TriggerAddAction( gg_trg_Chain_Towers, function Actions )
endfunction

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

JASS:

library Enum

function GroupEnumUnitsInLine takes location point1, location point2, real AOE returns group
local group ex = CreateGroup()
local group g = CreateGroup()
local group old = CreateGroup()
local real count = 0
local real end = ( DistanceBetweenPoints(point1, point2) / 85.0)//&#039; 
local location l = point1
local unit u
local effect e
if point2 == null  then
//          debug call DisplayTextToPlayer(Player(0),0,0,&quot;location null&quot;)
endif
set e = AddSpecialEffect(&quot;Abilities\\Spells\\Orc\\LightningShield\\LightningShieldTarget.mdl&quot;,GetLocationX(point1),GetLocationY(point1))
call DestroyEffect(e) 
set e = AddSpecialEffect(&quot;Abilities\\Spells\\Orc\\LightningShield\\LightningShieldTarget.mdl&quot;,GetLocationX(point2),GetLocationY(point2))
call DestroyEffect(e) 
  loop
        exitwhen count &gt; end
        set l = PolarProjectionBJ(l, 50.00, AngleBetweenPoints(point1, point2))
        call GroupEnumUnitsInRangeOfLoc(ex,l,95,null)
        loop
            exitwhen FirstOfGroup(ex) == null
            set u = FirstOfGroup(ex)
            if IsUnitInGroup(u, old) != true then
                call GroupAddUnit(g,u)
            endif
            call GroupRemoveUnit(ex,u)
        endloop
        set count = count + 1
    endloop

    set ex = null
    set old = null
    set l = null
    return g
endfunction
endlibrary

 

Tamisrah

Active Member
Reaction score
16
Might sound stupid but what is it actually supposed to do? That'd probably help a lot ^^
 

Evan1993

Ultra Cool Member
Reaction score
30
You place towers next to each other making beams to damage units.

I havn't added the damage part yet becuase I'm having problems with picking the units as you can see in the screen shot.

The units tinted red are units that have been picked to be damaged.

Its a little more complex then that but I'm can/have got the rest to work.
 

PurgeandFire

zxcvmkgdfg
Reaction score
509
I don't know what's wrong, but since the thing actually seems... specific, I think that it isn't grouping the middle and bottom left lines. Are you sure your GroupEnumUnits...() thing is working correctly in those situations?
 

Tamisrah

Active Member
Reaction score
16
Hm all I can see right now is that you leak some groups in damage and in the enuminline function.
*ContinuesReading*

Edit: Whats that boolean error in the Actions function supposed to do?
If you'd find an existing instance you'll 'leak' the one you create on startup, but as far as I can tell that won't happen often since you don't loop through the instances. (the condition always returns false since you check the caster for a newly created instance)

Edit2: Seems like you haven't taken care of leaks yet (you'll leak some units and locations aswell) so I won't comment further on them ^^

And I can't quite tell how the actions thingy is connected to the powergenerator thingy from your code.
It seems like you create new instances without increasing the total but instead you increase total if the powergenerator spell is casted.
 

Evan1993

Ultra Cool Member
Reaction score
30
Whats that boolean error in the Actions function supposed to do?
If you'd find an existing instance you'll 'leak' the one you create on startup, but as far as I can tell that won't happen often since you don't loop through the instances. (the condition always returns false since you check the caster for a newly created instance)

Edit2: Seems like you haven't taken care of leaks yet (you'll leak some units and locations aswell) so I won't comment further on them ^^

And I can't quite tell how the actions thingy is connected to the powergenerator thingy from your code.
It seems like you create new instances without increasing the total but instead you increase total if the powergenerator spell is casted.

well I've changed my code a little... heres what I have now.

Not sure if I have a new problem now or if its the same old one.

JASS:

scope ChainTower


globals //&#039; Spell settings

    real BaseAOE = 500
    real AOEPerLevel = 100
    spell array ChainTowers
    integer total = -1 //used to tell if the trigger has been run or not.
    trigger gg_trg_Power_generator
    timer DmgInterval = CreateTimer()
endglobals

struct linkcollection

    lightning array l[20]
    integer lcount = 0
    integer rcount = 0
    unit u1 = null
    unit array u2[20]
  method add takes unit u1, unit u2, integer index returns nothing
      set this.u1 = u1
      set this.u2[index] = u2
      set this.l[index] = AddLightningEx(&quot;MBUR&quot;, true, GetUnitX(u1), GetUnitY(u1), 200, GetUnitX(u2), GetUnitY(u2), 200)
  endmethod
  
  method onDestroy takes nothing returns nothing
  local integer i = 0
  call DisplayTextToPlayer(Player(0),0,0,&quot;Destroying Ligtning Count: &quot; + I2S(.lcount))
  
  
  loop
  exitwhen i &gt; .lcount
  call DisplayTextToPlayer(Player(0),0,0,&quot;Removing gfx: &quot; + I2S(i))
  call DestroyLightning(.l<i>)
  set i = i + 1
  endloop
  set .u1 = null
  endmethod
  
endstruct

struct spell
    linkcollection array links [20]
    group towers = null
    integer linkcount = 0
    unit generator = null
    unit caster = null

  method onDestroy takes nothing returns nothing//&#039; Clean up.
    local integer i = 1
    local unit x
    
    loop
        exitwhen i &gt; .linkcount
        call DisplayTextToPlayer(Player(0),0,0,&quot;Destroying Link: &quot; + I2S(i))
        call .links<i>.destroy()
        set i = i + 1
    endloop
    
    loop
        exitwhen FirstOfGroup(.towers) == null
        set x = FirstOfGroup(.towers)
        call KillUnit(x)
        call GroupRemoveUnit(.towers, x)
    endloop
    
    call KillUnit(.generator)
    set .towers = null
    set .generator = null
    set x = null
    set total = total - 1
 endmethod
 
endstruct
private function damage takes nothing returns nothing
    local spell dat
    local group hurt = CreateGroup()
    local unit victim
    local integer i = 0 
    local integer i2 = 0
    local integer i3 = 0
    loop
    exitwhen i &gt; total 
    set dat = ChainTowers<i>
    
    loop
    exitwhen i3 &gt; dat.linkcount
    
        loop//&#039;*** LINK LOOP
        exitwhen i2 &gt; dat.links[i3].lcount
            
            //if dat.links[i2].u2[i2] != null then
                debug if (i2 &gt; 0 and i3 &gt; 0) and dat.links[i2].u2[i2] == null then
                    debug call DisplayTextToPlayer(Player(0),0,0,&quot;u2 Null on lightning: &quot; + I2S(i2) + &quot; Link: &quot; + I2S(i3) )
                    debug if dat.links[i2].u1 == null and (i2 &gt; 0 and i3 &gt; 0) then
                        debug call SetUnitVertexColor(dat.links[i2].u1,0,0,0,255)
                        debug call DisplayTextToPlayer(Player(0),0,0,&quot;u1 Null on lightning: &quot; + I2S(i2) + &quot; Link: &quot; + I2S(i3) )
                    debug endif
                debug endif
                set hurt = GroupEnumUnitsInLine(GetUnitLoc(dat.links[i2].u1), GetUnitLoc(dat.links[i2].u2[i2]), 0 )

                loop//&#039; UNIT GROUP LOOP
                exitwhen FirstOfGroup(hurt) == null
                        set victim = FirstOfGroup(hurt)
                        call SetUnitVertexColor(victim,255,0,0,255)
                        call GroupRemoveUnit(hurt,victim)
                endloop//&#039; END UNIT GROUP LOOP   
            //endif
            set i2 = i2 + 1
        endloop //&#039;** END LINK LOOP
        set i2 = 0
        set i3 = i3 + 1
    endloop
    set i = i + 1
    endloop
endfunction

//&#039; Power generator
function Trig_Power_generator_Conditions takes nothing returns boolean
    return GetSpellAbilityId() == &#039;ACbz&#039;
endfunction

function Trig_Power_generator_Actions takes nothing returns nothing
    local integer i = -1
    local location loc = GetSpellTargetLoc()
    local spell dat
    local unit gen
    local boolean end = false
    if total == -1 then
        call TimerStart(DmgInterval, 0.50,true, function damage)
        set total = 0
    endif
    
    loop
        exitwhen i &gt; total 
        set i = i + 1 // i starts at -1
        set dat = ChainTowers<i>
        
        if dat.caster == GetSpellAbilityUnit() then
            set end = true
            call dat.destroy()
        endif
        
    endloop

    set dat = spell.create()
    set dat.generator = CreateUnitAtLoc(GetOwningPlayer(GetSpellAbilityUnit()), &#039;ncfs&#039;, loc, bj_UNIT_FACING)
    set dat.caster = GetSpellAbilityUnit()
    
    if end == false then
        set total = total + 1
        set ChainTowers[total] = dat
        //debug call DisplayTextToPlayer(Player(0),0,0, I2S(total))
    endif
    
endfunction

//===========================================================================
function InitTrig_Power_generator takes nothing returns nothing
    set gg_trg_Power_generator = CreateTrigger(  )
    call TriggerRegisterAnyUnitEventBJ( gg_trg_Power_generator, EVENT_PLAYER_UNIT_SPELL_EFFECT )
    call TriggerAddCondition( gg_trg_Power_generator, Condition( function Trig_Power_generator_Conditions ) )
    call TriggerAddAction( gg_trg_Power_generator, function Trig_Power_generator_Actions )
endfunction




function DieCond takes nothing returns boolean
    return GetUnitTypeId(GetTriggerUnit()) == &#039;nlps&#039;
endfunction

function Die_Actions takes nothing returns nothing
    local integer i = -1
    local boolean end = false
    local spell dat
    local unit x
    
    loop
        exitwhen i &gt; total 
        set i = i + 1
        set dat = ChainTowers<i>
        
        loop
            exitwhen FirstOfGroup(dat.towers) == null or end == true
            set x = FirstOfGroup(dat.towers)
            
            //if x == GetDyingUnit() then
             //   set end = true
           //     call DestroyLightning( dat.lightnings[GetUnitUserData(x)])
          //  endif
            
        endloop

    endloop
    
endfunction

//===========================================================================
function InitTrig_Die takes nothing returns nothing
    local trigger die = CreateTrigger(  )
    call TriggerRegisterAnyUnitEventBJ( die, EVENT_PLAYER_UNIT_DEATH )
    call TriggerAddCondition( die, Condition( function DieCond ) )
    call TriggerAddAction( die, function Die_Actions )
endfunction






function Conditions takes nothing returns boolean
    return GetSpellAbilityId() == &#039;ANr3&#039;
endfunction

function Actions takes nothing returns nothing
    local location l = GetSpellTargetLoc()
    local real x = GetLocationX(l)
    local real y = GetLocationY(l)
    local integer i = 0 
    local integer index = 0
    local unit u = CreateUnit(GetOwningPlayer(GetSpellAbilityUnit()), &#039;nlps&#039;, x,y,bj_UNIT_FACING)
    local unit t
    local real AOE = (BaseAOE + (AOEPerLevel * GetUnitAbilityLevel(u,&#039;ANr3&#039;)))
    local group g = CreateGroup()
    local spell dat
    local boolean error = true
    local integer sid = 0
    
    // Find which struct has the data for this instance of the spell.
    loop 
    exitwhen i &gt; total or error == false
        set dat = ChainTowers<i>
        if dat.caster == GetSpellAbilityUnit() then
            set error = false
            set index = i
            call DisplayTextToPlayer(Player(0),0,0,&quot;yo.&quot;)
        endif
    
    set i = i + 1
    endloop
    
    if error == false then
    set dat = spell.create()
    endif
    
    //Pick all the units near the tower. (So they can be linked)
    call GroupEnumUnitsInRangeOfLoc(g, l, AOE, null)
    //Initialize link struct, add to the link count.
    set dat.linkcount = dat.linkcount + 1
    set dat.links[dat.linkcount] = linkcollection.create()

    loop
        exitwhen FirstOfGroup(g) == null
        set t = FirstOfGroup(g)
            if (t != u) and (GetOwningPlayer(t) == GetOwningPlayer(u))  and ( (GetUnitTypeId(t) == &#039;ncfs&#039;)  or (GetUnitTypeId(t) == &#039;nlps&#039;)) then
                set dat.links[dat.linkcount].lcount = dat.links[dat.linkcount].lcount + 1 // Add to the &quot;lighnting&quot; count.
                debug call DisplayTextToPlayer(Player(0),0,0,&quot;Created lightning #: &quot; + I2S(dat.links[dat.linkcount].lcount) + &quot; on link #:&quot; + I2S(dat.linkcount) )
                call SetUnitVertexColor(t,0,0,255,255)
                //link them.
                call dat.links[dat.linkcount].add(u,t,dat.links[dat.linkcount].lcount)
                //yucky debug below.
                debug call CreateTextTagLocBJ( &quot;dat.links[&quot; + I2S(dat.links[dat.linkcount].lcount) + &quot;].u1&quot;, GetUnitLoc(u), 0, 10, 100, 100, 100, 0 )
                debug call CreateTextTagLocBJ( &quot;dat.links[&quot; + I2S(dat.links[dat.linkcount].lcount) + &quot;].u2[&quot; +I2S(dat.links[dat.linkcount].lcount) + &quot;]&quot;, GetUnitLoc(t), 0, 10, 100, 100, 100, 0 )
            endif
            
        call GroupRemoveUnit(g,t)
    endloop
    //add the tower we created to the tower group for the spell struct.
    if dat.towers == null then
        set dat.towers = CreateGroup()
    endif
    call GroupAddUnit(dat.towers, u)
    set ChainTowers[index] = dat
endfunction

//===========================================================================
function InitTrig_Chain_Towers takes nothing returns nothing
    set gg_trg_Chain_Towers = CreateTrigger(  )
    call InitTrig_Power_generator()
    call TriggerRegisterAnyUnitEventBJ( gg_trg_Chain_Towers, EVENT_PLAYER_UNIT_SPELL_EFFECT )
    call TriggerAddCondition( gg_trg_Chain_Towers, Condition( function Conditions ) )
    call TriggerAddAction( gg_trg_Chain_Towers, function Actions )
endfunction

endscope
</i></i></i></i></i></i>
 
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