• 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.
  • The Hive's 22nd Icon Contest: Creep Abilities is now concluded, time to vote for your favourite set of icons! Click here to vote!
  • ✅ The POLL for Hive's Texturing Contest #34 is OPEN! Vote for the TOP 3 SKINS! 🔗Click here to cast your vote!
  • ✅ The POLL for Hive's Techtree Contest #20 is OPEN! Vote for the TOP 3 FACTIONS! 🔗Click here to cast your vote!

How to select cells one by one?

Level 9
Joined
Aug 26, 2016
Messages
204
The screenshot shows the cells as green squares, in which the "POINTS" units are created, but I select 20 points in a certain radius and replace them with other points, for example.
 

Attachments

  • 222.jpg
    222.jpg
    2 MB · Views: 46
It sounds like you want to create a Grid of Points.

One way to do it: Use double nested For Loops to generate Points across the map, where one loop represents the Rows and the other loop represents the Columns. Then during this process, Save each Point in a Hashtable where the Parent Key would be the Row and the Child Key would be the Column. I would personally make Parent: 1, Child: 1 represent the bottom left corner of the Grid but it's up to you.

So when loading 1,1 from the Hashtable you would get the Point saved at the bottom left cell.
Loading 2,1 would get you the Point to the right of it.
Loading 0,1 would fail because 0 breaks the bounds of the Grid. Make sure you have a safety check for this.

For getting Points within a radius, you would first define a starting Cell, then define the search radius which can be a single value representing the "neighbor count", and using basic arithmetic fill an Array with all of the Points loaded from within that radius.

So for example, if your origin is cell 2,2 and your radius is 1, that would fill your Array with the Points loaded from these keys:
3,1 / 3,2 / 3,3
2,1 / 2,2 / 2,3
1,1 / 1,2 / 1,3

The actual math is pretty straightforward, you do a number of calculations referencing the origin, adding or subtracting from it as needed.

Edit: Attached an example map.
Type "1" to see an example of creating a unit at a specified grid cell (x/y). Type "2" to see an example of creating multiple units within a radius around a grid cell. Type "3" to see an example of converting Warcraft 3's built-in "world coordinates" into our custom grid cell coordinates. You need to select a unit first for this one to work.

Edit 2: Attached "final" version of the map in one of my later posts.
 
Last edited:
so, what are the green cubes? Units? Destructibles? Something else?
Destructibles.I use them as points for terrain generation via pre-created templates, and the system randomly creates the terrain at these points. But I can't choose a single random point and instead use nearby ones to create tunnel rooms.

It sounds like you want to create a Grid of Points. To do so, use a double nested For Loop to generate Points across the map, where one loop represents the Row and the other loop represents the Column. Then during this process, Save each Point in a Hashtable where the Parent Key would be the Row and the Child Key would be the Column. I would personally make Parent: 1, Child: 1 represent the bottom left corner of the Grid.

So when loading 1,1 from the Hashtable you would get the Point saved at the bottom left cell.
Loading 2,1 would get you the Point to the right of it.
Loading 0,1 would fail because 0 breaks the bounds of the Grid. Make sure you have a safety check for this.

For getting Points within a radius, you would first define a starting Cell, then define the search radius which can be a single value representing the "neighbor count", and using basic arithmetic fill an Array with all of the Points loaded from within that radius.

So for example, if your origin is cell 2,2 and your radius is 1, that would fill your Array with the Points loaded from these keys:
3,1 / 3,2 / 3,3
2,1 / 2,2 / 2,3
1,1 / 1,2 / 1,3

The actual math is pretty straightforward, you do a number of calculations referencing the origin, adding or subtracting from it as needed.

Edit: Attached an example map.
Type "1" to see an example of creating a unit at a specified grid cell (x/y). Type "2" to see an example of creating multiple units within a radius around a grid cell. Type "3" to see an example of converting Warcraft 3's built-in "world coordinates" into our custom grid cell coordinates. You need to select a unit first for this one to work.

Thanks, but it's not exactly what I need, but it's pretty good, and I'm a complete idiot at math...
 
Thanks, but it's not exactly what I need, but it's pretty good, and I'm a complete idiot at math...
So what exactly do you need? Because you said you want to select cells one by one, and I showed how to:
1. Create these cells and store them in a Hashtable.
2. Reference one cell directly.
3. Reference multiple cell at once in a radius.

If the Hashtable is what scares you away then you can also store these cells in an Array of Points during the grid creation:
  • -------- Create and save the grid: --------
  • For each (Integer Grid__Row) from Grid__Min_Y to Grid__Max_Y, do (Actions)
    • Loop - Actions
      • Set VariableSet Grid__World_Y = (Grid__World_Y + Grid__Cell_Size)
      • For each (Integer Grid__Column) from Grid__Min_X to Grid__Max_X, do (Actions)
        • Loop - Actions
          • Set VariableSet Grid__Point = (Point((Grid__World_X + (Grid__Cell_Size x (Real(Grid__Column)))), Grid__World_Y))
          • Hashtable - Save Handle OfGrid__Point as Grid__Column of Grid__Row in Grid__Hash.
          • -------- --------
          • -------- NEW: --------
          • Set VariableSet Grid__Loop = (Grid__Loop + 1)
          • Set VariableSet Grid__All_Points[Grid__Loop] = Grid__Point
          • -------- --------
          • -------- Note: Floating text has a limit of 100 active at a time, so a 12x12 Grid will leave some out! --------
          • Floating Text - Create floating text that reads ((String(Grid__Column)) + (, + (String(Grid__Row)))) at Grid__Point with Z offset 0.00, using font size 10.00, color (100.00%, 100.00%, 100.00%), and 0.00% transparency
