HomeUser Control Panel (unavailable in archive)ForumsTutorialsArt GalleryResourcesMaps

Bug with structs and MoveLightning

11-16-2007, 11:28 PM#1
Jazradel
I have a function that crashes when it gets to MoveLightning because for some reason or another my lightning doesn't really exist. GetLightningA, etc also crash. The only clue I have as to what's going wrong is the fact that H2I on the lightning returns the same number as the struct id.
The function I am having trouble with is called Remove, it's towards the bottom. Note that the RemoveLast, Move and MoveLast all work perfectly even though they're very similar.
Collapse JASS:
library RP initializer Init
//THESE ARE THE CONFIGURATION GLOBALS. IT IS SAFE TO TOUCH THESE IF YOU KNOW WHAT THEY DO
//===========================================================================

globals
    private constant integer Range = 70
    private constant integer Limit = 2147483456
endglobals

//DO NOT TOUCH ANYTHING BELOW THIS LINE
//===========================================================================

globals
    private trigger Trig_Train = CreateTrigger()
    private trigger Trig_Deselect = CreateTrigger()
    private trigger Trig_Select = CreateTrigger()
    private gamecache cache = InitGameCache("RP.w3v")
    private boolexpr BTrue
    private timer array TIMERS
    private integer TIMERS_N = 0
endglobals

// Attaching Stuff
private keyword UnitData
private keyword FlagData
private keyword OriginData
private keyword TypeData

private function H2I takes handle h returns integer
    return h
    return 0
endfunction

//! textmacro GetSet takes TYPE
private function Get$TYPE$Data takes handle h returns integer
    return GetStoredInteger(cache, I2S(H2I(h)), "$TYPE$"+SCOPE_PRIVATE)
endfunction

private function Set$TYPE$Data takes handle h, $TYPE$Data c returns nothing
    call StoreInteger(cache, I2S(H2I(h)), "$TYPE$"+SCOPE_PRIVATE, c)
endfunction

private function Flush$TYPE$Data takes handle h returns nothing
    call StoreInteger(cache, I2S(H2I(h)), "$TYPE$"+SCOPE_PRIVATE, 0)
endfunction
//! endtextmacro
//! runtextmacro GetSet("Unit")
//! runtextmacro GetSet("Flag")
//! runtextmacro GetSet("Origin")
//! runtextmacro GetSet("Type")

// CS Safety
private function NewTimer takes nothing returns timer  
    if (TIMERS_N==0) then  
        return CreateTimer()  
    endif  
    set TIMERS_N = TIMERS_N - 1 
    return TIMERS[TIMERS_N] 
endfunction 

private function ReleaseTimer takes timer t returns nothing  
    call PauseTimer(t)  
    set TIMERS[TIMERS_N] = t 
    set TIMERS_N = TIMERS_N + 1 
endfunction

// General
private function FTrue takes nothing returns boolean
    return true
endfunction

private function CloneGroup takes group g returns group
    set bj_groupAddGroupDest = CreateGroup()
    call ForGroup(g, function GroupAddGroupEnum)
    return bj_groupAddGroupDest
endfunction

// Struct Data

private struct UnitData
    OriginData o
    integer lastflag = 1
endstruct

private struct FlagData
    OriginData o
    unit flag
    integer no
    real x
    real y
    trigger t
    lightning l
    group units = CreateGroup()
    method onDestroy takes nothing returns nothing
        local unit u
        local UnitData ud
        loop
            set u  = FirstOfGroup(.units)
            exitwhen u == null
            call GroupRemoveUnit(.units, u)
            set ud = GetUnitData(u)
            call ud.destroy()
            call FlushUnitData(u)
        endloop
        call DestroyGroup(.units)
        call DestroyLightning(.l)
        call DestroyTrigger(.t)
        call RemoveUnit(.flag)
    endmethod
endstruct

private struct OriginData
    TypeData t
    integer flagno = 0
    group flags = CreateGroup()
    unit u
    method onDestroy takes nothing returns nothing
        local unit u
        local FlagData f
        loop
            set u = FirstOfGroup(.flags)
            exitwhen u == null
            call GroupRemoveUnit(.flags, u)
            set f = GetFlagData(u)
            call f.destroy()
        endloop
        call DestroyGroup(.flags)
    endmethod
endstruct

