1. Are you planning to upload your awesome spell or system to Hive? Please review the rules here.
    Dismiss Notice
  2. Icon Contest #17 - Results are out! Step by to congratulate our winners!
    Dismiss Notice
  3. Melee Mapping Contest #2 - Results are out! Step by to congratulate the winners!
    Dismiss Notice
  4. C'thun has spoken! Texturing Contest #29 - Results are published - check 'em out!
    Dismiss Notice
  5. Join Terraining Contest #19 and witness the aftermath!
    Dismiss Notice

[System (vJass)] Anachrons Move System

Submitted by Anachron
This bundle is marked as approved. It works and satisfies the submission rules.
My updated Move System.

Code/Comments

Code (vJASS):

//:******************************************************************************
//:  Anachrons Move System
//:    by dhk_undead_lord / aka Anachron
//:    version 1.05
//:
//:
//:  ABOUT:
//:  This system has been thought to be able to easily
//:  create and manage spawn ways of troops.
//:  Top priority is the automatic movement control,
//:  such as high customizeability for users.
//:
//:  WHAT YOU NEED:
//:  You need JassNewGenPack to use this vJASS system.
//:  (Download it here: http://www.wc3c.net/showthread.php?goto=newpost&t=90999)
//:  
//:  STEPS TO IMPORT:
//:  I.) Copy this code.
//:  II.) Paste it into the head of your map.
//:  (Therefor go to the Trigger Editor, select the mapname and paste
//:   into the area on the right)
//:  III.) Save your map!
//:  (With File - Save Map (S) or control + S. DO NOT SAVE WITH SAVE AS!)
//:  IV.) You got it! You imported the system.
//:  
//:  To make sure this system works, you should try a few tests!
//:  
//:  METHODS
//:  
//:  >WayPoint.create takes real baseX, real baseY, real targX, real targY, real targRadius
//:  Constructor of WayPoints.
//:  
//:  >WayPoint.moveUnit takes unit u
//:  Move any unit to the target of this waypoint!
//:  
//:  >Way.create takes boolean scCon, boolean stCon, boolean hdCon returns Way
//:  Create a new Way, say whether orders should recast attack/move or not.
//:  
//:  >Way.addWayPoint takes WayPoint wp returns nothing
//:  Add a waypoint to the system! Horray, another patrol point.
//:
//:  >Way.addUnit takes unit u returns nothing
//:  Adds an unit to the way. Automaticly moves to the first waypoint.
//:
//:  >Way.removeUnit takes unit u returns nothing
//:  Remove a unit from the way system.
//:
//:  >Way.moveUnit takes unit u, integer curPos returns nothing
//:  Move the unit u to the waypoint curPos's position
//:
//:  >Way.moveNext takes unit u, integer curPos returns nothing
//:  Sets the new wayPoint for the unit u
//:
//:  >Way.getNearestWP takes unit u returns integer
//:  A very nice function to find the nearest waypoint of an unit.
//:  Is perfect for Revive spells were you need to reregister,
//:  because with this function its pretty easy to get the correct waypoint.
//:  
//:  Thanks for downloading and using my system!
//:  
//:  Please don't forget to give credits to me (dhk_undead_lord / Aka Anachron)
//:
//:******************************************************************************  
library AnaMoveSys initializer init
    //==========================================================================
    // %CUSTOMIZATION AREA%: Feel free to change anything to what you need!
    //==========================================================================
    globals
        //: %Default Values%
        //:     Basicly the radius the unit has to be to
        //:     get ordered to the next waypoint.
        private constant real TARGET_TOLERANCE          = 192.
        //:     Sets whether the unit should move again
        //:     after it casted a spell.
        private constant boolean SPELLCAST_CONTINUE      = true
        //:     Sets whether the unit should move again
        //:     after it used stop command.
        private constant boolean STOP_CONTINUE          = true
        //:     Sets whether the unit should move again
        //:     after it used the hold position command.
        private constant boolean HOLDPOSITION_CONTINUE  = false
        //:     Sets whether death units will automaticly
        //:     removed by the system.
        //:     WARNING: THIS IS HIGLY RECOMMENDED!
        //:     TO ADD UNITS (LIKE REVIVE) USE THE addUnit()
        //:     METHOD!
        private constant boolean DEATH_REMOVES = true
       
        //: %Hashtable Storage%
        //:     Sets which key is for the unit ID
        private constant integer KEY_UNIT = 0
        //:     Sets which key is for the way ID
        private constant integer KEY_WAY = 1
        //:     Sets which key is for the current
        //:     waypoint ID.
        private constant integer KEY_CURPOS = 2
       
        //: %Order Ids%
        private constant string ORDER_STOP = "stop"
        private constant string ORDER_HOLDPOSITION = "position"
        private constant string ORDER_ATTACKMOVE = "attack"
       
        //: %Timers%
        private constant timer MOVE_TIMER = CreateTimer()
        private constant real MOVE_INT = 0.75
       
        //: %Saving%
        private hashtable UNIT_DATA = InitHashtable()
        private group MOVING_UNITS = CreateGroup()
    endglobals
   
    //: %Conditions of reordering the units
    //: Here you can define the conditions,
    //: such as owner controlling and other
    //: useful filters.
    public function globalCheck takes nothing returns boolean
        return LoadWidgetHandle(UNIT_DATA, GetHandleId(GetTriggerUnit()), KEY_UNIT) != null
    endfunction
   
    public function checkSpellcast takes nothing returns boolean
        return globalCheck()
    endfunction
   
    public function checkStopOrder takes nothing returns boolean
        return globalCheck() and GetIssuedOrderId() == OrderId(ORDER_STOP)
    endfunction
   
    public function checkHoldOrder takes nothing returns boolean
        return globalCheck() and GetIssuedOrderId() == OrderId(ORDER_HOLDPOSITION)
    endfunction
   
    //==========================================================================
    //: %DO NOT CHANGE THIS UNLIKE YOU KNOW WHAT YOU ARE DOING%
    //==========================================================================
   
    public function reOrderUnit takes nothing returns nothing
        local integer unitID = 0
        local integer wayID = 0
        local integer curPos = 0
       
        if IsUnitInGroup(GetTriggerUnit(), MOVING_UNITS) then
            set unitID = GetHandleId(GetTriggerUnit())
            set wayID = LoadInteger(UNIT_DATA, unitID, KEY_WAY)
            set curPos = LoadInteger(UNIT_DATA, unitID, KEY_CURPOS)
            debug call BJDebugMsg("!AoSMoveSys] |NOTICE| <Way[" + I2S(wayID) + "]> <Reorder unit " + I2S(unitID) + ">")
            call Way.instances[wayID].moveUnit(GetTriggerUnit(), curPos)
        endif
    endfunction
   
    public function checkUnregister takes nothing returns boolean
        return GetOwningPlayer(GetTriggerUnit()) == Player(0)
    endfunction
   
    public function unregisterUnit takes nothing returns nothing
        local integer wayID = LoadInteger(UNIT_DATA, GetHandleId(GetTriggerUnit()), KEY_WAY)
       
        call Way.instances[wayID].removeUnit(GetTriggerUnit())  
    endfunction

    struct WayPoint
        real baseX = 0.
        real baseY = 0.
       
        real targX = 0.
        real targY = 0.
        real targRadius = 0.
       
        integer ID = 0
       
        //: =================================
        //: CREATE NEW INSTANCES
        //: =================================
        public static method create takes real bX, real bY, real tX, real tY, real tR returns WayPoint
            local thistype wp = thistype.allocate()
                set wp.baseX = bX
                set wp.baseY = bY
                set wp.targX = tX
                set wp.targY = tY
                set wp.targRadius = tR
            return wp
        endmethod
        //: =================================
       
        //: =================================
        //: Move the unit to the target loc
        //: =================================
        public method moveUnit takes unit u returns nothing
            call IssuePointOrder(u, ORDER_ATTACKMOVE, .targX, .targY)
        endmethod
        //: =================================  
    endstruct
   
    struct Way
        group units = CreateGroup()
       
        integer ID = 0
        static Way array instances[8191]
        static integer index = 0
       
        integer curwpID = 0
        WayPoint array wayPoints[128]
       
        //: Saves the triggers for the
        //: auto remove functions.
        //:     -> spellcast?
        static trigger scTrig = CreateTrigger()
        //:     -> stop?
        static trigger stTrig = CreateTrigger()
        //:     -> hold position?
        static trigger hpTrig = CreateTrigger()
       
        //: This unregisters unit which die
        static trigger deathTrig = CreateTrigger()
       
        //: =================================
        //: CREATE NEW INSTANCES
        //: =================================
        public static method create takes nothing returns thistype
            local thistype wy = thistype.allocate()
                call thistype.addWay(wy)
            return wy
        endmethod
        //: =================================
       
        //: =================================
        //: Add and remove ways to the system
        //: =================================
        private static method addWay takes thistype wy returns nothing
            set wy.ID = thistype.index
            set thistype.instances[thistype.index] = wy
            set thistype.index = thistype.index + 1
        endmethod
       
        private static method removeWay takes thistype wy returns nothing
            set thistype.instances[wy.ID] = thistype.instances[thistype.index]
            set thistype.index = thistype.index - 1
        endmethod
        //: =================================
       
        //: ====================================
        //: Add and remove Way Point to the way
        //: ====================================
        public method addWayPoint takes WayPoint wp returns nothing
            set wp.ID = .curwpID
            set .wayPoints[.curwpID] = wp
            set .curwpID = .curwpID + 1
        endmethod
       
        public method removeWayPoint takes WayPoint wp returns nothing
            set .wayPoints[wp.ID] = .wayPoints[.curwpID]
            set .curwpID = .curwpID - 1
        endmethod
        //: ====================================
       
        //: ====================================
        //: Add and remove units to the way
        //: ====================================
        public method addUnit takes unit u, integer curPos returns nothing
            if not(IsUnitInGroup(u, .units)) then
                call SaveWidgetHandle(UNIT_DATA, GetHandleId(u), KEY_UNIT, u)
                call SaveInteger(UNIT_DATA, GetHandleId(u), KEY_WAY, .ID)
                call SaveInteger(UNIT_DATA, GetHandleId(u), KEY_CURPOS, curPos)
               
                call GroupAddUnit(.units, u)
                call GroupAddUnit(MOVING_UNITS, u)
               
                call .moveUnit(u, curPos)
            else
                debug call BJDebugMsg("!AoSMoveSys] |ERROR| <Way[" + I2S(.ID) + "]> <addUnit: UNIT ALREADY REGISTERED!>")
            endif
        endmethod
       
        public method removeUnit takes unit u returns nothing
            call FlushChildHashtable(UNIT_DATA, GetHandleId(u))
            call GroupRemoveUnit(.units, u)
            call GroupRemoveUnit(MOVING_UNITS, u)
            debug call BJDebugMsg("!AoSMoveSys] |NOTICE| <Way[" + I2S(.ID) + "]> <removeUnit: UNIT HAS BEEN REMOVED!>")
        endmethod
        //: ====================================
       
        //: ====================================
        //: Move an unit to the target
        //: ====================================
        public method moveUnit takes unit u, integer curPos returns nothing
            call .wayPoints[curPos].moveUnit(u)    
        endmethod
       
        public method moveNext takes unit u, integer curPos returns nothing
            set curPos = curPos + 1
            if curPos < .curwpID then
                //: %Save data and move unit%
                call SaveInteger(UNIT_DATA, GetHandleId(u), KEY_CURPOS, curPos)
                call .moveUnit(u, curPos)
            else
                call .removeUnit(u)
            endif
        endmethod
        //: ====================================
       
        //: ====================================
        //: Additional Methods for users
        //: ====================================
        public method getNearestWP takes unit u returns integer
            local integer foundWP = -1
            local WayPoint wp = 0
            local integer i = 0
            local real tmpDist = 0.
            //: !Do NOT change this
            local real dist = 100000000.
           
            loop
                exitwhen i >= .curwpID
               
                // %Compare the distances%
                set tmpDist = SquareRoot(GetUnitX(u) * wp.targX + GetUnitY(u) * wp.targY)
                if tmpDist <= dist then
                    set foundWP = i
                    set dist = tmpDist    
                endif
               
                set i = i + 1    
            endloop
           
            return foundWP
        endmethod
        //: ====================================
       
        //: ====================================
        //: Desctrutor Method
        //: ====================================
        private method onDestroy takes nothing returns nothing
            local integer i = 0
           
            loop
                exitwhen i >= .curwpID
               
                call .wayPoints[i].destroy()
                 
                set i = i + 1
            endloop
           
            call thistype.removeWay(this)
        endmethod
        //: ====================================
    endstruct
   
    private struct MoveOrders
   
        //: =================================
        //: CHECK ALL WAYS FOR SPAWNING
        //: =================================
        static method checkWays takes nothing returns nothing
            local Way wy = 0
            local WayPoint wp = 0
            local integer i = 0
           
            local unit u = null
            local group g = CreateGroup()
            local integer unitID = 0
            local integer wpID = 0
           
            local real dx = 0.
            local real dy = 0.
            local real dist = 0.
           
            loop
                exitwhen i >= Way.index
               
                //----------------
                //: %Reset Data%
                //----------------
                set u = null
                call GroupClear(g)
                set wy = 0
                set wp = 0
                set unitID = 0
                //----------------
               
                set wy = Way.instances[i]
                call GroupAddGroup(wy.units, g)
               
                loop
                    set u = FirstOfGroup(g)
                    exitwhen u == null
                   
                    //-----------------------
                    // %Get unit data%
                    //-----------------------
                    set unitID = GetHandleId(u)
                    set wpID = LoadInteger(UNIT_DATA, unitID, KEY_CURPOS)
                    set wp = wy.wayPoints[wpID]
               
                    //: Check whether the unit is in the range of
                    //: her checkpoint
                    set dx = GetUnitX(u) - wp.targX
                    set dy = GetUnitY(u) - wp.targY
                    set dist = SquareRoot(dx * dx + dy * dy)
                    if dist <= wp.targRadius then
                        call wy.moveNext(u, wpID)
                        debug call BJDebugMsg("!AoSMoveSys] |NOTICE| <Way[" + I2S(wy.ID) + "]> <Unit " + I2S(GetHandleId(u)) + " reached target>")
                    endif
                   
                    call GroupRemoveUnit(g, u)
                endloop
               
                set i = i + 1
            endloop
           
            call GroupClear(g)
            set u = null
            set g = null
        endmethod
        //: =================================
    endstruct
   
    private function init takes nothing returns nothing
        local integer i = 0
        call TimerStart(MOVE_TIMER, MOVE_INT, true, function MoveOrders.checkWays)
       
        if SPELLCAST_CONTINUE then
            call TriggerAddAction(Way.scTrig, function reOrderUnit)
            call TriggerAddCondition(Way.scTrig, Condition(function checkSpellcast))
            set i = 0
            loop
                exitwhen i > 15
                call TriggerRegisterPlayerUnitEvent(Way.scTrig, Player(i), EVENT_PLAYER_UNIT_SPELL_ENDCAST, null)
                set i = i + 1
            endloop
        endif
               
        if STOP_CONTINUE then
            call TriggerAddAction(Way.stTrig, function reOrderUnit)
            call TriggerAddCondition(Way.stTrig, Condition(function checkStopOrder))
            set i = 0
            loop
                exitwhen i > 15
                call TriggerRegisterPlayerUnitEvent(Way.scTrig, Player(i), EVENT_PLAYER_UNIT_ISSUED_ORDER, null)
                set i = i + 1
            endloop
        endif
               
        if HOLDPOSITION_CONTINUE then
            call TriggerAddAction(Way.hpTrig, function reOrderUnit)
            call TriggerAddCondition(Way.hpTrig, Condition(function checkHoldOrder))
            set i = 0
            loop
                exitwhen i > 15
                call TriggerRegisterPlayerUnitEvent(Way.hpTrig, Player(i), EVENT_PLAYER_UNIT_ISSUED_ORDER, null)
                set i = i + 1
            endloop
        endif
               
        if DEATH_REMOVES then
            call TriggerAddAction(Way.deathTrig, function unregisterUnit)
            call TriggerAddCondition(Way.deathTrig, Condition(function checkUnregister))
            set i = 0
            loop
                exitwhen i > 15
                call TriggerRegisterPlayerUnitEvent(Way.deathTrig, Player(i), EVENT_PLAYER_UNIT_DEATH, null)
                set i = i + 1
            endloop
        endif
    endfunction

