• Listen to a special audio message from Bill Roper to the Hive Workshop community (Bill is a former Vice President of Blizzard Entertainment, Producer, Designer, Musician, Voice Actor) 🔗Click here to hear his message!
  • Read Evilhog's interview with Gregory Alper, the original composer of the music for WarCraft: Orcs & Humans 🔗Click here to read the full interview.

Make Road Line for Unit Run Snippet v3

This bundle is marked as awaiting update. A staff member has requested changes to it before it can be approved.
This is the code I use to handle creating a route for a unit, it will automatically run (or stop) according to the contacts you set.




// Have a setting you need know : MAX_SIZE_ROADLINE => number of times to save 1 point per region you set. usually it never reaches 99 :))
Road Point System
JASS:
globals
    hashtable road = InitHashtable() // For damage system                                                    
    constant integer MAX_SIZE_ROADLINE = 69 //Max size you use for a region save a point with name difference       
endglobals

struct Region
    trigger t
    rect r
    region rg
    string array name[MAX_SIZE_ROADLINE]
    real array x[MAX_SIZE_ROADLINE]
    real array y[MAX_SIZE_ROADLINE]
    integer array delay[MAX_SIZE_ROADLINE]
    integer size = -1
    string array new_road[MAX_SIZE_ROADLINE]
    boolean array is_teleport[MAX_SIZE_ROADLINE]
    method name2id takes string name returns integer
        local integer r = -1
        local integer n = 0
        loop
            exitwhen n >.size
            if.name[n] == name then
                set r = n
                exitwhen true
            endif
            set n = n + 1
        
        endloop
        return r
    endmethod
