System Mass Movement System

Doomhammer

Bob Kotick - Gamers' corporate spoilsport No. 1
Reaction score
67
The Mass Movement System is a system to facilitate and optimize the ordering of large amounts of units. It may come in handy to improve any type of footy map, TD maps or cinematics involving entire armies of moving units. As follows, a short :rolleyes: description, two screenies and the test map


1) What can it do?


It can order large amounts of units to move or attack-move to a certain position in a structured manner.​

2) The concept: Why not grab all units and send them to x/y?


Especially with large amounts of units, this is very likely to create movement lags. Also experience has proven that it is more efficient to order large amounts of units in unit groups.

3) How does the mass-movement system order units?

It counts how many units there are to be ordered, then creates grouping clusters according to each units position and the unit density. Each new group has a group captain whose distance to the target decides about the timing of the call to march off. So the units march off in structured groups and with a moderate timing to avoid congestions.

4) Requirements

Actually none apart from WE (since the code is kept on an old-school level).​


5) Code please!

JASS:

//%%%%%%%%%%%%%%%%%%%%% Custom Settings %%%%%%%%%%%%%%%%%%%%%%%%%%

function scatter_size takes integer n,real k returns real
	return 64000.0 / ( n * Pow(bj_E , k) )
endfunction

// The scatter size describes the size of the area, i.e. half the size of the rect 
// which is used to group clustered units into subgroups.
// It is set dependend on the unit amount n, and on an iteration factor k.

constant function scatter_size_min takes nothing returns real
	return 80.0
endfunction

// The maximum amount of units in a cluster before iterating the grouping with a factor k larger by 1.
// Should be quite a bit larger than 12, but definitely smaller than 50: the higher,
// the more operations needed, the smaller, the less likely suitable groups will be formed

constant function max_cluster takes nothing returns integer
	return 30
endfunction

//%%%%%%%%%%%%%%%%%%% Helper Functions %%%%%%%%%%%%%%%%%%%%%%

function All_filter takes nothing returns boolean
    return IsUnitType(GetFilterUnit() , UNIT_TYPE_STRUCTURE) == false and IsUnitType(GetFilterUnit() , UNIT_TYPE_PEON) == false and GetWidgetLife(GetFilterUnit()) > 0.405
endfunction

function OneId_filter takes nothing returns boolean
    return GetUnitTypeId(GetFilterUnit()) == bj_groupEnumTypeId and GetWidgetLife(GetFilterUnit()) > 0.405
endfunction

function TwoId_filter takes nothing returns boolean
    return GetUnitTypeId(GetFilterUnit()) == bj_groupEnumTypeId or GetUnitTypeId(GetFilterUnit()) == bj_forceCountPlayers and GetWidgetLife(GetFilterUnit()) > 0.405
endfunction

function Group_filter takes nothing returns boolean
    return IsUnitInGroup(GetFilterUnit() , bj_randomSubGroupGroup)
endfunction

//%%%%%%%%%%%%%%%%%%%%% Main Functions %%%%%%%%%%%%%%%%%%%%%%%%

function NearUnitArray takes nothing returns nothing
    local unit e=GetEnumUnit()
    local real dx= bj_meleeNearestMineDist - GetUnitX(e)
    local real dy= bj_randomSubGroupChance - GetUnitY(e)
    local real d= bj_enumDestructableRadius
    if ( dx < d and dx > - d ) and ( dy < d and dy > - d ) then
        set bj_ghoul[bj_destRandomConsidered]=e
        set bj_randDistID[bj_destRandomConsidered]=R2I(dx * dx + dy * dy)
        set bj_destRandomConsidered = bj_destRandomConsidered + 1
    endif
    set e = null
endfunction

