• 🏆 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!

Unit Spawn

Status
Not open for further replies.
Level 2
Joined
Aug 8, 2022
Messages
20
I want to make a spawn system like in Direct Strike, where u have a region to build units, and other region to spawn those units every 30 sec. I've already make a build stuff, but dont understand how to make a spawn trigger, any ideas?
 

Uncle

Warcraft Moderator
Level 64
Joined
Aug 10, 2018
Messages
6,579
For the every 30 seconds part you can either use a Timer event, which requires a variable, or the Periodic Interval event:
  • Events
    • Time - YourTimer expires
  • Events
    • Time - Every 30.00 seconds of game time
Both work fine. Timers have a bit more flexibility but it's not a big deal.

So now that our trigger has the correct Event, we simply need to Pick every unit in our "Build" Region and Create copies of them at our "Spawn" Region:
  • Spawn P1
    • Events
      • Time - Every 30.00 seconds of game time
    • Conditions
    • Actions
      • Set VariableSet TempGroup = (Units in P1Build <gen>)
      • Set VariableSet TempPoint = (Center of P1Spawn <gen>)
      • Unit Group - Pick every unit in TempGroup and do (Actions)
        • Loop - Actions
          • Unit - Create 1 (Unit-type of (Picked unit)) for Player 1 (Red) at TempPoint facing Default building facing degrees
      • Custom script: call DestroyGroup(udg_TempGroup)
      • Custom script: call RemoveLocation(udg_TempPoint)
The Variables/Custom script are there to help with memory leaks. Doing this is basically "emptying your recycle bin", it's not necessary but it's recommended.


If your map has multiple Players I would recommend a more advanced approach that uses a similar method but takes advantage of Array variables to greatly improve the flexibility. The best thing you can learn early on is how to use an Array variable and how to use a Player's Number as the [index]. The earlier you start using this design pattern the easier, cleaner, and more efficient your triggers will be.

With that in mind, I would use a Player Group that contains all of my active Players, either a Timer array variable which gives each Player their own "Spawn Timer" or a single Timer variable that is shared, and two Region array variables which track each Player's Build and Spawn Regions. Having these variables will greatly improve all of your future triggers since you would now have access to this data at any time.

Here's an example of setting up your Region arrays:
  • Events
    • Map initialization
  • Actions
    • Set Variable BuildRegion[1] = P1Build <gen>
    • Set Variable BuildRegion[2] = P2Build <gen>
    • Set Variable BuildRegion[3] = P3Build <gen>
    • Set Variable SpawnRegion[1] = P1Spawn <gen>
    • Set Variable SpawnRegion[2] = P2Spawn <gen>
    • Set Variable SpawnRegion[3] = P3Spawn <gen>
Here's an example of using BuildRegion[]. This trigger would create a Paladin for each of our active Players at the Center of their Build Region:
  • Events
    • Time - Every 10.00 seconds of game time
  • Actions
    • Player Group - Pick every player in ActivePlayers and do (Actions)
      • Loop - Actions
        • Set Variable TempPoint = (Center of BuildRegion[(Player number of (Picked player))])
        • Unit - Create 1 Paladin for (Picked player) at TempPoint facing Default building facing degrees
        • Custom script: call RemoveLocation(udg_TempPoint)
ActivePlayers is a Player Group variable which would be Set to all of our Users that are actively playing the game. Player Groups are a great way of doing something for multiple Players all at once. Also, when a Player leaves the game you could Remove them from this Player Group. This allows you to easily manage what happens to each Player, for example, a Leaver wouldn't receive a Paladin in the above trigger.
 
Last edited:
Level 2
Joined
Aug 8, 2022
Messages
20
2 issues:
1 - it's spawn worker unit too, construction "Units in BuildP1 matching (triggering unit is building, hero of peon type unit equal to no) does'nt help.
2 - costom scripts causing error.
And next step, can they be spawned in the same formation they were built?
Also they needed to become an allyed unit for player and atack to the target, is it possible to do so without making an ally computer with another fraction color?
 