endstruct
struct Roadline
    static integer i = -1
    static Region array regions
    static integer ROAD = StringHash("road")
    static integer DELAY = StringHash("delay")
    static integer X = StringHash("x")
    static integer Y = StringHash("y")
    static integer IS_TELE = StringHash("tele")

    static method LoadRoad takes integer hid returns string
        local string r = ""
        set r = LoadStr(road, hid, Roadline.ROAD)
        return r
    endmethod
 
    static method SaveDelay takes integer hid, integer delaytime returns nothing
        call SaveInteger(road, hid, Roadline.DELAY, delaytime)
    endmethod
    static method LoadDelay takes integer hid returns integer
        local integer r = 0
        set r = LoadInteger(road, hid, Roadline.DELAY)
        return r
    endmethod
    static method IsTele takes integer hid returns boolean
        local boolean r = false
        set r = LoadBoolean(road, hid, Roadline.IS_TELE)
        return r
    endmethod
    static method LoadX takes integer hid returns real
        local real r = 0
        set r = LoadReal(road, hid, Roadline.X)
        return r
    endmethod
    static method LoadY takes integer hid returns real
        local real r = 0
        set r = LoadReal(road, hid, Roadline.Y)
        return r
    endmethod
    static method is_have takes rect r returns boolean
        local boolean res = false
        local integer n = 0
        if.i != -1 then
            loop
                exitwhen n >.i
                if r ==.regions[n].r then
                    set res = true
                    exitwhen true
                endif
                set n = n + 1
            endloop
        endif
        return res
    endmethod
    static method find takes region rg returns integer
        local integer res = -1
        local integer n = 0
        if.i != -1 then
            loop
                exitwhen n >.i
                if rg ==.regions[n].rg then
                    set res = n
                    exitwhen true
                endif
                set n = n + 1
            endloop
        endif
        return res
    endmethod
    static method findbyrect takes rect r returns integer
        local integer res = -1
        local integer n = 0
        if.i != -1 then
            loop
                exitwhen n >.i
                if r ==.regions[n].r then
                    set res = n
                    exitwhen true
                endif
                set n = n + 1
            endloop
        endif
        return res
    endmethod
    static method Runto takes nothing returns nothing
        local region rg = GetTriggeringRegion()
        local unit u = GetEnteringUnit()
        local integer id = GetHandleId(u)
        local integer rgid =.find(rg)
        local string roadtype = LoadStr(road, id, Roadline.ROAD)
        local integer n = 0
        // call PLAYER.systemchat(Player(0),.regions[rgid].name[n])                        
    
        loop
            exitwhen n >.regions[rgid].size
            if roadtype ==.regions[rgid].name[n] then
                call SaveReal(road, id, Roadline.X,.regions[rgid].x[n])
                call SaveReal(road, id, Roadline.Y,.regions[rgid].y[n])
                call Roadline.SaveDelay(id,.regions[rgid].delay[n])
                if.regions[rgid].is_teleport[n] then
                    call SaveBoolean(road, id, Roadline.IS_TELE, true)
                else
                    call SaveBoolean(road, id, Roadline.IS_TELE, false)
                endif
                if.regions[rgid].new_road[n] != "" then
                    call SaveStr(road, id, Roadline.ROAD,.regions[rgid].new_road[n])
                endif
            endif
            set n = n + 1
        endloop
        

    endmethod
    static method register takes unit u, rect r, string roadname returns nothing
        local integer id =.findbyrect(r)
        local integer size = -1
        local integer hid = GetHandleId(u)
        if id != -1 then
            set size =.regions[id].name2id(roadname)
            if size != -1 then
                call SaveStr(road, hid, Roadline.ROAD,.regions[id].name[size])
                call SaveReal(road, hid, Roadline.X,.regions[id].x[size])
                call SaveReal(road, hid, Roadline.Y,.regions[id].y[size])
                call SaveInteger(road, hid, Roadline.DELAY,.regions[id].delay[size])
                call SaveBoolean(road, hid, Roadline.IS_TELE,.regions[id].is_teleport[size])
            endif
        endif
    endmethod
    static method new takes rect r, rect r2, integer delay, string name, string new_road, boolean is_teleport returns nothing
        local integer id = 0
        local integer size = 0
        local boolean b = false
        if not.is_have(r) then
            set.i =.i + 1
            set.regions[.i] = Region.create()
            set.regions[.i].r = r
            set.regions[.i].t = CreateTrigger()
            set.regions[.i].rg = CreateRegion()
            call RegionAddRect(.regions[.i].rg, r)
            call TriggerRegisterEnterRegion(.regions[.i].t,.regions[.i].rg, null)
            call TriggerAddAction(.regions[.i].t, function thistype.Runto)
            set b = true
        endif

        if b then
            set id =.i
        else
            set id =.findbyrect(r)
        endif
        set.regions[id].size =.regions[id].size + 1
        set size =.regions[id].size
        set.regions[id].name[size] = name
        set.regions[id].x[size] = GetRectCenterX(r2)
        set.regions[id].y[size] = GetRectCenterY(r2)
        set.regions[id].delay[size] = delay
        set.regions[id].new_road[size] = new_road
        set.regions[id].is_teleport[size] = is_teleport

    endmethod
endstruct


ROAD Line Setting

//You will setting roadline here
  • Setting Road
    • Events
      • Time - Elapsed game time is 1.00 seconds
    • Conditions
    • Actions
      • Custom script: call Roadline.new(gg_rct_M1R1, gg_rct_M1R2, 0, "road1", "", false)
      • Custom script: call Roadline.new(gg_rct_M1R2, gg_rct_M1R3, 0, "road1", "", false)
      • Custom script: call Roadline.new(gg_rct_M1R3, gg_rct_M1R4, 0, "road1", "", false)
      • Custom script: call Roadline.new(gg_rct_M1R4, gg_rct_M1R5, 0, "road1", "", false)
      • Custom script: call Roadline.new(gg_rct_M1R5, gg_rct_M1R6, 0, "road1", "", false)
      • Custom script: call Roadline.new(gg_rct_M1R6, gg_rct_M1R7, 0, "road1", "", false)
      • Custom script: call Roadline.new(gg_rct_M1R7, gg_rct_M1R8, 0, "road1", "", false)
      • -------- teleport to M1R9 --------
      • Custom script: call Roadline.new(gg_rct_M1R8, gg_rct_M1R9, 0, "road1", "", true)
      • Custom script: call Roadline.new(gg_rct_M1R9, gg_rct_M1R10, 0, "road1", "",false)
      • -------- =================== --------
      • Custom script: call Roadline.new(gg_rct_M1R8, gg_rct_M1R7, 0, "road2", "", false)
      • Custom script: call Roadline.new(gg_rct_M1R7, gg_rct_M1R6, 0, "road2", "", false)
      • Custom script: call Roadline.new(gg_rct_M1R6, gg_rct_M1R5, 0, "road2", "", false)
      • Custom script: call Roadline.new(gg_rct_M1R5, gg_rct_M1R4, 0, "road2", "", false)
      • Custom script: call Roadline.new(gg_rct_M1R4, gg_rct_M1R3, 0, "road2", "", false)
      • Custom script: call Roadline.new(gg_rct_M1R3, gg_rct_M1R2, 0, "road2", "", false)
      • Custom script: call Roadline.new(gg_rct_M1R2, gg_rct_M1R1, 0, "road2", "", false)
      • -------- change road line to "road1" --------
      • Custom script: call Roadline.new(gg_rct_M1R1, gg_rct_M1R2, 0, "road2", "road1", false)