function NearestSubGroup takes nothing returns group
    local group g= CreateGroup() //the final subgroup to be returned
    local integer n= bj_destRandomConsidered //the cluster size
    local integer i= 0
    local integer j= 0
    local integer d
    local unit u
    // bj_ghoul[] : the unit currently looked at
    //bj_randDistID : the unit's distance to the group 'captain'
    if ( n <= 12 ) then
        loop
	    exitwhen ( i > n )
	    call GroupAddUnit(g , bj_ghoul<i>)
	    call GroupRemoveUnit(bj_groupRemoveGroupDest , bj_ghoul<i>)
	    set bj_ghoul<i>=null
	    set i = i + 1
        endloop
    else
	loop
	    exitwhen ( i == n )
	    set j = i + 1
	    loop
		exitwhen ( j == n )
		if bj_randDistID<i> &lt; bj_randDistID[j] then
		    set u = bj_ghoul<i>
		    set d = bj_randDistID<i>
		    set bj_ghoul<i>=bj_ghoul[j]
		    set bj_randDistID<i>=bj_randDistID[j]
		    set bj_ghoul[j]=u
		    set bj_randDistID[j]=d
		endif
		set j = j + 1
	     endloop
	     set i = i + 1
	endloop
	loop
	    exitwhen i &lt; 0
            if i &gt; j - 12 then
                call GroupAddUnit(g , bj_ghoul<i>)
		call GroupRemoveUnit(bj_groupRemoveGroupDest , bj_ghoul<i>)
            endif
	    set bj_ghoul<i>=null
	    set i = i - 1
	endloop
	endif
	set u = null
    return g
endfunction

function ImmediateOrder takes nothing returns nothing
    call IssueImmediateOrder(GetEnumUnit() , bj_cineFadeContinueTex)
endfunction

function MassMoveType takes integer Id1, integer Id2, string order, real x, real y, player p, real t returns nothing
    local group g=CreateGroup()
    local group array subgroup
    local real array dist
    local boolexpr b
    local unit v
    local real dy
    local real dx
    local integer i= 0
    local integer j= 0
    local integer n

    if Id1 == 0 and Id2 == 0 then
        set b = Filter(function All_filter)
    elseif Id1 != 0 and Id2 == 0 then
        set bj_groupEnumTypeId = Id1
        set b = Filter(function OneId_filter)
    elseif Id1 != 0 and Id2 != 0 then
        set bj_groupEnumTypeId = Id1
        set bj_forceCountPlayers = Id2
        set b = Filter(function TwoId_filter)
    endif

    if GetLocalPlayer() == p then
        call SetCameraQuickPosition(x , y)
    endif
  
    call GroupEnumUnitsOfPlayer(g , p , b)
  
    if order == &quot;stop&quot; then
        set bj_cineFadeContinueTex = order
        call ForGroup(g , function ImmediateOrder)
    elseif order==&quot;move&quot; or order==&quot;attack&quot; then
	set bj_groupCountUnits = 0
	call ForGroup(g , function CountUnitsInGroupEnum)
        set n = bj_groupCountUnits
		
	//call BJDebugMsg(&quot;ordering &quot; + I2S(n) + &quot; units&quot;)
               
        if n &gt; 0 and n &lt;= 12 then
	    call GroupPointOrder(g , order , x , y)
        elseif n &gt; 12 then
            loop
                set v = FirstOfGroup(g)
                exitwhen v == null
                set bj_meleeNearestMineDist = GetUnitX(v)
                set bj_randomSubGroupChance = GetUnitY(v)
		loop
		    if scatter_size(n , j) &gt;= scatter_size_min() then
		        set bj_enumDestructableRadius = scatter_size(n , j)
		    else
		  	set bj_enumDestructableRadius = scatter_size_min()
		    endif
		    set bj_destRandomConsidered = 0
          	    call ForGroup(g , function NearUnitArray)
 		    if bj_destRandomConsidered &gt; max_cluster() then
		        set j = j + 1
 		    endif
		    exitwhen bj_destRandomConsidered &lt;= max_cluster()
                endloop
		set j = 0
		set bj_groupRemoveGroupDest = g
		set subgroup<i>=NearestSubGroup()
		set g = bj_groupRemoveGroupDest
                set dx = x - bj_meleeNearestMineDist
                set dy = y - bj_randomSubGroupChance
                set dist<i>=SquareRoot(dx * dx + dy * dy)
                set i = i + 1
            endloop
            loop
                exitwhen ( j == i )
                set n = j + 1
                loop
                    exitwhen ( n == i )
                    if dist[j] &lt; dist[n] then
                        set g = subgroup[j]
                        set dx = dist[j]
                        set subgroup[j]=subgroup[n]
                        set dist[j]=dist[n]
                        set subgroup[n]=g
                        set dist[n]=dx
                    endif
                    set n = n + 1
                endloop
                set j = j + 1
            endloop
            loop
	        exitwhen i &lt; 0
                set v = FirstOfGroup(subgroup<i>)
                set dist<i>=0.28 * dist<i>
                set dx = bj_RADTODEG * Atan2(GetUnitY(v) - y , GetUnitX(v) - x)
                call GroupPointOrder(subgroup<i> , order , x + dist<i> * Cos(dx * bj_DEGTORAD) , y + dist<i> * Sin(dx * bj_DEGTORAD))
                call TriggerSleepAction(t)
                call DestroyGroup(subgroup<i>)
                set subgroup<i>=null
	        set i = i - 1
            endloop
        endif
    endif
    call DestroyBoolExpr(b)
    call DestroyGroup(g)
    set g = null
    set v = null
    set p = null
