# [Snippet] Loc

#### Dirac

Level 6
JASS:
``````library Loc /* v2.1.0

Replacement of the Location native.

***********************************************************************
*
*   struct Loc
*
*           -   The Loc's position in the XY grid.
*           -   The Loc's total height (including ground z)
*
*
*       static method create takes real x, real y, real z returns Loc
*           -   Creates a new Loc with the given coordinates.
*       method lock takes nothing returns nothing
*           -   Locks the instance, preventing it from being
*           -   deallocating when unlocked
*       method unlock takes nothing returns nothing
*           -   Attempts to deallocate the instance, wont happen if
*           -   it's still being used.
*
*       method move takes real x, real y, real z returns nothing
*           -   Assigns the Loc new coordinates.
*
**********************************************************************/

struct Loc extends array

private static integer array r
private static integer ic = 0

readonly static location global = Location(0,0)

//*********************************************************************
//  Lock counters: a way to keep track of how many times a Loc has been
//  locked, starts counting from 1. Unlocking drops the counters by 1,
//  if it reaches 0 the instance is deallocated.
private integer lc

method move takes real sx, real sy, real sz returns nothing
call MoveLocation(global,sx,sy)
set x = sx
set y = sy
set z = sz+GetLocationZ(global)
endmethod

static method create takes real sx, real sy, real sz returns thistype
local thistype this = r[0]
if this==0 then
set ic = ic+1
set this = ic
else
set r[0] = r[this]
endif
call this.move(sx,sy,sz)
set lc = 1
return this
endmethod

method lock takes nothing returns nothing
set lc = lc+1
endmethod

/* idea brought by Nestharus */
method unlock takes nothing returns nothing
set lc = lc-1
if lc==0 then
set r[this] = r[0]
set r[0] = this
endif
endmethod

endstruct

endlibrary``````
JASS:
``````library AdvLoc /* v1.0.0

*/uses/*
*/  Loc  /* hiveworkshop.com/forums/submissions-414/snippet-lacking-loc-209322/

***********************************************************************
*
*       -   Has the exact same API as Loc with extended functionality
*
*       static method link takes Loc a, Loc b returns nothing
*           -   Creates a link between the two Locs, linked Locs keep
*           -   data relative to the other Loc's position such as...
*
*               -   Each Loc knows the angle/distance/slope from itself
*
*       method lock takes nothing returns nothing
*           -   Locks the instance, preventing it from being
*           -   deallocating when unlocked
*       method unlock takes nothing returns nothing
*           -   Attempts to deallocate the instance, wont happen if
*           -   it's still being used.
*
**********************************************************************/

//*********************************************************************
//  Lock counters: a way to keep track of how many times a Loc has been
//  locked, starts counting from 1. Unlocking drops the counters by 1,
//  if it reaches 0 the instance is deallocated.
private integer lc

method operator x takes nothing returns real
return Loc(this).x
endmethod

method operator y takes nothing returns real
return Loc(this).y
endmethod

method operator z takes nothing returns real
return Loc(this).z
endmethod

static method create takes real ox, real oy, real oz returns thistype
local thistype this = Loc.create(ox,oy,oz)
set ref = this
return this
endmethod

private static method math takes thistype a, thistype b returns nothing
set a.angle = Atan2(b.y-a.y,b.x-a.x)
set a.distance = SquareRoot((b.x-a.x)*(b.x-a.x)+(b.y-a.y)*(b.y-a.y))
set a.slope = (b.z-a.z)/a.distance
set b.angle = a.angle+bj_PI
set b.distance = a.distance
set b.slope = -a.slope
endmethod

set a.ref = b
set b.ref = a
call math(a,b)
endmethod

method unlink takes nothing returns nothing
if lc==0 then
set ref.ref = ref
set ref = this
endif
endmethod

method lock takes nothing returns nothing
set lc = lc+1
call Loc(this).lock()
endmethod

method unlock takes nothing returns nothing
set lc = lc-1
if lc==0 then
set ref.ref = ref
set ref = this
endif
call Loc(this).unlock()
endmethod

method move takes real nx, real ny, real nz returns nothing
call Loc(this).move(nx,ny,nz)
if this!=ref then
call math(this,ref)
endif
endmethod
endstruct

endlibrary``````

Last edited:

#### Magtheridon96

Level 35
You know, Loc.distance doesn't really make sense to me. (Unless it's the distance from 0,0)

edit
Why not call it a vector?

#### Dirac

Level 6
-Why not call it a vector?
Because completely replaces the Location native.
-So basically, this works like the Vector library?
No, Locs work on their own, it only works like a vector if you join Locs together
Also, the vector library doesn't update other vectors when moved.

I was thinking of making this handle lots of locs joined together, but making data update a monodirectional process (moving a Loc that has links with others would only update the status between that Loc and the others, not every Loc with every other Loc)

#### Magtheridon96

Level 35
Well, this has been done a million and one times, but your library is actually unique.
In the past, I used to remove the need for multiple locations in Jass with a simple library called zLoc:

JASS:
``````struct zLoc extends array
static location z = Location(0,0)
static method move takes real x, real y returns nothing
call MoveLocation(z, x, y)
endmethod
static method getZ takes nothing returns real
return GetLocationZ(z)
endmethod
endstruct``````

I guess your library fulfills that purpose and it provides a little bit extra functionalities.
If you can use this for Missile and it would increase readability, well, that's a plus.

Oh one thing:

JASS:
``````            local thistype this
if next[0]==0 then
set ic = ic+1
set this = ic
else
set this = next[0]
set next[0] = next[next[0]]
endif``````

->

JASS:
``````            local thistype this = next[0]
// Using this instead of next[0] is faster because:
// next is a global
// next[0] is an array lookup
// next will have a really long name while 'this' will remain 4 characters long
if this==0 then
set ic = ic + 1
set this = ic
else
set next[0] = next[this]
endif``````

#### Dirac

Level 6
Updated to v1.1.0
-Added manual ways to calculate the angle/distance/slope between two Locs
-Improved the way Locs are joined by using LinkedListModule, now you can join more than 2 Locs together, you can even join Loc groups together without any chance to bug
-Added the zangle and modulo members

#### Bribe

Level 37
What is accomplished when you join or unjoin these things? Seems pretty pointless to me.

#### Dirac

Level 6
Joining two Locs causes them to update automatically.
Lets say you're working with a system that takes a Loc as an argument and this system will toy around with this Loc (and does not destroy it afterwards)
If you decide to join the Loc you gave to that system with another Loc you're using for something else you would automatically have all the needed data between these two Locs without having to update them manually (Even when that might seem a better solution)
Anyways, joining two Locs only purpose is to make the user's work simpler.
The main idea of this system is to being able to allocate points in the map that many agents would point to / need while you're able to move them. Example:
Lets say that my missile library worked using this... it takes the Loc where the missile would go to. If you ever plan to redirect that missile all you have to do is to move that Loc.

#### Bribe

Level 37
Imo this is not modular enough to be called "Loc". It has extra utility which a lot of times won't be needed, therefore importing your thing requires a heavy amount of unwanted, injected material, for something you originally described as simply as a "replacement to the location native".

The only "replacement" for locations would be to have a dummy location for GetLocationZ, and we already have lots of those.

For getting the distance and such you can inline that into your own resources, and it makes you look more pro to use such advanced math anyway.

I have tried pushing a "Point" library which I originally thought of as a wrapper for locations, too, but Azlier rejected it for similar reasons as to why I am hesitating with this one.

http://www.hiveworkshop.com/forums/graveyard-418/point-176317/

#### Dirac

Level 6
The main idea of this library is to actually replace the location native, not just because of the "z" capacities, but because sometimes is very needed to keep track of coordinates around the map, not just loose arrays inside each struct, to reach flexibility on spell developing.
Anyways, i'm planning to update this soon as i've finally finished Missile using Loc, it's still in an extremely beta state.

#### Bribe

Level 37
This could be called "LinkedLocations" or something similar, then. But a name like "Loc" does not imply a bunch of features I have never needed.

#### Dirac

Level 6
Bribe I think that taking in consideration the amount of code a system generates is just petty.
A system is rather useful or not, the thing it matters the most is that every aspect of it's functionality is working properly and gives the users all the tools it needs.
It's not like you're shopping for a swiss army knife, the only payback for lots of codes is map size and being picky on how many systems to use is not the way to go. At the end of the day is systems like these who reduce amount of code in overall.
The idea of this is to keep track of a certain x,y around the map, if units move so may Locs, and has some extra functions that wont interfere with it's inefficiency if not used, like joining Locs or some storage for extra data such as distance, slope or angle.
If you want me to change the name, I guess it's fine but I would have to divide this system in two: One that replaces the Loc native and one that has the capacity to join them.

#### Bribe

Level 37
I would prefer that.

Now I can bundle a bunch of loosly-connected but mostly fluff together and call it a resource, but that's the wc3c.net way. Providing quality over quantity is a philosophy I like in a resource.

#### Dirac

Level 6
Updated v2.0.0
-Loc now acts as merely a replacement to location native
-Extra functionality has been passed to AdvLoc, which has the same API as Loc.

#### Bribe

Level 37
"unlock" should attempt to destroy the node, and it should be an integer variable which keeps tracks of multiple libraries which might depend on it.

#### Nestharus

Level 31
Yea, there shouldn't be any destroy method.

I see you took my ideas from Position ^)^, but you need to take some more ; P.

#### Dirac

Level 6
Yea, there shouldn't be any destroy method.

I see you took my ideas from Position ^)^, but you need to take some more ; P.

You mean like, not deallocating, anything, ever?
And no I actually wrote this before I read Position. Position inteds to keep track of the coordinates a specific agent occupies in the map, Loc is just for key coordinates the user would like to set for any other purpose.
Write this down: I do not intend to make this my own version of Position

I did like Bribe's idea for locking instances using integer variables... I'll add that soon

#### Nestharus

Level 31
I did like Bribe's idea for locking instances using integer variables... I'll add that soon

and the integer locks came from position >.>. You need to destroy the location on unlock when there are 0 locks left, otherwise everything will be attempting to destroy the position over and over again.

JASS:
``````        //excerpt from position ^)^
public method unlock takes nothing returns boolean
if (0 < pl) then
set pl = pl - 1
if (0 == pl) then
//recycle
set ir[this] = ir[0]
set ir[0] = this
endif
return true //unlock success
endif
return false //unlock fail
endmethod``````

#### Dirac

Level 6
I know get what Nes means when he says that there shouldnt be a destroy method
Loc v2.1.0
-Alloc is no longer a requirement
-Removed the destroy method, the unlock method deallocates the instance when required.
-Removed the destroy method as well

I find extremely silly to return a boolean in the unlock method.

Replies
11
Views
2K
Replies
29
Views
3K
Replies
13
Views
2K
Replies
8
Views
2K
Replies
123
Views
8K