ROAD LINE EXAMPLE Order

// It use for guide you make order unit move or attack, filter ,...
JASS:
struct ROADLINE_EXAMPLE
    static integer Move = 851986
    static integer Almove = 851988
    static integer Attack = 851983
    static method io takes unit u, integer order returns boolean
        return GetUnitCurrentOrder(u) == order // Returns true or false when comparing the input order id value with the current unit's order value                                                                                                 
    endmethod
    static method IsNotAction takes unit u returns boolean
        return not(.io(u,.Move) or.io(u,.Almove) or.io(u,.Attack))
    endmethod

    static method order takes nothing returns nothing
        local unit e = null
        local group g = null
        local integer id = -1
        set g = CreateGroup()
        call GroupEnumUnitsOfPlayer(g, Player(10), null) //Group all player 11 unit will check road line
        loop
            set e = FirstOfGroup(g)
            exitwhen e == null
            set id = GetHandleId(e)
            if GetUnitState(e, UNIT_STATE_LIFE) > 0 and IsUnitType(e, UNIT_TYPE_STRUCTURE) == false and.IsNotAction(e) then
                if Roadline.LoadRoad(id) != "" then
                    if Roadline.LoadDelay(id) > 0 then
                        call Roadline.SaveDelay(id, Roadline.LoadDelay(id) -1)
                    else
                        // call BJDebugMsg(R2S(Roadline.LoadX(id)) + " [] " + R2S(Roadline.LoadY(id)))        
                        if Roadline.IsTele(id) then
                            call SetUnitPosition(e, Roadline.LoadX(id), Roadline.LoadY(id))
                            call DestroyEffect(AddSpecialEffect("Abilities\\Spells\\NightElf\\Blink\\BlinkCaster.mdl", Roadline.LoadX(id), Roadline.LoadY(id)))
                        else
                            //Change it to "move" or "attack" if attack is target then contact me for more custom   
                            call IssuePointOrder(e, "move", Roadline.LoadX(id), Roadline.LoadY(id))
                        endif
                    endif
                endif
            endif
            call GroupRemoveUnit(g, e)
        endloop
        call GroupClear(g)
        call DestroyGroup(g)
        set e = null
    endmethod
endstruct


  • IntervalOrder
    • Events
      • Time - Every 1.00 seconds of game time
    • Conditions
    • Actions
      • Set Variable Set times = (times + 1)
      • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
        • If - Conditions
          • (times mod 5) Equal to 0
        • Then - Actions
          • Unit - Create 1 . Footman for Player 11 (Dark Green) at (Center of M1R1 <gen>) facing Default building facing degrees
          • Unit - Turn collision for (Last created unit) Off .
          • Custom script: call Roadline.register(bj_lastCreatedUnit, gg_rct_M1R1, "road1")
          • Unit - Create 1 . Footman for Player 11 (Dark Green) at (Center of M1R8 <gen>) facing Default building facing degrees
          • Unit - Turn collision for (Last created unit) Off .
          • Custom script: call Roadline.register(bj_lastCreatedUnit, gg_rct_M1R8, "road2")
        • Else - Actions
      • Custom script: call ROADLINE_EXAMPLE.order()



