• 🏆 Texturing Contest #33 is OPEN! Contestants must re-texture a SD unit model found in-game (Warcraft 3 Classic), recreating the unit into a peaceful NPC version. 🔗Click here to enter!
  • It's time for the first HD Modeling Contest of 2024. Join the theme discussion for Hive's HD Modeling Contest #6! Click here to post your idea!

[General] Item Spawning

Status
Not open for further replies.

sentrywiz

S

sentrywiz

I have this map:

Untitled.jpg

I want to spawn X number of item ONLY IN the brown sections of the map.

Now, I don't want to flood the map with trees just to prevent items spawning on the top ground and I don't want to create millions of
small regions and randomize them.

Is there any other way? A simpler, easier way to make this?
 
Level 21
Joined
Aug 13, 2011
Messages
739
Each time this trigger is run, it'll loop until it finds Black Marble terrain to spawn the item:
  • Events
  • Conditions
  • Actions
    • Set TempPoint = (Random point in (Playable map area))
    • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
      • If - Conditions
        • (Terrain type at TempPoint) Equal to Cityscape - Black Marble
      • Then - Actions
        • Item - Create Item at TempPoint
      • Else - Actions
        • Trigger - Run (This trigger) (checking conditions)
    • Custom script: call RemoveLocation (udg_TempPoint)
 
Level 25
Joined
Sep 26, 2009
Messages
2,381
I think you can check what texture is at a location.
With that, you could think of the terrain as a binary matrice, because the terrain either contains part you want to spawn item on or it does not contain it.

You will need these variables:
- a point variable
- a point array
- five integer variables
- four real variables

You want to divide the whole terrain into smallest possible parts so that you can check each point (where you can change texture) in the terrain. The smallest part of terrain is as big as the smallest rectangle brush (I think its 32x32, but you can easily check that in WE).
Choose the upper-left-most corner of the map as start point and make two loops, one nested in the other. One loop will iterate through each row and the other through each column. For each iteration of the second loop you calculate x and y coordinates as offset of the original coordinates and create a new location at the coordinates you set - then check if location at that point has the brown texture or not. If yes, save the location into point array, else destroy the point.

After the loop ends, the point array will contain all locations where you can spawn items. Then it would be just a matter of choosing numerous random number as indexes and choosing those locations.


Since I can't access WE for the time being, I'll write pseudo-code. It's in the hidden tabs.
Variables:
X, Y, sX, sY = real variables, they represent X, respectively Y coordinates. sX and sY stands for startX/Y and are meant for the X and Y coordinates of the starting point.
col, row, index, i, j = integer variables, col = number of columns, row = number of rows, index = index for point array; variable i and j are just used for iteration in loops.
loc = point variable
spawnPoints = point array

First, manually calculate the number of columns and rows. If the smallest part is 32x32, then divide the total lenght/width of playable map area by 32.

For start point, take the upper-left-most corner of the playable map and offset it by half width and height of the smallest part. This way, you will always check center of each smallest part, not its upper-left most corner.

Code:
row = height / 32
col = width / 32

sX = coordinate X of upper-left-most corner + 16
sY = coordinate Y of upper-left-most corner + 16

for integer i from 0 to row do:
    for integer j from 0 to col do:
        X = sX + 32 * j
        Y = sY + 32 * i
        loc = location at X and Y
        if (terrain at loc == brown terrain) do:
            index = index + 1
            spawnPoint[index] = loc
        else
            destroy loc
notice I do not destroy points that contain the brown terrain. Also, do not rewrite index, unless you destroy all points in spawnPoints array.

Lastly, I can spawn items randomly by doing this:
Code:
integer i = random integer from 0 to index
create item at spawnPoints[i]

Of course you could create your own pseudo-random number generator so that you won't end up with items being spawned way too close to each other.
You could also deindex locations where you spawned items so that you won't spawn two items at same location.
 
Level 37
Joined
Mar 6, 2006
Messages
9,240
  • Events
  • Conditions
  • Actions
    • Set TempPoint = (Random point in (Playable map area))
    • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
      • If - Conditions
        • (Terrain type at TempPoint) Equal to Cityscape - Black Marble
      • Then - Actions
        • Item - Create Item at TempPoint
      • Else - Actions
        • Trigger - Run (This trigger) (checking conditions)
    • Custom script: call RemoveLocation (udg_TempPoint)

You should remove the location before running the trigger again.
 

sentrywiz

S

sentrywiz

Each time this trigger is run, it'll loop until it finds Black Marble terrain to spawn the item:
  • Events
  • Conditions
  • Actions
    • Set TempPoint = (Random point in (Playable map area))
    • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
      • If - Conditions
        • (Terrain type at TempPoint) Equal to Cityscape - Black Marble
      • Then - Actions
        • Item - Create Item at TempPoint
      • Else - Actions
        • Trigger - Run (This trigger) (checking conditions)
    • Custom script: call RemoveLocation (udg_TempPoint)

Beautiful. Didn't even think it was possible to check for terrain textures.
But like @Maker says, the location leaks way too many times.

I will change this to also remove location each iteration.

+rep anyway (to all)

I think you can check what texture is at a location.
With that, you could think of the terrain as a binary matrice, because the terrain either contains part you want to spawn item on or it does not contain it.

You will need these variables:
- a point variable
- a point array
- five integer variables
- four real variables

You want to divide the whole terrain into smallest possible parts so that you can check each point (where you can change texture) in the terrain. The smallest part of terrain is as big as the smallest rectangle brush (I think its 32x32, but you can easily check that in WE).
Choose the upper-left-most corner of the map as start point and make two loops, one nested in the other. One loop will iterate through each row and the other through each column. For each iteration of the second loop you calculate x and y coordinates as offset of the original coordinates and create a new location at the coordinates you set - then check if location at that point has the brown texture or not. If yes, save the location into point array, else destroy the point.

After the loop ends, the point array will contain all locations where you can spawn items. Then it would be just a matter of choosing numerous random number as indexes and choosing those locations.


Since I can't access WE for the time being, I'll write pseudo-code. It's in the hidden tabs.

I'm very interested in the way you suggested.
Even though I found a simpler solution, I also like the kind of complex
math and explanation about your answer.

Amazing. Almost wish I didn't found the other simpler way :p
 
Status
Not open for further replies.
Top