private struct TypeData
    integer flagid
    real rotation = 0
    string order = "attack"
    
    string ltype
    integer red = 1
    integer blue = 1
    integer green = 1
    
    group origins
    
    method onDestroy takes nothing returns nothing
        local unit u
        local OriginData o
        loop
            set u = FirstOfGroup(.origins)
            exitwhen u == null
            call GroupRemoveUnit(.origins, u)
            set o = GetOriginData(u)
            call o.destroy()
        endloop
        call DestroyGroup(.origins)
    endmethod
endstruct

//The Rally Point System

private function GetFlagXData takes OriginData o, integer i returns FlagData
    local group g = CloneGroup(o.flags)
    local unit u
    local FlagData f
    loop
        set u = FirstOfGroup(g)
        exitwhen u == null
        call GroupRemoveUnit(g, u)
        set f = GetFlagData(u)
        if f.no == i then
            return f
            exitwhen true
        endif
    endloop
    return 0
endfunction

public function Unregister takes unit u returns nothing
    local OriginData o = GetOriginData(u)
    call o.destroy()
endfunction

private function MoveToNextFlag takes nothing returns nothing
    local unit u = GetTriggerUnit()
    local trigger t = GetTriggeringTrigger()
    local UnitData ud = GetUnitData(u)
    local FlagData f = GetFlagData(t)
    if f.no < Limit then
        if ud.lastflag == f.no and ud.o == f.o then
            if f.no == ud.o.flagno then
                set f = GetFlagXData(ud.o, ud.lastflag)
                call GroupRemoveUnit(f.units, u)
                call ud.destroy()
                call FlushUnitData(u)
            else
                set f = GetFlagXData(ud.o, ud.lastflag)
                call GroupRemoveUnit(f.units, u)
                set ud.lastflag = ud.lastflag + 1
                set f = GetFlagXData(ud.o, ud.lastflag)
                call GroupAddUnit(f.units, u)
                call IssuePointOrder(u, ud.o.t.order, f.x, f.y)
            endif
        endif
    else
        set f = GetFlagXData(ud.o, ud.lastflag)
        call ud.destroy()
        call FlushUnitData(u)
    endif
    set u = null
    set t = null
endfunction

private function MoveToFirstFlag takes nothing returns nothing
    local unit u = GetTriggerUnit()
    local unit m
    local OriginData o = GetOriginData(u)
    local UnitData ud
    local FlagData f
    set m = GetTrainedUnit()
    if m == null then
        set m = GetSoldUnit()
        if m == null then
            set m = GetRevivingUnit()
        endif
    endif
    if Limit > 0 and o.flagno > 0 then
        set ud = UnitData.create()
        set ud.o = o
        call SetUnitData(m, ud)
        set f = GetFlagXData(o, 1)
        call GroupAddUnit(f.units, m)
        call IssuePointOrder(m, o.t.order, f.x, f.y)
    endif
    set u = null
    set m = null
endfunction

public function AddLast takes unit u, real x, real y returns integer
    local OriginData o = GetOriginData(u)
    local FlagData f
    local FlagData ft
    if o.flagno < Limit then
        set o.flagno = o.flagno + 1
        set f = FlagData.create() 
        set f.o = o
        set f.no = o.flagno
        set f.x = x
        set f.y = y
        if o.flagno > 1 then
            set ft = GetFlagXData(o, o.flagno-1)
            set f.l = AddLightning(o.t.ltype, false, ft.x, ft.y, x, y)
        else
            set f.l = AddLightning(o.t.ltype, false, GetUnitX(u), GetUnitY(u), x, y)
        endif
        call SetLightningColor( f.l, 0, 0, 0, 0)
        set f.flag = CreateUnit(GetOwningPlayer(u), o.t.flagid, x,  y, o.t.rotation)
        call ShowUnit(f.flag,false)
        if GetLocalPlayer() == GetOwningPlayer(u) then
            call ShowUnit(f.flag,true)
            call SetLightningColor( f.l, o.t.red, o.t.green, o.t.blue, 1)
        endif
        call GroupAddUnit(o.flags, f.flag)
        call SetFlagData(f.flag,f)
        set f.t = CreateTrigger()
        call TriggerAddAction(f.t, function MoveToNextFlag)               
        call TriggerRegisterUnitInRange(f.t, f.flag, Range, BTrue)
        call SetFlagData(f.t, f)
    endif
    return o.flagno
endfunction

public function RemoveLast takes unit u returns nothing
    local OriginData o = GetOriginData(u)
    local FlagData f
    if o.flagno > 0 then
        set f = GetFlagXData(o, o.flagno)
        call f.destroy()
        set o.flagno = o.flagno - 1
    endif
endfunction

