System Track Unit Movement System

Azlier

Old World Ghost
Reaction score
461
>HandleId are never the same and never recycled.

Wrong. They're recycled all the time.

GetHandleId and hashtables on units is a terrible idea. Use AIDS properly.
 

uberfoop

~=Admiral Stukov=~
Reaction score
177
yes that works but then say a unit dies with the integer 2 attached to it how would i recycle it and use it again and all that stuff
By using AIDS structs. You know, like, setting a struct up to be created and destroyed upon unit creation and destruction. So that you can clear the data properly.

The issue now is that the unit id gets recycled and the new unit gets the id of the old one. This would not be a problem if the data was stored in blocks that get cleared when the unit they're attached to is removed, but your system doesn't do that.


Hence, use AIDS to store data in AIDS structs.
 

kingkingyyk3

Visitor (Welcome to the Jungle, Baby!)
Reaction score
216
JASS:
library UnitTracking initializer Init requires AIDS
    
    globals
        private constant real PERIOD = .03125
    endglobals
    
    private struct Data extends array
        real bx
        real by
        real nx
        real ny
        real dis
        real totaldis
        boolean stoptrack
        
        private thistype next
        private thistype prev
        private static real dx
        private static real dy
        
        //From T32, =D
        static method PeriodicLoop takes nothing returns nothing
            local thistype this=thistype(0).next
            loop
                exitwhen this==0
                if not this.stoptrack then
                    set this.bx = this.nx
                    set this.by = this.ny
                    set this.nx = GetUnitX(this.unit)
                    set this.ny = GetUnitY(this.unit)
                    set thistype.dx = this.nx - this.bx
                    set thistype.dy = this.ny - this.by
                    set this.dis = SquareRoot(thistype.dx * thistype.dx + thistype.dy * thistype.dy)
                    set this.totaldis = this.totaldis + this.dis
                else
                    // This is some real magic.
                    set this.prev.next=this.next
                    set this.next.prev=this.prev
                    // This will even work for the starting element.
                    debug set this.prev=0
                endif
                set this=this.next
            endloop
        endmethod
               
        method startTracking takes nothing returns nothing
            set this.stoptrack = false
            set thistype(0).next.prev=this
            set this.next=thistype(0).next
            set thistype(0).next=this
            set this.prev=thistype(0)
        endmethod
        //
        
        private method AIDS_onCreate takes nothing returns nothing
            set this.bx = 0.
            set this.by = 0.
            set this.nx = 0.
            set this.ny = 0.
            set this.dis = 0.
        endmethod
        
        private method AIDS_onDestroy takes nothing returns nothing
            set this.stoptrack = true  
        endmethod
        
        //! runtextmacro AIDS()
    endstruct
        
    globals
        private Data d
    endglobals
    
    function TrackUnitMovement takes unit whichunit returns nothing
        set d = Data[whichunit]
        if d.stoptrack then
            call d.startTracking()
        endif
    endfunction

    function StopTrackingUnit takes unit whichunit returns nothing
        set Data[whichunit].stoptrack = true
    endfunction
   
    function IsUnitMoving takes unit whichunit returns boolean
        set d = Data[whichunit]
        return d.dis != 0.
    endfunction
    
    function GetUnitMovingAngle takes unit whichunit returns real
        set d = Data[whichunit]
        return 57.2958 * (Atan2(d.ny - d.by, d.nx - d.bx))
    endfunction
    
    function GetUnitMovingDistance takes unit whichunit returns real
        return Data[whichunit].dis
    endfunction
    
    function GetUnitTotalMovingDistance takes unit whichunit returns real
        return Data[whichunit].totaldis
    endfunction
    
    function ResetUnitDistance takes unit whichunit returns nothing
        set Data[whichunit].totaldis = 0.
    endfunction
    
    private function Init takes nothing returns nothing
        call TimerStart(CreateTimer(),PERIOD,true,function Data.PeriodicLoop)
    endfunction
endlibrary


This is more efficient. Uses T32 and AIDS. T32 has a onInit function which collides with AIDS, so I had modify it.
 

Gtam

Lerning how to write and read!! Yeah.
Reaction score
164
Okay i added uberfoops trigger and showed what you must not do.
I cant fix it since i dont uderstand strucks properly and even less AIDS structs. It was fun when i started creating this system but now with the problem i have to first understand the things i need to do and im not going to waste the 2 days of vacation i have left to try and fix it. If its GYed oh well. I Had fun creating it.
 

uberfoop

~=Admiral Stukov=~
Reaction score
177
Uh, you didn't show anything. The reason my trigger breaks your system is because a unit gets reassigned an earlier index. That has nothing to do with using RemoveUnit versus KillUnit, or which global variable you store a unit to. It's a flaw that would cause your system to bug in any map that doesn't recycle units ie almost all of them. The only reason I used RemoveUnit was to allow the index to be recycled faster.