Uncle

Warcraft Moderator
Level 64
Joined
Aug 10, 2018
Messages
6,579
1: When you use the "matching..." function you need to reference the unit as (Matching unit):
  • Set VariableSet TempGroup = (Units in P1Build <gen> matching (Matching unit) is a Building Equal to False)
Alternatively, you can use an If Then Else in your Pick Every Unit function and filter the units there.

2: You made a mistake either using the wrong variable name or something simple. I'd have to see what you did.

3: To maintain the same formation you need to figure out the unit's distance/angle from the center of the Build Region and then Create them using Point with polar offset, applying the distance/angle to the center of the Spawn Region:
  • Spawn P1
    • Events
      • Time - Every 30.00 seconds of game time
    • Conditions
    • Actions
      • Set Variable TempGroup = (Units in P1Build <gen> matching...)
      • Set Variable BuildPoint = (Center of P1Build <gen>)
      • Set Variable SpawnPoint = (Center of P1Spawn <gen>)
      • Unit Group - Pick every unit in TempGroup and do (Actions)
        • Loop - Actions
          • Set Variable UnitPoint = (Position of (Picked unit))
          • Set Variable Distance = (Distance between UnitPoint and BuildPoint)
          • Set Variable Angle = (Angle between UnitPoint and BuildPoint)
          • Set Variable CreatePoint = (SpawnPoint offset by Distance towards Angle degrees)
          • Unit - Create 1 (Unit-type of (Picked unit)) for Player 1 (Red) at CreatePoint facing Default building facing degrees
          • Custom script: call RemoveLocation(udg_UnitPoint)
          • Custom script: call RemoveLocation(udg_CreatePoint)
      • Custom script: call DestroyGroup(udg_TempGroup)
      • Custom script: call RemoveLocation(udg_BuildPoint)
      • Custom script: call RemoveLocation(udg_SpawnPoint)
4: You have to use Allied Computers for this. You can change the color of Units/Players and even Player names so your Computer can look exactly like the Player.
 
Last edited:
Level 2
Joined
Aug 8, 2022
Messages
20
Ok, first one solved
Second one, first script work, but second cause: Cannot convert rect to location in permanent whichLocation in call to RemoveLocation
  • Spawn
    • Events
      • Time - Every 30.00 seconds of game time
    • Conditions
    • Actions
      • Set VariableSet BuildedP1 = (Units in UnitsP1 <gen> matching ((((Matching unit) is A structure) Equal to False) and ((((Matching unit) is A Hero) Equal to False) and (((Matching unit) is A peon-type unit) Equal to False))))
      • Set VariableSet SpawnT1 = SpawnSpotT1 <gen>
      • Unit Group - Pick every unit in BuildedP1 and do (Actions)
        • Loop - Actions
          • Unit - Create 1 (Unit-type of (Picked unit)) for Player 1 (Red) at (Center of SpawnSpotT1 <gen>) facing Default building facing degrees
      • Custom script: call DestroyGroup(udg_BuildedP1)
      • Custom script: call RemoveLocation(udg_SpawnT1)
 

Uncle

Warcraft Moderator
Level 64
Joined
Aug 10, 2018
Messages
6,579
Here's an example map. Order your units into the Grass (build region) and they will periodically spawn on the Rocks (spawn region).

I have it working for Players 1, 2, and 3.

Note that I'm using a passive Ability called Spawn Classification to figure out which units should be spawnable.

I gave this ability to the Footman, Rifleman, and Knight, but NOT the Peasant.
 

Attachments

  • Build Spawn Example.w3m
    21.5 KB · Views: 6
Last edited:
Level 2
Joined
Aug 8, 2022
Messages
20
I've lost in all this stuff, its not working and i can't understand why 😓
If you mind, can you take a look?
 

Attachments

  • X1.w3m
    141.8 KB · Views: 6

Uncle