public function RemoveAll takes unit u returns nothing
    local integer i = 0
    local OriginData o = GetOriginData(u)
    loop
        set i = i + 1
        exitwhen i > o.flagno
        call GetFlagXData(o, i).destroy()
    endloop
    set o.flagno = 0
endfunction

private function Select takes nothing returns nothing
    local integer i = 0
    local unit u = GetTriggerUnit()
    local OriginData o = GetOriginData(u)
    local FlagData f
    loop
        set i = i + 1
        exitwhen i > o.flagno
        if GetLocalPlayer() == GetOwningPlayer(u) then
            set f = GetFlagXData(o, i)
            call SetLightningColor( f.l, o.t.red, o.t.green, o.t.blue, 1)
            call ShowUnit( f.flag, true )
        endif
    endloop
    set u = null
endfunction

private function Deselect takes nothing returns nothing
    local integer i = 0
    local unit u = GetTriggerUnit()
    local OriginData o = GetOriginData(u)
    local FlagData f
    loop
        set i = i + 1
        exitwhen i > o.flagno
        set f = GetFlagXData(o, i)
        call SetLightningColor( f.l, 0, 0, 0, 0)
        call ShowUnit( f.flag, false )
    endloop
    set u = null
endfunction

private function Init takes nothing returns nothing
    call TriggerAddAction(Trig_Train, function MoveToFirstFlag)
    call TriggerAddAction(Trig_Select, function Select)
    call TriggerAddAction(Trig_Deselect, function Deselect)
    set BTrue = Condition(function FTrue)
endfunction

public function Register takes unit u, TypeData t returns boolean
    local OriginData o
    if GetOriginData(u) == 0 then
        set o = OriginData.create()
        //Order units when trained
        call TriggerRegisterUnitEvent( Trig_Train, u, EVENT_UNIT_SELL )
        call TriggerRegisterUnitEvent( Trig_Train, u, EVENT_UNIT_TRAIN_FINISH )
        call TriggerRegisterUnitEvent( Trig_Train, u, EVENT_UNIT_HERO_REVIVE_FINISH )
        //Show points when selected
        call TriggerRegisterUnitEvent( Trig_Select, u, EVENT_UNIT_SELECTED )
        call TriggerRegisterUnitEvent( Trig_Deselect, u, EVENT_UNIT_DESELECTED )
        //Set rp
        set o.u = u
        set o.t = t
        call SetOriginData(u, o)
        call GroupAddUnit(t.origins, u)
        return true
    endif
    return false
endfunction

public function Define takes integer flag, real rotation, string ltype, integer red, integer green, integer blue returns TypeData
    local TypeData t = TypeData.create()
    set t.flagid = flag
    set t.rotation = rotation
    set t.ltype = ltype
    set t.red = red
    set t.green = green
    set t.blue = blue
    return t
endfunction

public function IsRegistered takes unit u returns boolean
    if GetOriginData(u) > 0 then
        return true
    endif
    return false
endfunction

public function AddDefaultAbility takes unit u returns nothing
    call UnitRemoveAbility(u, 'ARal')
endfunction

public function RemoveDefaultAbility takes unit u returns nothing
    call UnitRemoveAbility(u, 'ARal')
endfunction

public function SetOrder takes TypeData t, string s returns nothing
    set t.order = s
endfunction

public function DestroyType takes TypeData t returns nothing
    call t.destroy()
endfunction

public function Remove takes unit u, integer i returns nothing
    local OriginData o = GetOriginData(u)
    local FlagData f
    local FlagData ft
    local integer n = i+1
    if i > 0 and i <= o.flagno  then
        set f = GetFlagXData(o, i)
        call f.destroy()
        if i < o.flagno then
            loop
                exitwhen n > o.flagno
                set ft = GetFlagXData(o, n)
                set ft.no = ft.no - 1
                set n = n + 1
            endloop
            set f = GetFlagXData(o, i)
            if i == 1 then
                call MoveLightning(f.l, false, GetUnitX(o.u), GetUnitY(o.u), f.x, f.y)
            else
                set ft = GetFlagXData(o, i-1)
                call MoveLightning(f.l, false, ft.x, ft.y, f.x, f.y)
            endif
        endif
        set o.flagno = o.flagno - 1
    endif
    set u = null
endfunction