endfunction</i></i></i></i></i></i></i></i></i></i></i></i></i></i></i></i></i></i></i></i></i>
 

Attachments

  • mass_1.jpg
    mass_1.jpg
    218.1 KB · Views: 1,143
  • mass_2.jpg
    mass_2.jpg
    176.2 KB · Views: 1,001
  • Mass Movement System.w3x
    231.7 KB · Views: 643

Sim

Forum Administrator
Staff member
Reaction score
534
I suggest indenting a bit your wall of texts...

This is a real mess trying to read that :p
 

emjlr3

Change can be a good thing
Reaction score
395
looks kool, though I dont get it much
 

Doomhammer

Bob Kotick - Gamers' corporate spoilsport No. 1
Reaction score
67
looks kool, though I dont get it much

1) in short: if ordering masses of units to a certain position is an issue, then this can help alleviate movement lags.

2) maybe things become clearer when you have a look at the test map
 

Doomhammer

Bob Kotick - Gamers' corporate spoilsport No. 1
Reaction score
67
I really meant it, seriously. This isn't an essay ;)

Well, yeah. This is meant to illustrate the single problems that occur with lots of units and how they're solved to a large extent. It's by no means a must-read! It's rather some extra info for those who want to know it all. If it pleases your taste, then I can cut out the reading-part and paste it as trigger comment in the map. I already made all my efforts to format the text.
 

Cohadar

master of fugue
Reaction score
209
This would be soooo good to see in some footy map.

PS: Code looks like from stone age :)
 
N

NuBy

Guest
Wow, this is pretty cool lol, BUT you should remove the rat noise :p I swear its annoying. lol
 

Doomhammer

Bob Kotick - Gamers' corporate spoilsport No. 1
Reaction score
67
@ NuBy: LOL, the rats sound. Funny, isn't it? If it starts getting annoying, switch over to sheep:D

@Daxtreme: Recent changes:
I refreshed the first post as well as the map itself: My detailed descriptions are packed into a map comment section. Also I fixed some leaks with the GUI example triggers in the map :rolleyes:
 

Sim

Forum Administrator
Staff member
Reaction score
534
So yea I created about 200 units and ordered them to attack.

Here are the results:



They walk, stop, walk, stop, walk, stop.

Some of them gather in groups. Others don't.

Some don't really move at all :p

Keep in mind I had some more units and I ordered them all to the same point using the system.
 

Doomhammer

Bob Kotick - Gamers' corporate spoilsport No. 1
Reaction score
67
rough words over my MMS.

Unless your PC is poorly equipped (what are your stats, Dax?), I can't find much of an explanation for units not moving at all. There are some exceptional situations when one positioning of units may cause some strange effects to happen (sometimes if they stand extremely dense together), yet all in all the sorting algorithms are reliable. The stop-and-go motion is due to the warcraft engine overwhelmed with unit movements. At a certain point starting with ~300 units+ it starts to get too much calculation work for the movement despite the fact that the system really facilitates the job. So that's basically part of the essence Phyrex and me ended up with in the end: Warcraft3 simply isn't made for numbers of units that high. Yet given the fact that with a simple UnitPointOrder you're very likely to get tailbacks, congestions and severe movement lags with unit numbers of about 80+, the system does serve its purpose for unit amounts of ~ 80 to ~300.
Also, I see that you're commanding all units together, which means that the fast units (footmen) have to adapt their speed to the slow units (sheep), which causes additional tailbacks. Hence it is always more efficient (and allows more control) to command unit types seperately.
Feel free to have some more test runs. What you experienced can't be regular.
 