Add a Road Point

JASS:
// (your_region_now, your_region_come, your_delay_time , your_road_name , new_road_name?, teleport?)
 call Roadline.new(gg_rct_M1R1, gg_rct_M1R2, 0, "road1", "", false)
your_delay_time is when join a region, will have delay time unit do something in region.
Contents

Roadline v3 by OgreMagiLord#1971 (Map)

Reviews
Antares
static method find takes region rg returns integer local integer res = -1 local integer n = 0 if.i != -1 then loop exitwhen n >.i if rg ==.regions[n].rg then...
What is the reason you have three identical copies of RoadPoint in your script? As far as I can tell, you are not using any instanceable structs in your script. You could make a Road struct that you create with Road.New() and that has a rect array as a member, holding all the road points. Then you can add a method MyRoad.AddRoadPoint to add new road points to that road.

You are looping over all rects to find the one that the unit entered on the TriggerRegisterEnterRectSimple event. You can save the integer i to a hashtable with the rect as the key and retrieve it much faster that way.

You have hardcoded numbers such as if ORDER.Load(id) == 7 then or integer GREEN = 6 in your code that aren't explained anywhere. The former one should be just the maximum number of rects added to that Road.

And that's really the main issue with your ressource. As a system, it lacks customization options. As a template, it lacks explanations what the various parts are there for, making me believe that anyone who has the ability to understand your code and modify it to their own needs would also be able to write it from scratch. It doesn't help that your english isn't the best. I would advise that you get help doing your descriptions, either translate it with ChatGPT or have a hive member help you out. A bit of whitespace between the various functions would also help to make the code more readable.

Your code has some useful bits in there, but I don't think it's in a state where it can be approved.

Awaiting Update
 
What is the reason you have three identical copies of RoadPoint in your script? As far as I can tell, you are not using any instanceable structs in your script. You could make a Road struct that you create with Road.New() and that has a rect array as a member, holding all the road points. Then you can add a method MyRoad.AddRoadPoint to add new road points to that road.

You are looping over all rects to find the one that the unit entered on the TriggerRegisterEnterRectSimple event. You can save the integer i to a hashtable with the rect as the key and retrieve it much faster that way.

You have hardcoded numbers such as if ORDER.Load(id) == 7 then or integer GREEN = 6 in your code that aren't explained anywhere. The former one should be just the maximum number of rects added to that Road.

And that's really the main issue with your ressource. As a system, it lacks customization options. As a template, it lacks explanations what the various parts are there for, making me believe that anyone who has the ability to understand your code and modify it to their own needs would also be able to write it from scratch. It doesn't help that your english isn't the best. I would advise that you get help doing your descriptions, either translate it with ChatGPT or have a hive member help you out. A bit of whitespace between the various functions would also help to make the code more readable.

Your code has some useful bits in there, but I don't think it's in a state where it can be approved.

Awaiting Update
Yeah, Thanks for your review, I'll take the time to make it easier to understand and use, and I'll let you know when it's updated
 
vJASS:
    static method find takes region rg returns integer 
        local integer res = -1 
        local integer n = 0 
        if.i != -1 then 
            loop 
                exitwhen n >.i 
                if rg ==.regions[n].rg then 
                    set res = n 
                    exitwhen true 
                endif 
                set n = n + 1 
            endloop 
        endif 
        return res 
    endmethod
This could be solved much easier by storing the id to the region/rect with a hashtable.

vJASS:
    static method LoadDelay takes integer hid returns integer 
        local integer r = 0 
        set r = LoadInteger(road, hid, Roadline.DELAY) 
        return r 
    endmethod
=>
vJASS:
    static method LoadDelay takes integer hid returns integer 
        return LoadInteger(road, hid, Roadline.DELAY) 
    endmethod

While the code looks better overall, the documentation is still lacking. You're copy&pasting the code to the hiveworkshop page; that doesn't help. I can look up the code in your test map. What I need is a listing of all public functions and how to use them, what the arguments mean etc.

Having an example is necessary, but not enough. You need both examples and a documentation.

I have no idea what's going on in the Custom Road example.
 
Top