System Track Unit Movement System

Gtam

Lerning how to write and read!! Yeah.
Reaction score
164
Track Unit Movement System Created by Gtam

Requires:
NewGen
AIDS by Jesus4Lyf

JASS:
//=========================================================================================\\
//=========================================================================================\\
//==   _______    __   __    ___    ___     ______                                       ==\\
//==  |___ ___|  |  | |  |  |   \  /   |  /  _____    //================\\               ==\\
//==     | |     |  | |  |  |  \ \/ /  |  | |_____    //= Track Unit ===\\               ==\\
//==     | |     |  | |  |  |  |\  /|  |  \_____  \   //= Movement =====\\               ==\\
//==     | |     |  |_|  |  |  | \/ |  |   ______ |   //= System v1.07 =\\               ==\\
//==     |_|     \_______/  |__|    |__|  \_______/   //================\\               ==\\
//==                                                                                     ==\\
//==                                                                                     ==\\
//== Track Unit Movement System is a system that keeps track of how far unit unit has    ==\\
//== travelled for a long and short period and can say if a unit is currently moving and ==\\
//== in which direction.                                                                 ==\\
//==                                                                                     ==\\
//== The Functions for you                                                               ==\\
//==                                                                                     ==\\
//==   TrackUnitMovement() takes unit whichUnit returns nothing                          ==\\
//==    This function adds a unit to the system                                          ==\\
//==                                                                                     ==\\
//==   StopTrackingUnit() takes unit whichUnit, boolean long returns nothing             ==\\
//==    This function removes the unit from the system                                   ==\\
//==                                                                                     ==\\
//==   IsUnitMoving() takes unit whichUnit returns boolean                               ==\\
//==    This function will return true if a unit is moving and false if not              ==\\
//==                                                                                     ==\\
//==   GetUnitMovingAngle() takes unit whichUnit returns real                            ==\\
//==    This function will return the angle the unit is moving in                        ==\\
//==                                                                                     ==\\
//==   GetUnitMovingDistance() takes unit whichUnit returns real                         ==\\
//==    This function returns the units moving distance since being added                ==\\
//==                                                                                     ==\\
//==   GetUnitTotalMovingDistance() takes unit whichUnit returns real                    ==\\
//==    This function returns the units moving distance since being added and cannot be  ==\\
//==    reseted                                                                          ==\\
//==                                                                                     ==\\
//==   ResetUnitMovingDistance() takes unit whichUnit returns nothing                    ==\\
//==    This set the units moving distance to 0                                          ==\\
//==                                                                                     ==\\
//=========================================================================================\\
//=========================================================================================\\
library TUMS initializer Init requires AIDS
    
    struct TUMS extends array
        //! runtextmacro AIDS()
        
        real ox
        real oy
        real nx
        real ny
        real Distance
        
        method AIDS_onCreate takes nothing returns nothing
            set this.ox = 0.
            set this.oy = 0.
            set this.nx = 0.
            set this.ny = 0.
            set this.Distance = 0.
        endmethod
    endstruct
        
    globals
        private constant real PeriodicMovementCheck = .03125
        private real x
        private real y
        private real Squareroot
        private unit P
        private group TrackUnits = CreateGroup()
    endglobals

    function TrackUnitMovement takes unit whichUnit returns nothing
        if IsUnitInGroup( whichUnit, TrackUnits) == false then
            call GroupAddUnit( TrackUnits, whichUnit)
        endif
    endfunction

    function StopTrackingUnit takes unit whichUnit returns nothing
        if IsUnitInGroup( whichUnit, TrackUnits) == true then
            call GroupRemoveUnit( TrackUnits, whichUnit)
        endif
    endfunction
   
    function IsUnitMoving takes unit whichUnit returns boolean
        local TUMS d = TUMS[whichUnit]
        local real dx = d.nx - d.ox
        local real dy = d.ny - d.oy
        if SquareRoot(dx * dx + dy * dy) > 0 then
            return true
        else
            return false
        endif
    endfunction
    
    function GetUnitMovingAngle takes unit whichUnit returns real
        local TUMS d = TUMS[whichUnit]
        return 57.2958 * (Atan2(d.ny - d.oy, d.nx - d.ox))
    endfunction
    
    function GetUnitMovingDistance takes unit whichUnit returns real
        return TUMS[whichUnit].Distance
    endfunction
    
    function ResetUnitDistance takes unit whichUnit returns nothing
        set TUMS[whichUnit].Distance = 0
    endfunction
    
    private function TUMS_Group takes nothing returns nothing
        local TUMS d = TUMS[GetEnumUnit()]
        local real dx
        local real dy
        set P = GetEnumUnit()
        set x = GetUnitX(P)
        set y = GetUnitY(P)
        set dx = x - d.nx
        set dy = y - d.ny
        set Squareroot = SquareRoot(dx * dx + dy * dy)
        if IsUnitType (P, UNIT_TYPE_DEAD) == false then
            if Squareroot <= 35 then
                set d.Distance = d.Distance + Squareroot
            endif
            set d.ox = d.nx
            set d.oy = d.ny
            set d.nx = x
            set d.ny = y
        else
            call StopTrackingUnit(P)
        endif
    endfunction
    
    private function TUMS_Actions takes nothing returns nothing
        call ForGroup( TrackUnits, function TUMS_Group )
    endfunction
    
    private function Init takes nothing returns nothing
        call TimerStart( CreateTimer(), PeriodicMovementCheck, true, function TUMS_Actions)
    endfunction