Grid__All_Points will now be filled with all of your cells (Points).
Referencing Grid__All_Points[1] will get you the cell in the bottom left corner of the map. Grid__All_Points[2] will get you the cell to the right of it.
The grid in my example map is 12x12 (144 cells in total), so when you reach Grid__All_Points[13] you will return back to the bottom left corner of the map and move up 1 cell (to the next next row). The pattern then repeats itself.

Edit:
I attached a new version that simplifies things even further, you don't have to even touch the Hashtable.
Edit 2: Attached "final" version of the map in one of my later posts.
 
Last edited:
So what exactly do you need? Because you said you want to select cells one by one, and I showed how to:
1. Create these cells.
2. Reference one directly.
3. Reference multiple at once in a radius.

Sounds like a solution to me.
Let's say there's a square, then a turn, or straight ahead. I understand that dungeon generation is a complicated thing, but thanks to your help, I finally got to this point)).
 
It doesn't have to be too complicated, it all depends on how "smart" you want your system to be. Random terrain? Super easy. Random terrain that interconnects and has different rules to prevent overlaps, dead ends, and unreachable locations - Definitely more difficult.

Note that I edited my last post and updated the Grid map. It has an example of some simple terrain generation using "cells one by one", which is done using an Array of Points.
 
Last edited:
So what exactly do you need? Because you said you want to select cells one by one, and I showed how to:
1. Create these cells and store them in a Hashtable.
2. Reference one cell directly.
3. Reference multiple cell at once in a radius.

If the Hashtable is what scares you away then you can also store these cells in an Array of Points during the grid creation:
  • -------- Create and save the grid: --------
  • For each (Integer Grid__Row) from Grid__Min_Y to Grid__Max_Y, do (Actions)
    • Loop - Actions
      • Set VariableSet Grid__World_Y = (Grid__World_Y + Grid__Cell_Size)
      • For each (Integer Grid__Column) from Grid__Min_X to Grid__Max_X, do (Actions)
        • Loop - Actions
          • Set VariableSet Grid__Point = (Point((Grid__World_X + (Grid__Cell_Size x (Real(Grid__Column)))), Grid__World_Y))
          • Hashtable - Save Handle OfGrid__Point as Grid__Column of Grid__Row in Grid__Hash.
          • -------- --------
          • -------- NEW: --------
          • Set VariableSet Grid__Loop = (Grid__Loop + 1)
          • Set VariableSet Grid__All_Points[Grid__Loop] = Grid__Point
          • -------- --------
          • -------- Note: Floating text has a limit of 100 active at a time, so a 12x12 Grid will leave some out! --------
          • Floating Text - Create floating text that reads ((String(Grid__Column)) + (, + (String(Grid__Row)))) at Grid__Point with Z offset 0.00, using font size 10.00, color (100.00%, 100.00%, 100.00%), and 0.00% transparency
Grid__All_Points will now be filled with all of your cells (Points).
Referencing Grid__All_Points[1] will get you the cell in the bottom left corner of the map. Grid__All_Points[2] will get you the cell to the right of it.
The grid in my example map is 12x12 (144 cells in total), so when you reach Grid__All_Points[13] you will return back to the bottom left corner of the map and move up 1 cell (to the next next row). The pattern then repeats itself.

Edit:
I attached a new version that simplifies things even further, you don't have to even touch the Hashtable.

All that's left is to figure out how to track the unit to a point so it doesn't spawn there again, and then we can try spawning passages and rooms, but I have no idea where to start XD
 