And really, never post fixes to a system without rigorously testing them. This proves both of your 'fixes' to fix nothing:

edit: removed this code because it was errored
 

Gtam

Lerning how to write and read!! Yeah.
Reaction score
164
When i use kill unit the second units distnace is 0 and when i use a diffrent variable also 0
 

uberfoop

~=Admiral Stukov=~
Reaction score
177
When i use kill unit the second units distnace is 0 and when i use a diffrent variable also 0

Then impliment my code in your test map with the new code. I just tested it, and it bugs.

edit: one sec, revising code, made an error.

Edit:
Okay. Here is the code that breaks your system. Replace my code in your map with this, and observe the breakage:

JASS:

scope THISBREAKSGTAMSSYSTEM initializer SHAMWOW
globals
    unit EL_MAN
    unit THE_OTHER_MAN
endglobals

function LOLWUT takes nothing returns nothing
    call BJDebugMsg(R2S(GetUnitTotalMovingDistance(THE_OTHER_MAN)))
endfunction

function LOLCATS takes nothing returns nothing
    set THE_OTHER_MAN = CreateUnit(Player(0),'hfoo',0,0,0)
    call TimerStart(CreateTimer(),1,true,function LOLWUT)
    call TrackUnitMovement(THE_OTHER_MAN)
endfunction

function SLAPCHOP takes nothing returns nothing
    call KillUnit(EL_MAN)
    call TimerStart(CreateTimer(),100,false,function LOLCATS)
endfunction

function SHAMWOW takes nothing returns nothing
    set EL_MAN = CreateUnit(Player(0),'hfoo',0,0,0)
    call IssuePointOrder(EL_MAN,"move",0,1000)
    call TimerStart(CreateTimer(),5,false,function SLAPCHOP)
    call TrackUnitMovement(EL_MAN)
endfunction
endscope
 

Gtam

Lerning how to write and read!! Yeah.
Reaction score
164
gettriggerunit: if i do that by setting the global to 0 when a unti dies it would render the getunittotalmovingdistance function useless.
 

Gtam

Lerning how to write and read!! Yeah.
Reaction score
164
Okay i added functions to prevent the bug uberfoop pointed out, gave me, i halfed fixed, he change the code, i needed new fix. so here
 

uberfoop

~=Admiral Stukov=~
Reaction score
177
You didn't fix anything, all you did was monopolize on two natives.
Even if your wrappers are used, the system will still bug in most cases, since a lot of deaths in wc3 aren't triggered at all.


Stop putting band aids on your Jass. If you don't start using AIDS structs, this system is hopeless.




Demonstration of up-to-date system break without using the KillUnit or RemoveUnit natives directly (aka, demonstration of system still being broken):
 

Attachments

  • TUMS.w3x
    43.5 KB · Views: 257

Gtam

Lerning how to write and read!! Yeah.
Reaction score
164
yea im not around aloy lately but i noticed what you are saying before reading you post. I have an update to the system that will not require AIDS at all anymore and fix the distance thing that you keep breaking :(. It will be up in 40 min. And the two functions that i added wi be removed.
 

Gtam

Lerning how to write and read!! Yeah.
Reaction score
164
i know dont point it out it was longer than 40 min but hey look on the bright side .......... Im sorry the is no bright side oh well look on the bright side wait didnt we just say there is no bright side yes we did oh well look on the first post haha. The new version is released plz coment on how it is since its my first hashtable use.
 

Azlier

Old World Ghost
Reaction score
461
Why not just use AIDS properly?

People have been begging you to do this for weeks.
 

Gtam

Lerning how to write and read!! Yeah.
Reaction score
164
in my opinion this is better and doesnt use extra systems so if you have another indexing system than AIDS you will have to switch so this is better for me.
 

Azlier

Old World Ghost
Reaction score
461
Why do people insist on using the unsafe and slower GetHandleId and hashtables over a unit indexer? This system is even more unsafe than before. Or maybe it's the same, just slower. I forget what the previous code looked like.

This system independence craze is ruining lots of code.
 

kingkingyyk3

Visitor (Welcome to the Jungle, Baby!)
Reaction score
216
I will use struct if hashtable is used. It saves the calling of functions.
 
General chit-chat
Help Users
  • No one is chatting at the moment.

      The Helper Discord

      Staff online

      Members online

      Affiliates

      Hive Workshop NUON Dome World Editor Tutorials

      Network Sponsors

      Apex Steel Pipe - Buys and sells Steel Pipe.
      Top