public function Add takes unit u, integer i, real x, real y returns nothing
    local OriginData o = GetOriginData(u)
    local FlagData f
    local FlagData ft
    local integer n = i
    if i > 0 and i <= o.flagno  then
        loop
            exitwhen n > o.flagno
            set f = GetFlagXData(o, n)
            set f.no = f.no + 1
            set n = n + 1
        endloop
        set o.flagno = o.flagno + 1
        set f = FlagData.create()
        set f.o = o
        set f.no = i
        set f.x = x
        set f.y = y
        if i > 1 then
            set ft = GetFlagXData(o, i)
            set f.l = AddLightning(o.t.ltype, false,ft.x,ft.y,f.x,f.y)
            set ft = GetFlagXData(o, i+1)
            call MoveLightning(f.l, false, f.x, f.y, ft.x, ft.y)
        else
            set f.l = AddLightning(o.t.ltype, false,GetUnitX(u),GetUnitY(u),f.x,f.y)
            set ft = GetFlagXData(o, i+1)
            call MoveLightning(f.l, false, f.x, f.y, ft.x, ft.y)
        endif
        call SetLightningColor( f.l, 0, 0, 0, 0)
        set f.flag = CreateUnit(GetOwningPlayer(u), o.t.flagid, x,  y, o.t.rotation)
        call ShowUnit(f.flag,false)
        if GetLocalPlayer() == GetOwningPlayer(u) then
            call ShowUnit(f.flag,true)
            call SetLightningColor( f.l, o.t.red, o.t.green, o.t.blue, 1)
        endif
        call GroupAddUnit(o.flags, f.flag)
        call SetFlagData(f.flag,f)
        set f.t = CreateTrigger()
        call TriggerAddAction(f.t, function MoveToNextFlag)               
        call TriggerRegisterUnitInRange(f.t, f.flag, Range, BTrue)
        call SetFlagData(f.t, f)
    endif
    set u = null
endfunction

public function Move takes unit u, integer i, real x, real y returns nothing
    local OriginData o = GetOriginData(u)
    local FlagData f
    local FlagData ft
    if o.flagno > 0 and i <= o.flagno then
        set f = GetFlagXData(o, i)
        call SetUnitPosition(f.flag, x, y)
        set f.x = GetUnitX(f.flag)
        set f.y = GetUnitY(f.flag)
        if i == 1 then
            call MoveLightning(f.l, false, GetUnitX(o.u), GetUnitY(o.u), f.x, f.y )
        else
            set ft = GetFlagXData(o, i-1)
            call MoveLightning(f.l, false, ft.x, ft.y, f.x, f.y )
        endif
        set ft = GetFlagXData(o, i+1)
        call MoveLightning(ft.l, false, f.x, f.y, ft.x, ft.y )
        call DestroyTrigger(f.t)
        set f.t = CreateTrigger()
        call TriggerAddAction(f.t, function MoveToNextFlag)               
        call TriggerRegisterUnitInRange(f.t, f.flag, Range, BTrue)
        call SetFlagData(f.t, f)
    endif
endfunction

public function MoveLast takes unit u, real x, real y returns nothing
    local OriginData o = GetOriginData(u)
    local FlagData f 
    local FlagData ft
    if o.flagno > 0 then
        set f = GetFlagXData(o, o.flagno)
        call SetUnitPosition(f.flag, x, y)
        set f.x = GetUnitX(f.flag)
        set f.y = GetUnitY(f.flag)
        if o.flagno == 1 then
            call MoveLightning(f.l, false, GetUnitX(o.u), GetUnitY(o.u), f.x, f.y )
        else
            set ft = GetFlagXData(o, o.flagno-1)
            call MoveLightning(f.l, false, ft.x, ft.y, f.x, f.y )
        endif
        call DestroyTrigger(f.t)
        set f.t = CreateTrigger()
        call TriggerAddAction(f.t, function MoveToNextFlag)               
        call TriggerRegisterUnitInRange(f.t, f.flag, Range, BTrue)
        call SetFlagData(f.t, f)
    endif
endfunction

endlibrary
The map is also attached. And cohadar, this is not the place or the time to discuss how I attach stuff.

Edit: Fixed cohadar's name and added GetXData.
Edit2: Decided to uploaded the entire script, since no one was looking at the map.
Attached Files
File type: w3xRally Point System.w3x (31.9 KB)
11-17-2007, 02:28 AM#2
Vexorian
Tons of functions I am not seeing, like GetOriginData, GetFlagData , etc. So I can't really debug this.
11-17-2007, 04:05 AM#3
cohadar
Ok I will not talk about attaching here.

But in case you want to know why your code crashes send me a PM
and we will talk about attaching and a little about spelling.
11-17-2007, 05:40 AM#4
Jazradel
As I said, SetXData and GetXData were simply attaching via gamecache. They'rein the map, but I'll put them up here in a sec.

