Random Town Locations

Squeekems

TH.net Regular
Reaction score
11
I am making a map that randomly generates itself at start. I am going to have 6 villages owned by players 7-12 and I want them to spawn in random locations on the map, but not near each other. Any ideas on how I could do this?

This trigger sets the points of the villages, clears the areas of trees, and spawns the town halls. Regions are centered on the points of the villages.
The problem with this is the villages can spawn next to each other.

Trigger:
  • Set Villages
    • Events
    • Conditions
    • Actions
      • Set TempPoint[0] = (Center of (Playable map area))
      • For each (Integer A) from 0 to 5, do (Actions)
        • Loop - Actions
          • For each (Integer B) from 0 to 1, do (Actions)
            • Loop - Actions
              • Set TempReal[(Integer B)] = (Random real number between -5000.00 and 5000.00)
          • Set VillagePoint[(Integer A)] = (TempPoint[0] offset by (TempReal[0], TempReal[1]))
          • Region - Center Village[(Integer A)] on VillagePoint[(Integer A)]
          • Destructible - Pick every destructible in Village[(Integer A)] and do (Destructible - Remove (Picked destructible))
          • Unit - Create 1 Village Hall for (Player(((Integer A) + 7))) at VillagePoint[(Integer A)] facing Default building facing degrees
      • Custom script: call RemoveLocation(udg_TempPoint[0])
 

GFreak45

I didnt slap you, i high 5'd your face.
Reaction score
130
u could do this SO easily with jass since you can do custom loops

JASS:
scope TownLocations initializer SetTownLocations
    function CheckRange takes real x, real y, integer a returns boolean
        local integer i = 7
        local bool ret = true
        loop
            exitwhen i == 0
            if a != i
                set ret = ret and SquareRoot(Pow(x - GetLocationX(udg_TownLocations<i>), 2) + Pow(y - GetLocationY(udg_TownLocations<i>), 2)) &lt;= MinDistanceBetweenTowns
            endif
            set i = i - 1
        endloop
    endfunction

    function SetTownLocations takes nothing returns nothing
        local integer i = 7
        loop
            exitwhen i == 0
            loop
                set udg_TownLocations<i> = Location(GetRandomReal(), GetRandomReal(), i)
                exitwhen CheckRange(GetLocationX(udg_TownLocations<i>), GetLocationY(udg_TownLocations<i>))
            endloop
            set i = i -1
            endloop
    endfunction
endscope</i></i></i></i></i>
 

skyblader

You're living only because it's illegal killing.
Reaction score
159
There was once someone made for me the triggers, to spawn a number of resources randomly on the map, with a minimum gap in between. However it causes real lag at the start of the game, and I don't really understand how it works >< You might wanna give it a try if yoy don't prefer the one GFreak suggested.

Trigger:
  • Setup Resources
    • Events
      • Time - Elapsed game time is 0.00 seconds
    • Conditions
    • Actions
      • Set ResourceBlockers = (Units of type Resource Blocker)
      • Set ResourcePoint[1] = (Random point in (Playable map area))
      • Set ResourceInteger = 2
      • Trigger - Run Resource Points &lt;gen&gt; (ignoring conditions)


Trigger:
  • Resource Points
    • Events
    • Conditions
    • Actions
      • Set ResourcePoint[ResourceInteger] = (Random point in (Playable map area))
      • Set ResourceBoolean = False
      • For each (Integer A) from 1 to (ResourceInteger - 1), do (Actions)
        • Loop - Actions
          • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
            • If - Conditions
              • (Distance between ResourcePoint[ResourceInteger] and ResourcePoint[(Integer A)]) Less than 1500.00
            • Then - Actions
              • Set ResourceBoolean = True
            • Else - Actions
      • Unit Group - Pick every unit in ResourceBlockers and do (Actions)
        • Loop - Actions
          • Set TempPoint = (Position of (Picked unit))
          • For each (Integer A) from 1 to (Number of units in ResourceBlockers), do (Actions)
            • Loop - Actions
              • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
                • If - Conditions
                  • (Distance between ResourcePoint[ResourceInteger] and TempPoint) Less than 200.00
                • Then - Actions
                  • Set ResourceBoolean = True
                • Else - Actions
          • Custom script: call RemoveLocation(udg_TempPoint)
      • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
        • If - Conditions
          • ResourceBoolean Equal to True
        • Then - Actions
          • Trigger - Run (This trigger) (ignoring conditions)
        • Else - Actions
          • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
            • If - Conditions
              • ResourceInteger Not equal to 15
            • Then - Actions
              • Set ResourceInteger = (ResourceInteger + 1)
              • Wait 0.20 seconds
              • Trigger - Run (This trigger) (ignoring conditions)
            • Else - Actions
              • For each (Integer B) from 1 to 15, do (Actions)
                • Loop - Actions
                  • Unit - Create 1 Resources for Player 12 (Brown) at ResourcePoint[(Integer B)] facing Default building facing degrees
                  • Cinematic - Ping minimap for (All players) at ResourcePoint[(Integer B)] for 5.00 seconds
                  • Custom script: call RemoveLocation(udg_ResourcePoint[bj_forLoopBIndex])
 

Squeekems

TH.net Regular
Reaction score
11
u could do this SO easily with jass since you can do custom loops

