• 🏆 Texturing Contest #33 is OPEN! Contestants must re-texture a SD unit model found in-game (Warcraft 3 Classic), recreating the unit into a peaceful NPC version. 🔗Click here to enter!
  • It's time for the first HD Modeling Contest of 2024. Join the theme discussion for Hive's HD Modeling Contest #6! Click here to post your idea!

[Snippet] Loc

Level 6
Joined
Jun 20, 2011
Messages
249
JASS:
library Loc /* v2.1.0

Replacement of the Location native.

***********************************************************************
*
*   struct Loc
*
*       readonly real x
*       readonly real y
*           -   The Loc's position in the XY grid.
*       readonly real z
*           -   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)
        
        readonly real x 
        readonly real y
        readonly real z
        
        //*********************************************************************
        //  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/

Advanced Loc handling

***********************************************************************
*
*   struct AdvLoc
*       -   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...
*
*           readonly real angle
*           readonly real distance
*           readonly real slope
*               -   Each Loc knows the angle/distance/slope from itself
*               -   to it's linked partner. Updates automatically.
*
*       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.
*
**********************************************************************/

    struct AdvLoc extends array

        readonly thistype ref

        readonly real angle
        readonly real distance
        readonly real slope

        //*********************************************************************
        //  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

        static method link takes AdvLoc a, AdvLoc b returns nothing
            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:
Level 6
Joined
Jun 20, 2011
Messages
249
-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)
 
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
 
Level 6
Joined
Jun 20, 2011
Messages
249
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
 
Level 6
Joined
Jun 20, 2011
Messages
249
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

Code Moderator
Level 50
Joined
Sep 26, 2009
Messages
9,464
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/
 
Level 6
Joined
Jun 20, 2011
Messages
249
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.
 
Level 6
Joined
Jun 20, 2011
Messages
249
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.
 
Level 6
Joined
Jun 20, 2011
Messages
249
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.

I'll add the documentation soon
 
Level 6
Joined
Jun 20, 2011
Messages
249
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
 
Level 31
Joined
Jul 10, 2007
Messages
6,306
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
 
Level 6
Joined
Jun 20, 2011
Messages
249
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.
AdvLoc v1.0.0
-Removed the destroy method as well

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