endlibrary


A nice example of use is in the DemoMap

Code:
ChangeLog
v1.00 Released
v1.01 Uses Variable for picked unit and stops teleporting as counting.
v1.02 Updated to everyones suggestions
v1.03 Show what you must not do.
v1.04 New functions to prevent stuff ups
v1.05 No AIDS uses hashtable
v1.06 Now uses AIDS Structs and no hashtables.
v1.07 Little update
 

Attachments

  • TUMS.w3x
    268.4 KB · Views: 261

Flare

Stops copies me!
Reaction score
662
You've got a large number of GetEnumUnit (28, from a quick count), GetUnitX and GetUnitY (5 of each, I think) calls within your group callback function - store the values in variables instead.

Also, GetUnitMoving -> IsUnitMoving - seems more appropriate. If you compare to most native functions that return a boolean, they are generally worded with Is (e.g. IsUnitEnemy, IsUnitType, etc.)

Also, a maximum threshold on how much distance constitutes as movement would be nice (a value of 35 or so would be a reasonable default). People may not want to count teleportation as movement, and adding a threshold will allow a reasonable ability to distinguish between teleporting and sliding/walking (since teleporting less than 35 units of distance would be difficult, whereas sliding/walking less than 35 units of distance in 0.03125sec timeframe would be easily possible)

Also, why are you returning GetUnitMovingAngle in degrees? From what I recall, there is only one native function that requires an angle value in degrees (SetUnitFacing), so it just seems silly to return the value that would have the least use
 

kingkingyyk3

Visitor (Welcome to the Jungle, Baby!)
Reaction score
216
If the tracked unit is removed from game, the group will keep reference to it. You should refresh it.
 

Narks

Vastly intelligent whale-like being from the stars
Reaction score
90
JASS:

//==   GetUnitMovingAnle() takes unit whichUnit returns real                             ==\\
//==   GetUnitTotalMovingDitance(0 takes unit whichUnit returns real                     ==\\


spelling errors
 

Gtam

Lerning how to write and read!! Yeah.
Reaction score
164
Ok it bother me that the first thing you notice about a system is spelling and flare i will get on that.
 

Gtam

Lerning how to write and read!! Yeah.
Reaction score
164
Okay but would this work for dead units

JASS:
private function TUMS_Group takes nothing returns nothing
        set Picked = GetEnumUnit()
        if IsUnitAliveBJ(GetEnumUnit()) == true then
            if SquareRoot((nx[GetUnitIndex(Picked)] - GetUnitX(Picked)) * (nx[GetUnitIndex(Picked)] - GetUnitX(Picked)) + (ny[GetUnitIndex(Picked)] - GetUnitY(Picked)) * (ny[GetUnitIndex(Picked)] - GetUnitY(Picked))) <= 35 then
                set Distance[GetUnitIndex(Picked)] = Distance[GetUnitIndex(Picked)] + SquareRoot((nx[GetUnitIndex(Picked)] - GetUnitX(Picked)) * (nx[GetUnitIndex(Picked)] - GetUnitX(Picked)) + (ny[GetUnitIndex(Picked)] - GetUnitY(Picked)) * (ny[GetUnitIndex(Picked)] - GetUnitY(Picked)))
                set TotalDistance[GetUnitIndex(Picked)] = TotalDistance[GetUnitIndex(Picked)] + SquareRoot((nx[GetUnitIndex(Picked)] - GetUnitX(Picked)) * (nx[GetUnitIndex(Picked)] - GetUnitX(Picked)) + (ny[GetUnitIndex(Picked)] - GetUnitY(Picked)) * (ny[GetUnitIndex(Picked)] - GetUnitY(Picked)))
            endif
            set ox[GetUnitIndex(Picked)] = nx[GetUnitIndex(Picked)]
            set oy[GetUnitIndex(Picked)] = ny[GetUnitIndex(Picked)]
            set nx[GetUnitIndex(Picked)] = GetUnitX(Picked)
            set ny[GetUnitIndex(Picked)] = GetUnitY(Picked)
        else
            set Alive[GetUnitIndex(Picked)] = Alive[GetUnitIndex(Picked)] + 1
            if Alive[GetUnitIndex(Picked)] == 160 then
                call StopTrackingUnit(Picked)
                set Alive[GetUnitIndex(Picked)] = 0
            endif
        endif
    endfunction
 

GetTriggerUnit-

DogEntrepreneur
Reaction score
129
[del][lJASS]IsUnitAliveBJ(whichUnit)[/lJASS][/del]
[lJASS]GetUnitState(whichUnit, UNIT_STATE_LIFE) > 0.00[/lJASS]

