Make a Building Auto-Spawn Units

Discussion in 'Starcraft 2 (SC2) Editor Help' started by Kyuft, Jan 19, 2012.

  1. Kyuft

    Kyuft Member

    Ratings:
    +11 / 0 / -0
    Hey, I am pretty new to triggers and I need help with a map that has a "king of the hill"ish theme. I want a certain building to spawn a colossus every 40 seconds (for the owner) ONLY if it is owned by someone. I already have the "capturing" of the buildings done, I just need it to spawn units at a certain interval only if it is owner by a player.
    -Kyuft
     
  2. Jokker

    Jokker Member

    Ratings:
    +16 / 0 / -0
    This can be done in several ways. You can make the building actually train these units. This means, you change the build tie of colossus to 40 seconds. Change resource costs to Zero. Then make a trigger, that triggers every 40 game seconds. Orders this building to train a colossus IF it is not controlled by neutral (checks if it is captured). This will automatically make the colossus for the owning player, because the training building is owned by that player. You would be able to see the building process also.

    The second way is just to make a trigger, that creates a unit at the building location every 40 seconds for the owning player of the building.
    Something like Periodic event - every 40 seconds.
    Create a Unit (colossus) at target location (you can add a region or point here, or the location of the building) for the player ( owner of unit(building))

    I'm certain that there are even more ways to do it : D

    I would post pics about the triggers, but I am not at home right now. So if you still have problems later, I'll gladly help.

    Hope this helps,
    Cheers!
     
  3. Jokker

    Jokker Member

    Ratings:
    +16 / 0 / -0
    Trigger:
    • test
      • Events
        • Timer - Every 40.0 seconds of Game Time
      • Local Variables
      • Conditions
      • Actions
        • General - If (Conditions) then do (Actions) else do (Actions)
          • If
            • (Owner of Barracks [93.50, 45.50]) == 0
          • Then
          • Else
            • Unit - Order Barracks [93.50, 45.50] to (Barracks - Train Marine) (Replace Existing Orders)



    This one makes barracks train a marine every 40 seconds. As you can see, it won't do anything, if the barracks are owned by player 0. If its owned by any other player, it will start training a marine though.

    So a couple of things to keep in mind:
    1) You still need to adjust the marine training time to 39 or 1. depends if you want it to train all the 40 seconds or come out every 40 sec without the training process.
    2) If you plan to use the typical training mechanism, remove the supply and resource cost of the unit.
    3) If you plan to use the typical trainng mechanism, you should make the building un-selectable.. (or any other solution, which you like the best) Then the players won't be able to cancel the training process and treat the building "as their own". It should be invulnerable too, if you want it to be a controllpoint.
     
  4. Siretu

    Siretu Starcraft 2 Editor Moderator Staff Member

    Ratings:
    +295 / 0 / -0
    There is a third way which would be to do it in the data editor. Give the spawning building a behavior. In the behavior, make the period 40 seconds, change the periodic effect to a "Create unit" effect that creates a colossus.
     
  5. Kyuft

    Kyuft Member

    Ratings:
    +11 / 0 / -0
    Thanks for the replies! Jokker, I like your ideas, however, is there a way to make it so that every barracks trains the units with the same triggers? Like instead of clicking on the coordinates of a specific building, make it be just barracks in general? So I don't have to make a trigger for each barracks?

    Siretu,
    How will I be able to control when it spawns units. (Only spawn units when it is controlled by a player) I thought that i could just make a trigger that gives the behavior to the unit when it is captured, but wouldn't that give the behavior to every barracks? Is there some sort of requirement that I could give the units? Like, has to be owned by a player other than player 0 (If that means neutral).

    -Kyuft
     
  6. Jokker

    Jokker Member

    Ratings:
    +16 / 0 / -0
    Yes it is possible to order a Unit Group.

    You would need to make a global variable Unit Group. Then put all the buildings in this unit group at map initializtion.
    Then use these two simple triggers: (I named my global variable All Rax)

    This one makes the unit group train a unit every 40 seconds.
    Trigger:
    • Train
      • Events
        • Timer - Every 40.0 seconds of Game Time
      • Local Variables
      • Conditions
      • Actions
        • Unit - Order all units in All Rax to (Barracks - Train Marine) (Replace Existing Orders)


    And this one checks that if the building is owned by player 0, it will cancel the started training process.
    Trigger:
    • OwnerTest
      • Events
        • Unit - Any Unit training progress is Started
      • Local Variables
      • Conditions
        • (Owner of (Triggering unit)) == 0
      • Actions
        • Unit - Cancel progress bar of ((Triggering unit)) slot 1


    I did not test these. So They might need a tweak or two. Cheers.
    Oh and btw, Siretus way of using behaviours is worth checking out. It will teach you about behaviours, as well as will be better for map optimization, although these two triggers are not very heavy on the map lol.
    So Siretus way is more professional and cleaner also. Might be harder to get to work at first though
     
  7. Kyuft

    Kyuft Member

    Ratings:
    +11 / 0 / -0
    I think I might go with Siretu's way, however, there is one problem with what you just posted, all of the buildings will spawn a unit at the same time no matter when they were captured. I would like them to be seperate. Again, Siretu's way is probably the one i will try, but I need his way to only work if the building has been captured.
    -Kyuft
     
  8. Siretu

    Siretu Starcraft 2 Editor Moderator Staff Member

    Ratings:
    +295 / 0 / -0
    Ah, I was going to mention that but forgot it. I would just add a validator but right now I can't seem to find a good validator type to use. Here's something that might work:

    Make a new validator with the "Unit filters" type. Make the "Validator: Unit" caster and in "Validator: Filters", uncheck neutral.

    In the behavior you want to add the validator to "Behavior: Validators (Disable)"

    Also, I just wanted to mention that you don't even have to mess with variables for Jokker's idea. The function "Units in region matching condition" returns a unit group. This means that instead of "All rax", you can use that function to get all rax on the map.
     
  9. Kyuft

    Kyuft Member

    Ratings:
    +11 / 0 / -0
    Now that you mention it, Jokker's idea would work, but your way is much cleaner, easier, and like Jokker said, more professional. Also, whenever I try to give Jokker +rep for helping me, it says," you must spread around rep before giving more to Jokker". the problem is, you and him are the only people that help me alot.
    -Kyuft
     
  10. Kyuft

    Kyuft Member

    Ratings:
    +11 / 0 / -0
    A little off topic:
    I can't seem to be able to make a trigger that goes like this: If there is a unit within 5 units of ANY barracks, then ONLY the barracks that have units nearby will start to make units.
    This is what I have so far:
    Trigger:
    • IDK
      • Events
        • Unit - (Triggering unit) Enters a distance of 5.0 from !!!(What do I put here to make it apply to all rax?)!!!
      • Local Variables
      • Conditions
        • !!!(Do I need to put something here?)!!!
      • Actions
        • Unit - Change Ownership of !!!(What do I put here for all rax?)!!! to player (Triggering player) and Change Color.
     
  11. Jokker

    Jokker Member

    Ratings:
    +16 / 0 / -0
    If I was you, I would make a different kind of system for capture-points.

    My idea:
    1) You go attack the neutral building you want to capture.
    2) If it falls below 20% (example) of health, heal it and change the ownership to the owner of attacking unit.

    Now if the building is allready captured:
    1) You attack the other players captured point.
    2) If it goes below 20% it will change to neutral and gets healed.
    3) You keep attacking.
    4) If it falls below 20% again, it will be healed and ownership is changed to the owner of attacking unit.

    I think this would make the capturing more fun and would add a capturing "progress" in the game. Also the capturing would be faster later as the damage you will be able to deal fast increases.
    NB! This brings me to another idea, if you would implement all of this. ADD UPGRADES to capture points. This would mean capture point armor, maybe even point-defence turrets? Slow auto health regen? maybe a 3 second phase out ability, so it would be harder to attack/to buy time to defend.
    (If you don't want to mess around with any kind of other progress bars for capturing)

    Now, if you still want to make the units spawn with triggers (coz as i said, Siretus version is A LOT of better, but harder to get to work),
    you could implement the spawning into the capturing.

    This could be done like this:
    1) If a building is captured you run another trigger, that tells the captured bulding to train a unit.
    2) another trigger that says: Any unit finishes training a unit. condition - unit is not owned by neutral. action - start training another unit. else ( unit is owned by neutral) - cancel training.

    You could also add a leakproof trigger that checks like every 20 seconds of the game that a neutral building is not training a unit. If it is, cancel it.

    These triggers wont make the map slower. cause there isnt much for the computer to process here. and about 20-40 second loops won't be a problem also. (+ they will not run all together as the capturing is done at different time)

    Hope this makes sense,

    Jokker
     
  12. Siretu

    Siretu Starcraft 2 Editor Moderator Staff Member

    Ratings:
    +295 / 0 / -0
    If you use the data editor to handle the spawning, you just have to add another validator.

    This time add one with the "Enumerate Area" type.

    - Go into Search: Areas and add a new value in the list.

    - Change the area radius to 5.

    - Press okay

    - Change the Search filters to your preference. I would start with excluding Self, Missile, Dead and Hidden.

    That should be all you need. Basically what this does is that it counts the units in the area that fits in your filters. In this case it means it takes all units(that are not the building itself, a missile, dead or hidden) in a 5 radius around the unit and counts them. It then compares them(according to "Validator: Compare" which defaults as "Greater Than") with "Search: Count". So if the amount of units in the 5 radius around the buildings are greater than 0, it will return true, otherwise it becomes false.

    Add this validator at the same place in the behavior as you added the other validator. In other words, add it to the "Behavior: Validators (Disable)" field.

    If you want to do this with triggers instead, you have to make sure to use triggers for spawning as well since it's pretty hard to mix them up like this. Basically what I would do is just skip the trigger you've made entirely and put the stuff in the same place as you have the spawning.

    So let's say you have this trigger for spawning:

    Trigger:
    • Train
      • Events
        • Timer - Every 40.0 seconds of Game Time
      • Local Variables
      • Conditions
      • Actions
        • Unit - Order all units in All Rax to (Barracks - Train Marine) (Replace Existing Orders)


    First of all, I will do a couple of things to modify this in a good way. First of all, let's get rid of All rax since we only need it for this specific thing.

    Trigger:
    • Train
      • Events
        • Timer - Every 40.0 seconds of Game Time
      • Local Variables
      • Conditions
      • Actions
        • Unit - Order all units in (Barracks units in (Entire map) owned by player Any Player matching Excluded: Missile, Dead, Hidden, with at most Any Amount) to (Barracks - Train Marine) (Replace Existing Orders)


    This looks kind of scary but what I did was, I just replace All Rax with the function "Units in Region matching condition" and then I changed the Unit type parameter of that function "Barracks"

    Let's do another modification. I am doing it one modification at a time just so I don't lose you somewhere on the way :)

    Trigger:
    • Train
      • Events
        • Timer - Every 40.0 seconds of Game Time
      • Local Variables
      • Conditions
      • Actions
        • Unit Group - Pick each unit in (Barracks units in (Entire map) owned by player Any Player matching Excluded: Missile, Dead, Hidden, with at most Any Amount) and do (Actions)
          • Actions
            • Unit - Order (Picked unit) to (Barracks - Train Marine) (Replace Existing Orders)


    This is practically the same code as earlier but it looks different. First of all, I added a new action. It's called "Pick each Unit in Unit Group". It's a kind of loop that loops around and does the same actions to all units in the group. A unit group is just a group with units. So let's say we have a unit group with Unit A, Unit B and Unit C. Let's pretend I have a "Pick each Unit in Unit Group" action with a simple action called "Kill (Picked Unit)" in it. It would then pick the first unit in the Unit group(Unit A). This means that the "(Picked Unit) refers to Unit A. So what happens? It kills Unit A. Next up, it would pick Unit B. This means Unit B is now the (Picked Unit) so Unit B will also get killed. Finally, it will pick Unit C as (Picked Unit) and kill it as well.

    Anyway, that was just an example of "Pick each Unit in Unit Group". Let's get back to the trigger above. In the trigger above, the unit group is not the unit group with Unit A, B and C. It's all barracks units in the entire map. So for the Unit group parameter, I picked the function "Units in Region matching condition". This is the same function we used in the first modification I did. I edited in the same way as well. I made the Unit type parameter into "Barracks".

    So this means it'll put all barracks on the map in a group and one by one go through them and set them to (Picked Unit). In this case the action in the loop is "Issue Order". NOTE: This is not the same action that we had before. The one we had before is called "Issue Order to Unit Group". Just make sure the unit refers to (Picked Unit) and that the ability command is "Barracks - Train Marine"

    Let's do another modification. We want to make sure it doesn't spawn for player 0. This means we want a condition, but we can't just add it to the conditions at top because that would apply to the ENTIRE trigger(So if the condition is false, it wont run the trigger at all).

    Let's consider what we want. We want it to ONLY spawn units if the owner of the Barracks is NOT player 0. Here's the new modified trigger:

    Trigger:
    • Train
      • Events
        • Timer - Every 40.0 seconds of Game Time
      • Local Variables
      • Conditions
      • Actions
        • Unit Group - Pick each unit in (Barracks units in (Entire map) owned by player Any Player matching Excluded: Missile, Dead, Hidden, with at most Any Amount) and do (Actions)
          • Actions
            • General - If (Conditions) then do (Actions) else do (Actions)
              • If
                • (Owner of (Picked unit)) != 0
              • Then
                • Unit - Order (Picked unit) to (Barracks - Train Marine) (Replace Existing Orders)
              • Else


    First of all, we added a new action INSIDE the "Pick each Unit in Unit Group" loop. Inside the "If" part, we can add more conditions. If the conditions in there are true, it will run the actions in the "Then" part. Otherwise, it'll run the actions in the "Else" part.

    So we added our condition. It's a simple comparison. Value 1 is "Owner of Unit". You just have to make sure to change the unit to (Picked Unit). This way, it refers to the barracks that the loop is currently picking. I changed the operator to "!=". This means that the entire condition will be true if Value 1 is ANYTHING but Value 2. Value 2 is just 0.

    Then I took the "Issue Order" action from the previous modification and just moved it down in the "Then" part. Since we added a check here, it means that it'll never tell barracks to train the marine if they're owned by player 0. So, that means the entire second trigger Jokker made is not needed anymore since it's there to prevent player 0's units from spawning.

    So this trigger is no longer necessary! You can remove it.
    Trigger:
    • OwnerTest
      • Events
        • Unit - Any Unit training progress is Started
      • Local Variables
      • Conditions
        • (Owner of (Triggering unit)) == 0
      • Actions
        • Unit - Cancel progress bar of ((Triggering unit)) slot 1


    Now finally, we want to add the solution to your last problem. "If there is a unit within 5 units of ANY barracks, then ONLY the barracks that have units nearby will start to make units.". As I see it, there's two possibilities.

    1. There are no units within 5 range of any barracks. This means all barracks spawn units.

    2. Some barracks have units within 5 range, only these barracks spawn units.

    So, what we're going to do is have an integer variable called "nrUnits". We'll use this to count the total amount of units around all the barracks. If this is 0, it means that we're in case 1(see above). Otherwise, we're in case 2.

    This will be a big modification but don't be afraid, I'll go it through line by line.

    Trigger:
    • Train
      • Events
        • Timer - Every 40.0 seconds of Game Time
      • Local Variables
        • nrUnits = 0 <Integer>
      • Conditions
      • Actions
        • Unit Group - Pick each unit in (Barracks units in (Entire map) owned by player Any Player matching Excluded: Missile, Dead, Hidden, with at most Any Amount) and do (Actions)
          • Actions
            • General - If (Conditions) then do (Actions) else do (Actions)
              • If
                • (Owner of (Picked unit)) != 0
              • Then
                • Variable - Set nrUnits = (nrUnits + (Number of Living units in (Any units in (Region((Position of (Picked unit)), 5.0)) owned by player Any Player matching Excluded: Missile, Dead, Hidden, with at most Any Amount)))
              • Else
        • Unit Group - Pick each unit in (Barracks units in (Entire map) owned by player Any Player matching Excluded: Missile, Dead, Hidden, with at most Any Amount) and do (Actions)
          • Actions
            • General - If (Conditions) then do (Actions) else do (Actions)
              • If
                • (Owner of (Picked unit)) != 0
                • Or
                  • Conditions
                    • nrUnits == 0
                    • (Number of Living units in (Any units in (Region((Position of (Picked unit)), 5.0)) owned by player Any Player matching Excluded: Missile, Dead, Hidden, with at most Any Amount)) > 0
              • Then
                • Unit - Order (Picked unit) to (Barracks - Train Marine) (Replace Existing Orders)
              • Else


    As you can see, I added a new variable to Local variables. It's called "nrUnits" and it is of the Integer type. I made this a LOCAL variable since we don't really need to use this variable anywhere else.

    You might also notice that there are two "Pick each Unit in Unit Group" loops now instead of one. This is because we need to go through the entire group of barracks before we start giving them orders just to see if any of them has units around them.

    Let's start with the first loop. It looks basically the same as the loop in the previous modification. Pick each Unit in the barracks on the map. Check if the owner of the picked unit is 0. Here's the new part: Instead of giving the picked unit the order to train the marine, we just set the variable to a new value. We use the action "Set Variable" for this to set the "nrUnits" variable to nrUnits + Number of units around the picked barracks.

    So to set the nrUnits variable to the sum of nrUnits and the number of units around the picked unit, we set the value to Arithmetic (Integer) and set Value 1 to nrUnits and value 2 to the function "Number of Units in Unit Group". I then modified the Unit Group to the function "Units In Region Matching Condition". We've used this function before but we want to use it differently this time. Instead of changing the unit type to "Barracks", we keep it at "Any" because we just care if there's any unit at all. It doesn't specifically have to be a barracks. Instead we change the Region. We only want the units in a 5 radius circle around it so we change the Region to "Convert Circle to Region".

    This function takes a center point and a radius. The radius is simple. Just set it to 5. The Center is harder but still pretty simple. Change the Center from "Position from XY" to "Position Of Unit". Change the Unit to "Picked Unit". That's all for the first "Pick each Unit in Unit Group" loop.

    So let's look at the second "Pick each Unit in Unit Group" loop. It is almost the same, as the one we had in the previous modification but I changed the conditions a little. Below the "(Owner of (Picked unit)) != 0" condition I made a new condition but it's not a comparison. Instead it's an "Or". So for this "If Then Else" action to go to the "Then" part instead of the "Else" part, at least ONE of the conditions below the Or has to be true and on top of that, the "(Owner of (Picked unit)) != 0" condition must be true as well.

    So in the Or condition we have two different conditions. The first one is simply "nrUnits == 0". If this is true, it means we're in case 1 and that no barracks has units around it and if no barracks has units around it, we're allowed to spawn units at that barrack.

    If we're in case 1, everything is fine. We'll spawn units if that is the case. But if we're in case 2, "nrUnits == 0" will be false and we will only go to the "Then" part if the second condition in there is true. The second condition looks long and complicated but it's all things we're familiar with.

    It's a comparison and the Value 1 is the only complicated thing in there. It's a function(the same function we used in the the first "Pick each Unit in Unit Group" loop) called "Number of Units in Unit Group". I changed the Unit group parameter to "Units in Region Matching Condition". Leave Unit type parameter at any. We care about all kinds of units now, not only barracks. We need to make the region into the circle again so change the region into the "Convert Circle into Region" function. Change the Center to the "Position of Unit" function and change the Unit parameter of the "Position of Unit" function to "Picked Unit". Make sure the radius of the "Convert Circle into Region" function is 5. That's it, you're done with Value 1.

    Next is the operator. If we're in case 2 we want to create a unit if there are units around the picked barracks. This is true if the number of units around it are greater than 0. So change the operator to ">"(Greater than). Make sure the Value 2 is 0 and you're done.

    I hope you found this useful, if you're going the data editor route, try to do it in the trigger editor as well since it is good practice.
     
  13. Kyuft

    Kyuft Member

    Ratings:
    +11 / 0 / -0
    Okay, I think I fixed what I need, but I have a question.
    How do I make 3 players into 1 team color? Like in Desert Strike, you are all you own colors, but when the units spawn, they spawn purple or yellow.
    -Kyuft
     
  14. Dave312

    Dave312 Censored for your safe viewing

    Ratings:
    +269 / 0 / -0
    I haven't actually played Desert Strike, but typically in these cases there is a computer controlled player which owns the common units. You can give shared control to this computer player to allow other players to command the units if required.
     
  15. Kyuft

    Kyuft Member

    Ratings:
    +11 / 0 / -0
    In some games it is like that, yes, but I want to each player to have full control over their units but have certain units have the team color without an extra "player". Siretu said something about a custom trigger function to me when we talked on skype.
     
  16. Dave312

    Dave312 Censored for your safe viewing

    Ratings:
    +269 / 0 / -0
    The action Set Unit Color ought to do the trick.
     
  17. Siretu

    Siretu Starcraft 2 Editor Moderator Staff Member

    Ratings:
    +295 / 0 / -0
    Exactly. What I mentioned to him in skype was a custom function that returns the team of a player(takes a player and returns the team) since I remember searching for it without finding anything like it and therefore making my own. A function like that would be useful if he wants to use teams and wants to know what color to make the units.
     
  18. Kyuft

    Kyuft Member

    Ratings:
    +11 / 0 / -0
    I don't understand how to make custom functions. GFreaks tutorial was very vague. If we could talk on skype again that'd be great.
    EDIT: Siretu and I figured it out!
    -Kyuft
     

Share This Page