You think could explain how this all works for me, GFreak45? I am not a Jass user, but if it will do it without the major lagfest, I will use it. (Custom loops sounds like a tool I want to have on my belt, too. <(o_- )>)

What is scope? Is SetTownLocations another function that calls this code?

Why is i = 7? I would understand it better if it went from 7 to 12, but it goes from 7 to 0? That seems like it will do the loop 7 times. There are only 6 towns.

Is set setting two different variables in the same line?

How would I implement this code into my triggers? This may become more clear with my questions answered.

There was once someone made for me the triggers, to spawn a number of resources randomly on the map, with a minimum gap in between. However it causes real lag at the start of the game, and I don't really understand how it works >< You might wanna give it a try if yoy don't prefer the one GFreak suggested.

Yeah, I came up with a system similar to that for one of my previous maps. It's not fun at all. Thanks for the suggestion, though. <(^_^)>
 

GFreak45

I didnt slap you, i high 5'd your face.
Reaction score
130
My suggestion requires jass newgen to compile correctly, but it shouldnt cause major lag spikes or anything, it is run at map initialization and will continue running till every town has a location that is not within MinDistanceBetweenTowns, replace this with the range you want, and the global variable i set it up to use is a point variable TownLocations with array checked

set ret = ret and something else is a boolean where it has to be true and another condition has to be true for it to be set to true

first you need to know this:
functions can be an action or a return function
Triggering unit is a return function that returns a unit - the triggering unit, they are referenced by other functions and by variables
ie:
JASS:
function DoMath takes integer a returns integer
    return a + 1
endfunction


so when you call that u use [ljass]call DoMath(integer a)[/ljass] where when u plug something in where integer a is it returns a + 1

Next are local variables, they are variables that store information unique to that trigger that exact time that it is running, for example:

JASS:
function Test takes nothing returns nothing
    local integer a = 1
    call PolledWait(10.0) //this is a wait for 10 seconds
    set a = a + 1
endfunction


in that function the end result a will ALWAYS be a = 2, regardless of how many times you run this it will always wind up with the variable a equaling 2, even if in between the wait the variable is changed in another trigger

before you go on now you need to know how the script compiles, basically a trigger is a long text script, but because of the way wc3 is compiled, when it puts all these triggers into 1 long script it does it in a random order, so these next things are used to organize that better, functions can not call other functions that are above them when the script compiles

next is encapsulation or wrapping functions in other types of text
[ljass]scope[/ljass] - used to make a function private and easily initialize functions (run at map init), these are compiled randomly with the other triggers, when a function is made private, it can not be referenced by a function in another scope, good for using generic names for functions
[ljass]library[/ljass] - used to put functions at the top of the script, mainly for systems so other people can call those functions, these libraries can require other libraries, making those libraries compile above them in the script
[ljass]struct[/ljass] - a complex way to organize varriable array indexes and encapsule methods (functions with extra functionality) - ignore these until you have a firm grasp on jass
 

Squeekems

TH.net Regular
Reaction score
11
My suggestion requires jass newgen to compile correctly, but it shouldnt cause major lag spikes or anything, it is run at map initialization and will continue running till every town has a location that is not within MinDistanceBetweenTowns, replace this with the range you want, and the global variable i set it up to use is a point variable TownLocations with array checked

set ret = ret and something else is a boolean where it has to be true and another condition has to be true for it to be set to true

[ljass]scope[/ljass] - used to make a function private and easily initialize functions (run at map init), these are compiled randomly with the other triggers, when a function is made private, it can not be referenced by a function in another scope, good for using generic names for functions
[ljass]library[/ljass] - used to put functions at the top of the script, mainly for systems so other people can call those functions, these libraries can require other libraries, making those libraries compile above them in the script
[ljass]struct[/ljass] - a complex way to organize varriable array indexes and encapsule methods (functions with extra functionality) - ignore these until you have a firm grasp on jass

So, I quoted everything that is new to me in your post. And now I have some new questions and some old ones. <( >_<)> (I should probably just message you)

1. Is jass newgen something that others need to get to use my map if I use it?
2. Why are you decrementing i in the function seven times? Should it not increment six times from 7?
3. How do I add this to my map? Lol. I tried just converting a new trigger to text and pasting it over what was there, and that was clearly wrong. I can probably answer some questions myself if I can play with the code.

Sorry if these are generic questions. :/
 

GFreak45

I didnt slap you, i high 5'd your face.
Reaction score
130
replace a few things in the code with your versions, MinDistanceBetweenTowns should be a real number which is the real distance minimum between your towns, this can not be huge because if there happens to be no space left for the towns the loop will never end and cause a crash, just make sure the map is big enough that the towns arent taking up most the map

also udg_TownLocations should be the point variable that you want to use with the udg_ prefix, you can change the name on it to whatever

it requires Jass newgen package to compile the map but to play it you just need wc3 ROC or TFT, basically every time you open it in the editor, it has to be JNPG

I decrement it by 1 that extra time so it hits the exitwhen requirement, but it exits before it sets 0 to a town location, you could also move the exitwhen line to after the function calls before the set i = i - 1 and change the 0 to 1 and it would work the same, or to after the set i = i - 1 and keep it 0, all of these would work properly
 
General chit-chat
Help Users
  • No one is chatting at the moment.

      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