Warcraft Moderator
Level 64
Joined
Aug 10, 2018
Messages
6,579
I've lost in all this stuff, its not working and i can't understand why 😓
If you mind, can you take a look?
Some of your variables were wrong so I fixed those. I also found some minor issues in your triggers and fixed them/cleaned them up.

Also, I found an issue when using the DisableBuildability() function across a large region like your Vision region. It was reaching the operation limit which prevented it from working properly.

Luckily, I found a working solution for your map. Use this function on any Regions that you want to be able to build on:
vJASS:
function BuildabilityFix takes rect r returns nothing
    local real minX = GetRectMinX(r)
    local real maxX = GetRectMaxX(r)
    local real minY = GetRectMinY(r)
    local real resetX = minX + 16
    local real x = resetX
    local real y = GetRectMaxY(r) - 16

    loop
    call SetTerrainPathable(x, y, PATHING_TYPE_AMPHIBIOUSPATHING, false)
    set x = x + 32
        if x > maxX then
            set x = resetX
            set y = y - 32
            exitwhen y < minY
        endif
    endloop
endfunction
This disables Amphibious-pathability across the region, which then allows you to build on it.

IMPORTANT - Your buildings must have these stats for it to work:
Placement Prevented By: Amphibious-pathable
Placement Requires: Buildable


Also, if the region is too large this function will fail! A solution would be to divide your region into multiple smaller regions and use this function on each of them. The regions I used it on in your map worked perfectly fine but a region like Vision is way too large.
 

Attachments

  • X1 Uncle 1.w3m
    142.6 KB · Views: 6
Last edited:
Level 2
Joined
Aug 8, 2022
Messages
20
So the last question left at the moment - how to make spawned units belong to computer whitout making P3 and P4 computer? If this is posible of course.
 

Uncle

Warcraft Moderator
Level 64
Joined
Aug 10, 2018
Messages
6,579
So the last question left at the moment - how to make spawned units belong to computer whitout making P3 and P4 computer? If this is posible of course.
It's impossible to make them act like Computers without literally making them Computers.

As far as I know you have two options for your units:
Make them owned by a Computer Player. This fixes most issues and is fairly easy to make work properly.
Keep them owned by the User but have triggers which interrupt/override their issued orders. This method has unwanted side effects and isn't really ideal.

That being said, it's not difficult to manage the Computer Players nor do they literally need to be P3 and P4.

Here's an example where your map has Players, and their Computer allies are Players 13, 14, 15, and 16:
  • Setup Computer Allies
    • Events
      • Time - Elapsed game time is 0.01 seconds
    • Conditions
    • Actions
      • -------- Set each User's computer player: --------
      • Set VariableSet AlliedPlayer[1] = Player 13 (Maroon)
      • Set VariableSet AlliedPlayer[2] = Player 14 (Navy)
      • Set VariableSet AlliedPlayer[3] = Player 15 (Turquoise)
      • Set VariableSet AlliedPlayer[4] = Player 16 (Violet)
      • -------- Set each Computer's user player: --------
      • Set VariableSet AlliedPlayer[13] = Player 1 (Red)
      • Set VariableSet AlliedPlayer[14] = Player 2 (Blue)
      • Set VariableSet AlliedPlayer[15] = Player 3 (Teal)
      • Set VariableSet AlliedPlayer[16] = Player 4 (Purple)
      • -------- Change their colors/names: --------
      • For each (Integer A) from 1 to 4, do (Actions)
        • Loop - Actions
          • Player - Change color of AlliedPlayer[(Integer A)] to (Color of (Player((Integer A)))), Changing color of existing units
          • Player - Set name of AlliedPlayer[(Integer A)] to (Name of (Player((Integer A))))
I attached a map demonstrating this. You can see that the gold bounty for the Computer's kills go to the User instead.
 

Attachments

  • Allied Computer 1.w3m
    18 KB · Views: 6
Last edited:
Status
Not open for further replies.
Top