Sim

Forum Administrator
Staff member
Reaction score
534
> Unless your PC is poorly equipped

Can't be that, it's general and I've seen it happen in my own map too, as well as TDs with lots of units such as wintermauls.

> At a certain point starting with ~300 units+ it starts to get too much calculation work for the movement despite the fact that the system really facilitates the job. So that's basically part of the essence Phyrex and me ended up with in the end: Warcraft3 simply isn't made for numbers of units that high.

False, in Starcraft Zone Control the maker definitely succeeded in ordering several hundreds of unit at the same time without any sort of congestion :p

In some TDs too a lot of units get ordered but don't congestionate.

I investigated but never got the answer.

> I see that you're commanding all units together, which means that the fast units (footmen) have to adapt their speed to the slow units (sheep),

In this screenshot I did, but later in the game I commanded only sheeps. Same results.
 

Doomhammer

Bob Kotick - Gamers' corporate spoilsport No. 1
Reaction score
67
>
> At a certain point starting with ~300 units+ it starts to get too much calculation work for the movement despite the fact that the system really facilitates the job. So that's basically part of the essence Phyrex and me ended up with in the end: Warcraft3 simply isn't made for numbers of units that high.

False, in Starcraft Zone Control the maker definitely succeeded in ordering several hundreds of unit at the same time without any sort of congestion :p

Not quite. Funny enough I happen to work together with the maker of Starcraft Zone Control for several months now. The maximum unit amount a single player could have and order was (up to v. 5.0.51 which is about the last released) set to 120, not to several hundred. Units wouldn't congest since on a single command they're less than 120 i.e. far less than ~300 (due to the rapid kill rate mostly a good deal less than 120 a player), starting rather widely diffused from different spots, and are shot away before they even could congest.

>
In some TDs too a lot of units get ordered but don't congestionate.

How much is a lot? Is it 30, is it 50, is it maybe 70 or is it 200?

> I see that you're commanding all units together, which means that the fast units (footmen) have to adapt their speed to the slow units (sheep),

In this screenshot I did, but later in the game I commanded only sheeps. Same results.
So you're saying that this system, which has worked very will in my zone control maps before
http://world-editor-tutorials.thehelper.net/maps.php?view=353
http://world-editor-tutorials.thehelper.net/maps.php?view=287
(even with older versions of the system which were far inferior in handling dense clusters of units), which works perfectly in the new Starcraft Zone Control, which works nicely in the current version of my Warcraft Zone Control, and which works well on my PC, when I have test runs in this very test map constantly causes tailbacks, units clustering and not moving, as well as severe congestions during your test runs, no matter how many units (starting from 10 to several hundred) of which type you're commanding around?
 

Sim

Forum Administrator
Staff member
Reaction score
534
Well I had thought there were more units while I was playing than 120, but then again it's a long time ago. It might have been around that.

> How much is a lot? Is it 30, is it 50, is it maybe 70 or is it 200?

Well for example in Element TD there might be around 200 units at the same time and they move perfectly well.

> no matter how many units (starting from 10 to several hundred) of which type you're commanding around?

Where did I mention 10 units...? We're speaking of 200+ units there and I said it.

It doesn't matter the type.

Anyways, this system is by far superior to others. I acknowledge the fact that there is a limit to the amount of units that can be moved, I just thought that maybe a system could maybe get rid of it ;)

Approved.
 

Legacyspy

New Member
Reaction score
19
Doomhammer
THANK YOU SO MUCH.
I've been looking for something like this for so long, as I had problems you mentioned with ordering units to move.
Thank YOU.
 

Technomancer

New Member
Reaction score
14
Well I had thought there were more units while I was playing than 120, but then again it's a long time ago. It might have been around that.

> How much is a lot? Is it 30, is it 50, is it maybe 70 or is it 200?

Well for example in Element TD there might be around 200 units at the same time and they move perfectly well.