I know attaching stuff isn't the problem anyway, since it gets the structs correctly. It just doesn't refer to the lightning properly.

Sorry for spelling your name wrong, cohadar.

Edit: Changed their to they're.
11-17-2007, 10:26 AM#5
cohadar
Expand JASS:

@Vexorian: How did you come up with that DO NOT USE THIS list?
11-17-2007, 10:48 AM#6
Tide-Arc Ephemera
Testing... most probably...
11-17-2007, 11:46 AM#7
Vexorian
Cohadar: he is not using CSData.

--

You are creating the lightning for the Local Player but then you move the lightning regardless of who you created it for... Try creating the lightning for everyone and set it to invisible or only move the lightning to the player that is supposed to have it.
11-17-2007, 12:35 PM#8
cohadar
I know he is not using CSData, what am I blind?

But he is using lightning attaching so I thought to give him a hint.
11-17-2007, 12:40 PM#9
masda70
Quote:
Originally Posted by cohadar
Expand JASS:

@Vexorian: How did you come up with that DO NOT USE THIS list?

There is a limit in the number of texttags you can create; applying H2I on them will always return an integer between 0 and 100. The rest are probably similar. For the 'argument' types, the explanation is simple: they are special flags not meant to point instanceable objects.
11-17-2007, 01:51 PM#10
cohadar
So basically those are not real handles.
11-17-2007, 07:23 PM#11
Silvenon
Yes, PLAYER_STATE_SOMETHING, EVENT_SOMETHING, DAMAGE_TYPE_SOMETHING don't look like real handles to me, just some crappy integers (which they basically are), so using ints as handles.......bad.
11-17-2007, 08:46 PM#12
Jazradel
No of the posts below mine make any sense to me, excepts Vex's. However, that's not the problem because I just fixed that and it still crashes and I can move it in other functions without a crash.
11-17-2007, 09:17 PM#13
cohadar
This is all happening because you are not using ABC....


...

Why the fuck don't we have an evil smiley on this forum?
11-17-2007, 09:36 PM#14
Jazradel
........................................__.......................................................... ....
.................................,-~*’`¯lllllll`*~,.................................................
...........................,-~*`lllllllllllllllllllllllllll¯`*-,.....................................
......................,-~*llllllllllllllllllllllllllllllllllllllllllll*-,..............................
..................,-*llllllllllllllllllllllllllllllllllllllllllllllllllllll.\............................
................;*`lllllllllllllllllllllllllll,-~*~-,llllllllllllllllllll\...........................
................\lllllllllllllllllllllllllll/...........\;;;;llllllllllll,-`~-,.........................
.................\lllllllllllllllllllll,-*.............`~-~-,...(.(¯`*,`,..........................
...................\llllllllllll,-~*........................)_-\..*`*;..)...........................
.....................\,-*`¯,*`)............,-~*`~................../...............................
.....................|/.../.../~,......-~*,-~*`;.................../.\..............................
.................../.../..../..../..,-,..*~,.`*~*..................*...\.............................
...................|.../.../..../.*`...\................................)....)¯`~,....................
...................|./..../..../........).........)`*~-,............../.....|..)...`~-,..............
.................././.../....,*`-,.....`-,....*`....,---......\...../...../..|..........¯```*~-,,,,
.................(............)`*~-,.....`*`.,-~*.,-*.......|.../..../..../...............\..........
..................*-,.......`*-,...`~,..``.,,,-*.............|.,*...,*....|.................\.........
......................*,.........`-,....)-,..................,-*`...,-*.....(`-,..............\........
........................f`-,........`-,/...*-,___,,-~*.....,-*......|....`-,...............\.......


I know the problem isn't to do with attaching stuff. All the other data on the struct works perfectly and the lightning works perfectly when refered to in other functions.

Edit: Hmmm, thats a terrible face palm guy. BRB finding a better one.
Edit2: That's slightly better.
11-18-2007, 10:08 AM#15
Silvenon
Have you checked if the lightning is even created? Because there are some issues (at least with me) with the checkVisibility boolean parameter (in lightning functions). Instead of setting that boolean to false, try setting it's alpha to 0 (this most probably isn't the problem, but still try).

Btw, just outta curiosity, why do you do this:

Collapse JASS:
if something then
    call DoSomething()
    call DoSomethingElse()
else
    call DoSomething()
endif

instead of this:

Collapse JASS:
if something then
    call DoSomethingElse()
endif
call DoSomething()

Saves you space.