Why don't you use a group-loop instead of ForGroup?
 

Flare

Stops copies me!
Reaction score
662
[del][lJASS]IsUnitAliveBJ(whichUnit)[/lJASS][/del]
[lJASS]GetUnitState(whichUnit, UNIT_STATE_LIFE) > 0.00[/lJASS]
Strictly speaking, [ljass]IsUnitType (whichUnit, UNIT_TYPE_DEAD) == false[/ljass] is more accurate. Health can be, unintentionally, added to a dead unit (all it takes it a simple mistake in enumeration, for example) which would cause a GetUnitState (and GetWidgetLife) check to return the incorrect result (since the unit would, in reality, be dead, but their health value would be greater than 0), whereas a dead unit will always be classified as UNIT_TYPE_DEAD

Why don't you use a group-loop instead of ForGroup?
For a FirstOfGroup loop (which is what I assume you mean by group loop), you are required to remove units from the group to continue iterating through the group (since FirstOfGroup will constantly remove the same unit, unless the unit is removed from the group), which is pointless since you're going to need those units again once the trigger next executes :D

Also, you've still got excess calls - GetUnitIndex, as J4L has already pointed out, and GetUnitX/Y are still being called to excess. I believe you could also store the square root value too (the parameters used appear to be indentical in both cases, so why call it twice when you can call it once :))

JASS:
            set Alive[GetUnitIndex(Picked)] = Alive[GetUnitIndex(Picked)] + 1
            if Alive[GetUnitIndex(Picked)] == 160 then
                call StopTrackingUnit(Picked)
                set Alive[GetUnitIndex(Picked)] = 0
            endif

May I ask what the point of this is? Seems like a very weird way of delaying system removal...
 

GetTriggerUnit-

DogEntrepreneur
Reaction score
129
Well use 2 group variables and then

e.g. the variable Units1 contains the units wanted.
[lJASS]set Units2 = Units1[/lJASS]
then you just ForGroupLoop with Units2...

Oh and for the [lJASS]GetUnitState[/lJASS], when you check how [lJASS]IsUnitAliveBJ[/lJASS] is made, you see [lJASS]GetUnitState[/lJASS].
 

Gtam

Lerning how to write and read!! Yeah.
Reaction score
164
If a unit has reincarnation i give it 5 seconds or its removed
 

Flare

Stops copies me!
Reaction score
662
JASS:
set Units2 = Units1

That won't work either - Units1 and Units2 are only pointers. They are not the handles themselves. So, if you modify Units1, it will also modify Units2 (since they point to the same handle). If you GroupRemoveUnit (Units1, whichUnit), Units2 no longer possesses that unit.

As it stands, a ForGroup is probably the best solution (since using an enumeration filter is a no-go due to the lack of enumeration within the system) and a FirstOfGroup loop is less efficient and impractical, by comparison.

then you just ForGroupLoop with Units2...
I think you meant to say a FirstOfGroup loop, since ForGroup is already being used.

At any rate, I suggest that the current group handling mechanism stays put. It's a simple, yet practical, solution and it works.

Oh and for the GetUnitState, when you check how IsUnitAliveBJ is made, you see GetUnitState.
Can you say, without any doubt, that Blizzard haven't made any mistakes whatsoever with JASS?

If a unit has reincarnation i give it 5 seconds or its removed
If the unit has reincarnation I think it's not considered as dead
(1) Dead units can still be revived (particularly Heroes, they've got quite a knack for bringing themselves back ;)) so I wouldn't suggest that you remove them shortly after death. When a unit is completely removed from the game, then they should be cleared from the system. I get the feeling that the AIDS_onDestroy method is called when units are completely removed, so it may be worth your while looking into that.

(2) That'd be something to check out GetTriggerUnit - anyone care to test and/or confirm this?
 

Gtam

Lerning how to write and read!! Yeah.
Reaction score
164
so a reincarnated unit would classify as dead??
 

Gtam

Lerning how to write and read!! Yeah.
Reaction score
164
Yes i have to make some coffee untill someone has the anwser. haha koking ill test it.

Edit: Okay everything updated and should work properly.
 

uberfoop

~=Admiral Stukov=~
Reaction score
177
How to break Gtam's system if placed in his demo map:
JASS:

scope THISBREAKSGTAMSSYSTEM initializer SHAMWOW
globals
    unit EL_MAN
endglobals

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

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

function SLAPCHOP takes nothing returns nothing
    call RemoveUnit(EL_MAN)
    call TimerStart(CreateTimer(),5,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


Note the manner in which the second man created starts up with the same total distance counter that the first man left off with, as demonstrated by the BJDebugMsg.




If you're going to require AIDS, please actually use it, especially seeing as how it would make this system actually work.
 

Gtam

Lerning how to write and read!! Yeah.
Reaction score
164
What do you mean that i actulay need to use aids. I dont see what i could do to fix this i tried everything that might change the result but it still shows the old units distance
 

Gtam

Lerning how to write and read!! Yeah.
Reaction score
164
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
 
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