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: 265

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.
  • WildTurkey WildTurkey:
    is there a stephen green in the house?
    +1
  • The Helper The Helper:
    What is up WildTurkey?
  • The Helper The Helper:
    Looks like Google fixed whatever mistake that made the recipes on the site go crazy and we are no longer trending towards a recipe site lol - I don't care though because it motivated me to spend alot of time on the site improving it and at least now the content people are looking at is not stupid and embarrassing like it was when I first got back into this like 5 years ago.
  • The Helper The Helper:
    Plus - I have a pretty bad ass recipe collection now! That section of the site is 10 thousand times better than it was before
  • The Helper The Helper:
    We now have a web designer at my job. A legit talented professional! I am going to get him to redesign the site theme. It is time.
  • Varine Varine:
    I got one more day of community service and then I'm free from this nonsense! I polished a cop car today for a funeral or something I guess
  • Varine Varine:
    They also were digging threw old shit at the sheriff's office and I tried to get them to give me the old electronic stuff, but they said no. They can't give it to people because they might use it to impersonate a cop or break into their network or some shit? idk but it was a shame to see them take a whole bunch of radios and shit to get shredded and landfilled
  • The Helper The Helper:
    whatever at least you are free
  • Monovertex Monovertex:
    How are you all? :D
    +1
  • Ghan Ghan:
    Howdy
  • Ghan Ghan:
    Still lurking
    +3
  • The Helper The Helper:
    I am great and it is fantastic to see you my friend!
    +1
  • The Helper The Helper:
    If you are new to the site please check out the Recipe and Food Forum https://www.thehelper.net/forums/recipes-and-food.220/
  • Monovertex Monovertex:
    How come you're so into recipes lately? Never saw this much interest in this topic in the old days of TH.net
  • Monovertex Monovertex:
    Hmm, how do I change my signature?
  • tom_mai78101 tom_mai78101:
    Signatures can be edit in your account profile. As for the old stuffs, I'm thinking it's because Blizzard is now under Microsoft, and because of Microsoft Xbox going the way it is, it's dreadful.
  • The Helper The Helper:
    I am not big on the recipes I am just promoting them - I use the site as a practice place promoting stuff
    +2
  • Monovertex Monovertex:
    @tom_mai78101 I must be blind. If I go on my profile I don't see any area to edit the signature; If I go to account details (settings) I don't see any signature area either.
  • The Helper The Helper:
    You can get there if you click the bell icon (alerts) and choose preferences from the bottom, signature will be in the menu on the left there https://www.thehelper.net/account/preferences
  • The Helper The Helper:
    I think I need to split the Sci/Tech news forum into 2 one for Science and one for Tech but I am hating all the moving of posts I would have to do
  • The Helper The Helper:
    What is up Old Mountain Shadow?

      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