All that's left is to figure out how to track the unit to a point so it doesn't spawn there again, and then we can try spawning passages and rooms, but I have no idea where to start XD
A lazy approach would be something like this, where you try to brute force random unused Points and if that fails (very unlikely) you use a fallback plan by Looping over the Array of Points and picking the first unused one you find:
  • Get Random Unused Point
    • Events
    • Conditions
    • Actions
      • -------- With a 12x12 grid this would Loop from 1 to 144: --------
      • Set VariableSet Grid__Size = (Grid__Max_X x Grid__Max_Y)
      • -------- --------
      • -------- Assume we failed to find an unused Point by default. Then set this to False if we find one: --------
      • Set VariableSet Grid__Failed_To_Get_Point = True
      • -------- --------
      • -------- Let's try to find a random unused Point. We will try 200 times before giving up and using a safer, guaranteed method: --------
      • For each (Integer Grid__Loop) from 1 to 200, do (Actions)
        • Loop - Actions
          • Set VariableSet Grid_X = (Random integer number between 1 and Grid__Size)
          • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
            • If - Conditions
              • Grid__Point_Is_Used[Grid_X] Equal to False
            • Then - Actions
              • Set VariableSet Grid__Point_Is_Used[Grid_X] = True
              • Set VariableSet Grid__Point = Grid__All_Points[Grid_X]
              • Set VariableSet Grid__Failed_To_Get_Point = False
              • Custom script: exitwhen true
            • Else - Actions
      • -------- --------
      • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
        • If - Conditions
          • Grid__Failed_To_Get_Point Equal to True
        • Then - Actions
          • For each (Integer Grid__Loop) from 1 to Grid__Size, do (Actions)
            • Loop - Actions
              • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
                • If - Conditions
                  • Grid__Point_Is_Used[Grid__Loop] Equal to False
                • Then - Actions
                  • Set VariableSet Grid__Point_Is_Used[Grid__Loop] = True
                  • Set VariableSet Grid__Point = Grid__All_Points[Grid__Loop]
                  • Custom script: exitwhen true
                • Else - Actions
        • Else - Actions
      • -------- --------
      • -------- By this stage of the trigger we SHOULD have found an unused Point. --------
      • Unit - Create 1 Footman for Player 1 (Red) at Grid__Point facing Default building facing degrees
If you run this trigger 100 times in a row you should end up with 100 Footman all at their own unique Points.

Grid__Point_Is_Used is a Boolean Array variable. It's paired with the Grid__All_Points variable. So like I said before, index [1] represents the bottom left corner cell (Point). So if Grid__Point_Is_Used[1] is set to True then that cell is being used. Note that if all of the Points are used then even the fallback plan will fail to work.

A more advanced approach would be to use a technique like this to guarantee non-repeating cells. Maker's post near the bottom should do the trick.

I'm going to take a break now but hopefully you can figure this all out. Understanding grids was the most important thing for me to learn as a developer, and the math is easy enough even for a dummy like me, you just have to put some time into it. Game development and programming is all grids, lol.
 
Last edited:
  • GridUnit
    • Events
      • Player - Player 1 (Red) skips a cinematic sequence
    • Conditions
    • Actions
      • Set VariableSet Grid__Size = (Grid__Max_X x Grid__Max_Y)
      • Set VariableSet Grid__Failed_To_Get_Point = True
      • For each (Integer Grid__Loop) from 1 to 100, do (Actions)
        • Loop - Actions
          • Set VariableSet Grid_X = (Random integer number between 1 and Grid__Size)
          • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
            • If - Conditions
              • Grid__Point_Is_Uses[Grid_X] Equal to False
            • Then - Actions
              • Set VariableSet Grid__Failed_To_Get_Point = False
              • Set VariableSet Grid__Point_Is_Uses[Grid_X] = True
              • Set VariableSet Grid__Point = Grid__All_Points[Grid_X]
              • Game - Display to (All players) for 5.00 seconds the text: 1
            • Else - Actions
      • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
        • If - Conditions
          • Grid__Failed_To_Get_Point Equal to True
        • Then - Actions
          • For each (Integer Grid__Loop) from 1 to Grid__Size, do (Actions)
            • Loop - Actions
              • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
                • If - Conditions
                  • Grid__Point_Is_Uses[Grid__Loop] Equal to False
                • Then - Actions
                  • Set VariableSet Grid__Point_Is_Uses[Grid__Loop] = True
                  • Set VariableSet Grid__Point = Grid__All_Points[Grid__Loop]
                  • Game - Display to (All players) for 5.00 seconds the text: 2
                • Else - Actions
        • Else - Actions
      • Game - Display to (All players) for 5.00 seconds the text: 3
      • Unit - Create 1 Peasant for Neutral Hostile at Grid__Point facing Default building facing degrees
      • Environment - Change terrain type at Grid__Point to Lordaeron Summer - Dark Grass using variation -1 in an area of size 3 and shape Circle
изображение_2025-10-07_200842896.pngLol
 
Compare the two triggers. Mine has Actions that yours does not have. One missing Action can throw the whole thing off.
  • Skip remaining actions
Edit: Hold on, I think "Skip remaining actions" doesn't work like I expected.

The fix:
Replace all "Skip remaining actions" with this Custom Script:
  • Custom script: exitwhen true
Here's a new map with a working setup.
 

Attachments

Last edited:
Compare the two triggers. Mine has Actions that yours does not have. One missing Action can throw the whole thing off.
  • Skip remaining actions
Edit: Hold on, I think "Skip remaining actions" doesn't work like I expected.

The fix:

Replace all "Skip remaining actions" with this Custom Script:
  • Custom script: exitwhen true
Here's a new map with a working setup.
You are a genius! Next I have to break my face with the creation of the logic of rooms and passages with the help of your system and I can confidently say that I will probably shoot my face off ((
 

Attachments

  • изображение_2025-10-07_204843571.png
    изображение_2025-10-07_204843571.png
    2.6 MB · Views: 22
Back
Top