endlibrary
 



Example

Code (vJASS):

scope example initializer init

    private function init takes nothing returns nothing
        local WayPoint wp = 0
        local Way wy = 0
        local unit u = CreateUnit(Player(0), 'hmpr', 800., -1200., 270.)
       
        call FogModifierStart(CreateFogModifierRect(Player(0), FOG_OF_WAR_VISIBLE, bj_mapInitialPlayableArea , false, false))
       
        //: Instaciate a new way
        set wy = Way.create()
        //: Add a new waypoint
        call wy.addWayPoint(WayPoint.create(800., -1200., -900., -1125., 192.))
        call wy.addWayPoint(WayPoint.create(-900., -1125., -860., -110., 192.))
        call wy.addWayPoint(WayPoint.create(-860., -110., 0., 0., 192.))
        //: Add a unit to the way, starting at waypoint 0.
        call wy.addUnit(u, 0)
    endfunction

endscope
 



Update 1:
Added remove functions to all objects, moved the example in an extra function

Keywords:
Auto, Move, Move System, System, Way Point, Way, Point
Contents

Anachrons Move System 1.05 (Map)

Reviews
Moderator
20:45, 6th Oct 2009 The_Reborn_Devil: It seems to be working and the code looks good. It's also quite useful. Approved. I give this system the rating Useful/Recommended [3.99/5].
  1. 20:45, 6th Oct 2009
    The_Reborn_Devil:

    It seems to be working and the code looks good.
    It's also quite useful.
    Approved.
    I give this system the rating Useful/Recommended [3.99/5].
     
  2. calex3

    calex3

    Joined:
    Mar 2, 2009
    Messages:
    285
    Resources:
    3
    Spells:
    3
    Resources:
    3
    Not useful to me...i need system where creep is created for ally of 5 players of team but creep mustn't be controlled by any player which exist....
    To make things easier i need system where there are only 5 players in team and none of them can't control creeps...
     
  3. -Berz-

    -Berz-

    Joined:
    Mar 5, 2008
    Messages:
    3,205
    Resources:
    123
    Icons:
    111
    Packs:
    1
    Skins:
    1
    Spells:
    10
    Resources:
    123
    Create a unit for some non-user player and change its team color? ^^
     
  4. calex3

    calex3

    Joined:
    Mar 2, 2009
    Messages:
    285
    Resources:
    3
    Spells:
    3
    Resources:
    3
    hmmm....so when i create unit for example for player 5 which is not playing then i change its team color....so then you can't control it?....wow thanks a lot
    EDIT
    actually it is not working...
     
  5. Anachron

    Anachron

    Joined:
    Sep 9, 2007
    Messages:
    6,167
    Resources:
    66
    Icons:
    49
    Packs:
    2
    Tools:
    1
    Maps:
    3
    Spells:
    9
    Tutorials:
    1
    JASS:
    1
    Resources:
    66
    You have to edit the conditions in order to make the system work.

    This is only a small example usage.
     
  6. -Berz-

    -Berz-

    Joined:
    Mar 5, 2008
    Messages:
    3,205
    Resources:
    123
    Icons:
    111
    Packs:
    1
    Skins:
    1
    Spells:
    10
    Resources:
    123
    Looks, ok. But why making this complicated since you can just make a few regions and check the unit type of "entering unit" and if it matches the order it to move to the next region.

    I'm pretty sure that this is how 90% of map makers do it ^^

    But It could be useful and wen you'll make a spawn it could be useful even more (like i have any clue what's written in that script :p)
     
  7. Deuterium

    Deuterium

    Joined:
    Mar 17, 2009
    Messages:
    1,301
    Resources:
    2
    Spells:
    1
    Tutorials:
    1
    Resources:
    2
    This could be useful to alot of people! :) I'll check code later tonight if I get any time ;)
     
  8. dragor-X

    dragor-X

    Joined:
    Feb 26, 2008
    Messages:
    173
    Resources:
    0
    Resources:
    0
    Well actually, this is useful if you have many spawn regions so you doon't have to create too many regions, that's right?! I'm sure im right >:)
     
  9. Anachron

    Anachron

    Joined:
    Sep 9, 2007
    Messages:
    6,167
    Resources:
    66
    Icons:
    49
    Packs:
    2
    Tools:
    1
    Maps:
    3
    Spells:
    9
    Tutorials:
    1
    JASS:
    1
    Resources:
    66
    Thats right, but thats not he only example.

    Also, while rects are squared, this system has an RADIUS,
    so entering the area of the waypoint will make the unit move
    to the next, while square looks ugly.

    And it will also move units to the target point again
    when you casted a spell, use the stop or the
    hold position order.

    I didn`t made the other order because its quite
    crazy to order them to attack/move again
    after a patrol order. (because it has to be triggered
    to happen, so this is not what you want)

    Because it bugs? Ever tried moving 25 units to the same area?
    it will bug on rects, but with my method units will continue try
    reaching the waypoint, until they reached him.

    Also, rects are ugly becaues you shouldn´t use them if you can
    avoid them. why using a check trigger if the unit is entered? It
    doesn´t looks well and also it is not that smooth as mine.
     
  10. Palaslayer

    Palaslayer

    Joined:
    Jun 16, 2008
    Messages:
    1,779
    Resources:
    66
    Icons:
    62
    Packs:
    1
    Spells:
    2
    Tutorials:
    1
    Resources:
    66
    i failed lots of times trying to do this (well, i used gui :D) and i just love that you made it :D

    really useful.
     
  11. Anachron

    Anachron

    Joined:
    Sep 9, 2007
    Messages:
    6,167
    Resources:
    66
    Icons:
    49
    Packs:
    2
    Tools:
    1
    Maps:
    3
    Spells:
    9
    Tutorials:
    1
    JASS:
    1
    Resources:
    66
    Yeah, was a beast of thinking but now I got it x)
    My Spawn system is 80% ready too! :)
     
  12. -Berz-

    -Berz-

    Joined:
    Mar 5, 2008
    Messages:
    3,205
    Resources:
    123
    Icons:
    111
    Packs:
    1
    Skins:
    1
    Spells:
    10
    Resources:
    123
    Seems to be working smooth, now you just need to make a spawn ^^
     
  13. Anachron

    Anachron

    Joined:
    Sep 9, 2007
    Messages:
    6,167
    Resources:
    66
    Icons:
    49
    Packs:
    2
    Tools:
    1
    Maps:
    3
    Spells:
    9
    Tutorials:
    1
    JASS:
    1
    Resources:
    66
    Bump. Updated.
     
  14. Raziel_br

    Raziel_br

    Joined:
    Oct 13, 2008
    Messages:
    554
    Resources:
    0
    Resources:
    0
    works on multiplayer?
     
  15. Anachron

    Anachron

    Joined:
    Sep 9, 2007
    Messages:
    6,167
    Resources:
    66
    Icons:
    49
    Packs:
    2
    Tools:
    1
    Maps:
    3
    Spells:
    9
    Tutorials:
    1
    JASS:
    1
    Resources:
    66
  16. Cpt.ZnacK

    Cpt.ZnacK

    Joined:
    Oct 11, 2009
    Messages:
    189
    Resources:
    1
    Tutorials:
    1
    Resources:
    1
    Very Helpful :D
     
  17. Anachron

    Anachron

    Joined:
    Sep 9, 2007
    Messages:
    6,167
    Resources:
    66
    Icons:
    49
    Packs:
    2
    Tools:
    1
    Maps:
    3
    Spells:
    9
    Tutorials:
    1
    JASS:
    1
    Resources:
    66
    I am glad you like it.
     
  18. pred1980

    pred1980

    Joined:
    Mar 19, 2010
    Messages:
    844
    Resources:
    1
    Maps:
    1
    Resources:
    1
    Can u add a testmap to demonstrate how to use it? Maybe you can create a little TD to show all the functionalities...

    Thx a lot
     
  19. pred1980

    pred1980

    Joined:
    Mar 19, 2010
    Messages:
    844
    Resources:
    1
    Maps:
    1
    Resources:
    1
    hi again :) ( look post before ).

    I understand it now, dont need any more example code. The system is really good and works perfect! I'll use it for my map.

    Thx and Reg.
    Patrick
     
    Last edited: Jan 9, 2014