> no matter how many units (starting from 10 to several hundred) of which type you're commanding around?

Where did I mention 10 units...? We're speaking of 200+ units there and I said it.

It doesn't matter the type.

Anyways, this system is by far superior to others. I acknowledge the fact that there is a limit to the amount of units that can be moved, I just thought that maybe a system could maybe get rid of it ;)

Approved.

I've always had issues with element TD, a good way to glitch that game is to spam any splash tower and Life towers because the animation causes the units to lag and then the life towers mop up giving you tons of lives and a very slow walkthrough rate.
 
General chit-chat
Help Users
  • No one is chatting at the moment.
  • Varine Varine:
    How can you tell the difference between real traffic and indexing or AI generation bots?
  • The Helper The Helper:
    The bots will show up as users online in the forum software but they do not show up in my stats tracking. I am sure there are bots in the stats but the way alot of the bots treat the site do not show up on the stats
  • Varine Varine:
    I want to build a filtration system for my 3d printer, and that shit is so much more complicated than I thought it would be
  • Varine Varine:
    Apparently ABS emits styrene particulates which can be like .2 micrometers, which idk if the VOC detectors I have can even catch that
  • Varine Varine:
    Anyway I need to get some of those sensors and two air pressure sensors installed before an after the filters, which I need to figure out how to calculate the necessary pressure for and I have yet to find anything that tells me how to actually do that, just the cfm ratings
  • Varine Varine:
    And then I have to set up an arduino board to read those sensors, which I also don't know very much about but I have a whole bunch of crash course things for that
  • Varine Varine:
    These sensors are also a lot more than I thought they would be. Like 5 to 10 each, idk why but I assumed they would be like 2 dollars
  • Varine Varine:
    Another issue I'm learning is that a lot of the air quality sensors don't work at very high ambient temperatures. I'm planning on heating this enclosure to like 60C or so, and that's the upper limit of their functionality
  • Varine Varine:
    Although I don't know if I need to actually actively heat it or just let the plate and hotend bring the ambient temp to whatever it will, but even then I need to figure out an exfiltration for hot air. I think I kind of know what to do but it's still fucking confusing
  • The Helper The Helper:
    Maybe you could find some of that information from AC tech - like how they detect freon and such
  • Varine Varine:
    That's mostly what I've been looking at
  • Varine Varine:
    I don't think I'm dealing with quite the same pressures though, at the very least its a significantly smaller system. For the time being I'm just going to put together a quick scrubby box though and hope it works good enough to not make my house toxic
  • Varine Varine:
    I mean I don't use this enough to pose any significant danger I don't think, but I would still rather not be throwing styrene all over the air
  • The Helper The Helper:
    New dessert added to recipes Southern Pecan Praline Cake https://www.thehelper.net/threads/recipe-southern-pecan-praline-cake.193555/
  • The Helper The Helper:
    Another bot invasion 493 members online most of them bots that do not show up on stats
  • Varine Varine:
    I'm looking at a solid 378 guests, but 3 members. Of which two are me and VSNES. The third is unlisted, which makes me think its a ghost.
    +1
  • The Helper The Helper:
    Some members choose invisibility mode
    +1
  • The Helper The Helper:
    I bitch about Xenforo sometimes but it really is full featured you just have to really know what you are doing to get the most out of it.
  • The Helper The Helper:
    It is just not easy to fix styles and customize but it definitely can be done
  • The Helper The Helper:
    I do know this - xenforo dropped the ball by not keeping the vbulletin reputation comments as a feature. The loss of the Reputation comments data when we switched to Xenforo really was the death knell for the site when it came to all the users that left. I know I missed it so much and I got way less interested in the site when that feature was gone and I run the site.
  • Blackveiled Blackveiled:
    People love rep, lol
    +1
  • The Helper The Helper:
    The recipe today is Sloppy Joe Casserole - one of my faves LOL https://www.thehelper.net/threads/sloppy-joe-casserole-with-manwich.193585/
  • The Helper The Helper:
    Decided to put up a healthier type recipe to mix it up - Honey Garlic Shrimp Stir-Fry https://www.thehelper.net/threads/recipe-honey-garlic-shrimp-stir-fry.193595/

      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