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

How to make a good TD from scratch

Level 7
Joined
Jun 23, 2009
Messages
297

Basic Tower Defense Tutorial

By Craphter, for The Hive Workshop






Welcome to my Tower Defense tutorial. Here, you will learn how to make a basic TD map from scratch, but, be warned, I start off talking as you already have some basic knowledge. I'll assume it is NOT your first map, since it's not a great idea to start off making a TD.






First off, open up your World Editor, start a new map, I chose these settings, you may choose whichever suit you most:


attachment.php



attachment.php



attachment.php



Whichever terrain you make, it's important that the path where the creeps will move, is an unbuildable terrain. Also, it is quite important that, for now, you make a design that has the features my designs have, because I will be explaining around these features. I'm talking about a single line, and defined start and finish regions.




attachment.php



Once you've layed out a basic terrain (all we'll need for now), well start with the "under the hood" part. First, delete the category that comes by default in the triggers. First, we'll need to set a few variables. Nine to be precise, one optional:


108548d1322497675-how-make-good-td-scratch-05.png


I'll go explaining why we need these variables as we use them, for now, you just need to have all of these, and their exact type. (There is one array, its size is the maximum number of players).

Now, we'll need some regions. This depends on how large your map is, how many turns there are, and how many players will there be. I chose 4 players to keep it simple. You'll need: one region per player in which they'll spawn, one region per turn in the creep's spawn, one region where the creeps are spawned, and one region where the creeps will head to, and die.


attachment.php


Every player needs a builder which will build the tower, right? So, let's create a unit, then we'll detect which players are online, and give them a builder. Open the Object Editor, and copy&paste a human peasant. Start by deleting harvest and call to arms from its abilities, but don't delete repair; it's also a good idea to add "invulnerable (neutral)" to its normal abilities. If you like, you may change the scaling value to a lower or higher number. Then, under "Combat - Attacks enabled", change it to "None". Change "Movement - Movement Speed" to somewhat around 500, and "food cost" to 0. Now, the important part, under "Tech Tree - Structures BUilt", delete ALL the upgrades. Now, change "text - name" to something like "builder", or whichever name you like. That would be all with the Object Editor for now.
Open up the Trigger Editor. I'll be using 3 main categories: general, movement, and waves; but since categories don't really matter, you may use whichever you like. And copy this trigger:


  • Start
    • Events
      • Time - Elapsed game time is 0.20 seconds
    • Conditions
    • Actions
      • Visibility - Disable fog of war
      • Visibility - Disable black mask
      • Leaderboard - Create a leaderboard for (All players) titled Example TD
      • Set Leaderboard = (Last created leaderboard)
      • Set TempRegion[1] = RedSpawn <gen>
      • Set TempRegion[2] = BlueSpawn <gen>
      • Set TempRegion[3] = TealSpawn <gen>
      • Set TempRegion[4] = PurpleSpawn <gen>
      • Leaderboard - Add Player 12 (Brown) to Leaderboard with label Creeps alive and value AliveCreeps
      • Leaderboard - Add Player 5 (Yellow) to Leaderboard with label Lifes left and value LivesLeft
      • For each (Integer A) from 1 to 4, do (Actions)
        • Loop - Actions
          • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
            • If - Conditions
              • ((Player((Integer A))) slot status) Equal to Is playing
            • Then - Actions
              • Set TempPoint = (Center of TempRegion[(Integer A)])
              • Unit - Create 1 Builder for (Player((Integer A))) at TempPoint facing Default building facing degrees
              • Selection - Select (Last created unit) for (Player((Integer A)))
              • Custom script: call RemoveLocation( udg_TempPoint)
              • Leaderboard - Add (Player((Integer A))) to Leaderboard with label (Name of (Player((Integer A)))) and value PlayerKills[(Integer A)]
              • Player - Set (Player((Integer A))) Current gold to 50
            • Else - Actions
      • Wait 5.00 seconds
      • Game - Display to (All players) the text: First wave in |c00F...
      • Custom script: call DestroyTrigger(GetTriggeringTrigger())



"Wait whaat? What's all thatf?"


Well, the complicated stuff is called "preventing memory leaks". What are memory leaks, well, in a nutshell, they're little bits of RAM which Warcraft uses to store a lot of different things, like locations, unit groups, unit types, and a LOT more things which I won't cover because it's a tutorial about mapmaking, but, if you wish to know more about memory leaks (Which I highly encourage) read this excellent post. For now, I'll teach you how to prevent them, and that means, storing the location in which the player's builder will be created, in a variable, so after we've used them, we can destroy them, otherwise, the map will be quite laggy. So, what does this trigger do? I'll break it step by step.

The event is quite simple, after 0.20 seconds, this trigger starts running. The first two actions are so that the whole map is visible to everyone (there's no point in hiding anything in a TD), then, we create a leaderboard and store it in a variable, which I'll talk more about later, then, we store 4 regions, 1 for each player (change it acording to the number of players in your map), so that we can use the loop, otherwise it wouldn't work, and, finally, we arrive to the loop. The loop is a for function, present in a LOT of programming languages, and Jass (or GUI) is no exception. What it does, basically, is to run everything in the loop as many times as the user says so, in this case, it says "from 1 to 4", so it will run 4 times. Each time it runs, the variable A increases in 1 number, starting from 1, up to 4. So, all we're doing, is repeating those actions 4 times, for each player. Simple enough, instead of making those actions 4 times, we just put them 1 time, and make the loop execute them 4 times. Then, we wait 5 seconds, just so that the players is overwhelmed right at the beginning, and we warn them that in 10 seconds the first wave will appear.

The last action simply destroys this trigger. Why? Well, because we won't need it anymore. Quoting Ralle: "it is said that destroying triggers after you no longer need them can be quite effective performance-wise, especially with long initialization triggers that run once and are then not used again." (just to clarify, this trigger's leaks are quite small indeed, but, I use the opportunity to introduce new mapmakers to memory leaks. Yes, it's not the best introduction, but now they have a basic concept).
Now, all players have a builder, we need the enemies to kill.


Create a new trigger, with only these actions:

  • Wave Spawner
    • Events
    • Conditions
    • Actions
      • Set TempPoint = (Center of Creep Spawn <gen>)
      • Unit - Create CreepsBorn UnitType for Player 12 (Brown) at TempPoint facing Default building facing degrees
      • Custom script: call RemoveLocation(udg_TempPoint)


"But Craphter, it has no events, no conditions and only three miserable action, do we REALLY need a separate trigger for this one action?"


No, not really. We seriously don't need a whole trigger for these three actions. But, this is because we only have 1 creep spawn. What if we had 8 creep spawns? The famous "Green Circle TD" has 8 spawns, thus, each time the map spawned a creep, it'd need those three actions times 8, in each wave trigger. For this map, it's almost useless, but, it's a good thing to start making things the right way, right from the start. Maybe the next TD you make does have several spawn points, and it's better that you were taught this way.
If you still don't understand the trigger, do not worry, when we're finished, you will.

Ok, we have a wave spawner, now we need a wave to spawn:

  • Wave 1
    • Events
      • Time - Elapsed game time is 15.00 seconds
    • Conditions
    • Actions
      • Set CreepsBorn = 15
      • Set UnitType = Footman
      • Trigger - Run Wave Spawner <gen> (ignoring conditions)
      • Custom script: call DestroyTrigger(GetTriggeringTrigger())

So, after 15 seconds, we set those two variables, and call wave spawner to spawn the creeps. Of course you'll need to make a trigger for each level you want your TD to have, copy&paste them, and go changing the variables values.
Ok, so we have the creeps, spawned, now, we need them to move their skeletons:

  • EnterSpawn
    • Events
      • Unit - A unit enters Creep Spawn <gen>
    • Conditions
    • Actions
      • Set AliveCreeps = (AliveCreeps + 1)
      • Set TempGroup = (Units in Creep Spawn <gen> owned by Player 12 (Brown))
      • Set TempPoint = (Center of Turn1 <gen>)
      • Unit Group - Pick every unit in TempGroup and do (Actions)
        • Loop - Actions
          • Unit - Order (Picked unit) to Move To TempPoint
      • Custom script: call DestroyGroup(udg_TempGroup)
      • Custom script: call RemoveLocation( udg_TempPoint)
Yeah, we'll count the number of creeps alive, just so that the player knows, in this type of TD it's unnecessary, but in TDs where the players loose once the Nº of creep > X, it's necessary. You can put that variable count, or not.
So, we set the variable TempGroup, because unit groups leak, and the same with TempPoint, then, we order all creeps owned by player 12 to move to the first turn, and we clear the variables.
That is a basic movement trigger, and you'll need one for EVERY turn the creeps need to take.
For turn 1:

  • Turn1
    • Events
      • Unit - A unit enters Turn1 <gen>
      • Time - Every 60.00 seconds of game time
    • Conditions
      • (Owner of (Triggering unit)) Equal to Player 12 (Brown)
    • Actions
      • Set TempPoint = (Random point in Turn2 <gen>)
      • Unit - Order (Triggering unit) to Move To TempPoint
      • Custom script: call RemoveLocation(udg_TempPoint)
It's quite important to check that the entering unit belongs to player 12, otherwise, a builder might enter accidentally that region, and the owner will be like "WTF? My builder is hunted", or, if he knows about map making, he'll realize what happened, and think the maker was too lazy to check the owner of the entering unit, and will wonder, "who taught that dude to make a TD?", so, to avoid all that, we'll just add that condition. We order the entering unit to move to the next turn, and erase the variable TempPoint.

Now, just copy the trigger Turn 1 and paste it as many times as you have a turn in your map, then, change each region's name, and, voilà, our movement system is completed. You might be wondering why I chose "random point in region" instead of "center of region". It's just a little detail so that all creeps won't try to go to the same point in a region, thus, looking kinda crappy, more artificial/robotic, and they'll probably bump into each other much more.

Now, once you've finished all the turns, make a trigger to lead the creep to it's final destination, the end region, and when they enter it, kill it.

  • End
    • Events
      • Unit - A unit enters End <gen>
    • Conditions
      • (Owner of (Entering unit)) Equal to Player 12 (Brown)
    • Actions
      • Unit - Kill (Entering unit)
      • Set AliveCreeps = (AliveCreeps - 1)
      • Set LifesLeft = (LifesLeft - 1)
      • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
        • If - Conditions
          • LifesLeft Equal to 0
        • Then - Actions
          • Game - Defeat Player 1 (Red) with the message: Defeat!
          • Game - Defeat Player 2 (Blue) with the message: Defeat!
          • Game - Defeat Player 3 (Teal) with the message: Defeat!
          • Game - Defeat Player 4 (Purple) with the message: Defeat!
        • Else - Actions
Each time a creep enters the final region, a life is lost; once all lives are lost, the game is too.

Now, we need a leaderboard, so, back to the leaderboard I talked about before. First, we store it in a variable, just to do things the right way. In this map it's not necessary because there's only 1 leaderboard, but, the next time you make a map, you might use 2 or more leaderboards, and you'll have to use variables to let the map know which leaderboard you're talking about.

Now, a kill trigger:

  • Kill
    • Events
      • Unit - A unit owned by Player 12 (Brown) Dies
    • Conditions
    • Actions
      • Set AliveCreeps = (AliveCreeps - 1)
      • Leaderboard - Change the value for Player 12 (Brown) in Leaderboard to AliveCreeps
      • For each (Integer A) from 1 to 4, do (Actions)
        • Loop - Actions
          • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
            • If - Conditions
              • (Owner of (Killing unit)) Equal to (Player((Integer A)))
            • Then - Actions
              • Set PlayerKills[(Integer A)] = (PlayerKills[(Integer A)] + 1)
              • Leaderboard - Change the value for (Player((Integer A))) in Leaderboard to PlayerKills[(Integer A)]
            • Else - Actions


What are we doing here?

Simple, we just detect who's the owner of the unit (tower) who killed the unit (creep), and add 1 to the PlayerKills variable. We also subtract 1 from creeps alive, and, of course, update the leaderboard.




Extra features:




1- How to sell a tower?



You'd need to create a trigger, and a new unit.
This unit should be called "Sell", which costs 0 gold, and change the icon game interface to "Items - Gold Coins" or whatever you like. Make all tower train this unit under "Techtree - Units Trained".
Then this trigger:

  • Sell
    • Events
      • Unit - A unit Begins training a unit
    • Conditions
      • (Unit-type of (Trained unit)) Equal to Sell
    • Actions
      • Unit - Remove (Trained unit) from the game
      • Player - Add (Point-value of (Triggering unit)) to (Owner of (Triggering unit)) Current gold
      • Wait 1.50 seconds
      • Unit - Remove (Triggering unit) from the game
It is important for you to know that, when a player sells the tower, he'll receive the "point value" of the tower, that's a value you can change under "Stats - Point Value". It's up to you whether or not they'll be able to sell the tower, whether or not they'll receive a 100% refund, and whether or not that refund includes previous upgrades. If the latter is true, you'll need to customize the point value of each tower to (point value of current tower) + (sum of all point values of previous towers).




2- What if a player leaves?


We just add this simple trigger:

  • Leaver
    • Events
      • Player - Player 1 (Red) leaves the game
      • Player - Player 2 (Blue) leaves the game
      • Player - Player 3 (Teal) leaves the game
      • Player - Player 4 (Purple) leaves the game
    • Conditions
    • Actions
      • Game - Display to (All players) the text: ((Name of (Triggering player)) + has left the game.)
      • Leaderboard - Change the label for (Triggering player) in Leaderboard to <Left the game>
      • Set TempGroup = (Units in (Playable map area) owned by (Triggering player))
      • Unit Group - Pick every unit in TempGroup and do (Actions)
        • Loop - Actions
          • Wait 1.00 seconds
          • Unit - Remove (Picked unit) from the game
      • Custom script: call DestroyGroup(udg_TempGroup)
Aand that's about it with triggers.
We just need to edit the player's forces so that all players are allies, and the units... Yeah... Just skip that part Craphter. Lazy ass.

I won't show you for two reasons.
1- You should know how to edit units, if you don't, I already taught you with the builder
2- It's up to you, the mapmaker, to input some creativity and personal mark


Do know that balancing the map is one of the hardest parts of mapmaking (if not the hardest), reaching a point in which it's fun to play, but not too easy.




Tips when making the towers:


- REMEMBER to erase all requirements which come by default; really important, or all towers will be unbuildable.
- Remember to set the build time quite low, I'd say maximum of 10 seconds.[/COLOR]
- Remember to make all tower upgradable to a better tower, more options means there are a variety of ways to play the map, which leads to more fun.
- It's a good idea to make towers invulerable (neutral), EVEN THOUGH your creeps should have no attacks enabled, it's just a bit neater.
- Don't tick "structures" under "Combat - Attack 1/2", in your towers, otherwise, they might attack each other.
- It's a REALLY good idea to make towers compliment each other, say, some towers make a lot of damage to certain creeps, but not so much to others, so players make up strategies, and make them think. Take, for example, Warcraft's attack and defense types, there are several types of armours and several types of attacks, all which compliment each other, it's not a good idea to have a whole army of piercing attack, just like it's a bad idea to have a whole army of Fortified.
- DO WORK a LOT more on the terrain, add doodas, cliffs, water, etc.
- Add a storyline, it adds higher quiality to the map ( for more mapmaking tips, read the General Mapping Section
- Remember to erase all ablities which come by default (for example, in guard tower, blight dispell magic, and magic sentry), same as default descriptions, and... well... mostly anything that comes by default.
- It's a good idea to disable "unit can flee", and turn down to 0 the collision size of the creeps; especially if they're getting stuck (this way they won't collide)
- Last, but not least, play your map a LOT, and I mean A LOT, once it's playable, you should keep playing it and testing it, alone, or with bots, or even more helpful, with friends, the more you play it, the more you'll be a ble to improve the gameplay and map experience. Why? Well simply cause when you play it, you discover glitches, bugs and things that need repair. Also, you come up with ideas much much easier, than when simply developing it.






That is all, I really hope you found this useful, and that you just finished your first tower defense map, or, one of your firsts. Do know that I just gave you the basic tools and knowledge you need for a TD... something like a hammer and a nail, now, it is entirely up to you to make the map actually fun, ask yourself, what makes MY TD different from all the other thousands out there? If you can't come up with at least one convincing argument, you need to keep adding features to your map.

Below, I attached my finished TD which I made while I was writing the tutorial. You are free to download it as a template, or to check out why something in yours doesn't work, etc. etc. You may use it however you want.

If you find anything wrong with the tutorial, or my explanations, or the map, or simply have a suggestion, a better way to do stuff, please do let me know, I'm open for any kind of feedback. Also, if you feel you'd like me to add any kind of feature to the tutorial, including how to do X thing, just tell me, I'll gladly work on it.



Thanks to PurgeandFire111, for the great help and tips he gave me.


And finally, thank you for taking the time to read my whole tutorial.






Craphter
 

Attachments

  • 01.png
    01.png
    116.4 KB · Views: 4,068
  • 02.png
    02.png
    1.1 MB · Views: 4,366
  • 03.png
    03.png
    974.2 KB · Views: 4,959
  • 04.png
    04.png
    1.1 MB · Views: 4,073
  • 06.png
    06.png
    1,022.9 KB · Views: 4,167
  • 05.png
    05.png
    20.1 KB · Views: 3,771
  • Example TD.w3x
    32.4 KB · Views: 591
Last edited:
Yeah, the signature detachment is just part of the rules. It is in place most likely so that there won't be weird images/unnecessary text.

For the "Start" and "Kill" trigger, you can use a loop to optimize the actions. Also, there are some actions after this part:
"Wait whaat? What's all that Craphter?"

That can be placed in [TRIGGER][/TRIGGER] tags.
 
Level 7
Joined
Jun 23, 2009
Messages
297
Yeah, the signature detachment is just part of the rules. It is in place most likely so that there won't be weird images/unnecessary text.

For the "Start" and "Kill" trigger, you can use a loop to optimize the actions. Also, there are some actions after this part:


That can be placed in [TRIGGER][/TRIGGER] tags.

True that, added the trigger tags.
I will, however, ask you for some help on the loop with start and kill, since I'm not entirely familiarized with loop actions.
 
For example, the Start trigger can be reduced to this:
  • Start
    • Events
      • Time - Elapsed game time is 0.20 seconds
    • Conditions
    • Actions
      • Visibility - Disable fog of war
      • Visibility - Disable black mask
      • Leaderboard - Create a leaderboard for (All players) titled Example TD
      • Set Leaderboard = (Last created leaderboard)
      • Leaderboard - Add Player 12 (Brown) to Leaderboard with label Creeps alive and value AliveCreeps
      • Leaderboard - Add Player 5 (Yellow) to Leaderboard with label Lifes left and value LifesLeft
      • For each (Integer A) from 1 to 4, do (Actions)
        • Loop - Actions
          • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
            • If - Conditions
              • ((Player((Integer A))) slot status) Equal to Is playing
            • Then - Actions
              • Set TempPoint = (Center of RedSpawn <gen>)
              • Unit - Create 1 Builder for (Player((Integer A))) at TempPoint facing Default building facing degrees
              • Selection - Select (Last created unit) for (Player((Integer A)))
              • Custom script: call RemoveLocation( udg_TempPoint )
              • Leaderboard - Add (Player((Integer A))) to Leaderboard with label (Name of (Player((Integer A)))) and value PlayerKills[(Integer A)]
              • Player - Set (Player((Integer A))) Current gold to 50
            • Else - Actions
      • Wait 5.00 seconds
      • Game - Display to (All players) the text: First wave in |c00F...
      • Custom script: call DestroyTrigger(GetTriggeringTrigger())
 
  • Leaver
    • Events
      • Player - Player 1 (Red) leaves the game
      • Player - Player 2 (Blue) leaves the game
      • Player - Player 3 (Teal) leaves the game
      • Player - Player 4 (Purple) leaves the game
    • Conditions
    • Actions
      • Game - Display to (All players) the text: ((Name of (Triggering player)) + has left the game.)
      • Leaderboard - Change the label for (Triggering player) in Leaderboard to <Left the game>
      • Set TempGroup = (Units in (Playable map area) owned by (Triggering player))
      • Wait 1.00 seconds
      • Unit Group - Pick every unit in TempGroup and do (Actions)
        • Loop - Actions
          • Unit - Remove (Picked unit) from the game
      • Custom script: call DestroyGroup(udg_TempGroup)
->

  • Init
    • Events
      • Map Initialization
    • Conditions
    • Actions
      • For each TempInt from 1 to 4, do (Actions)
        • Loop - Actions
          • Custom script: call TriggerRegisterPlayerEvent(gg_trg_Leaver, Player(udg_TempInt - 1), EVENT_PLAYER_LEAVE)
  • Leaver
    • Events
    • Conditions
    • Actions
      • Set TempPlayer = (Triggering player)
      • Game - Display to (All players) the text: ((Name of TempPlayer) + has left the game.)
      • Leaderboard - Change the label for TempPlayer in Leaderboard to <Left the game>
      • Wait 1.00 seconds
      • Custom script: set bj_wantDestroyGroup = true
      • Unit Group - Pick every unit in (Units in (Playable map area) owned by TempPlayer) and do (Actions)
        • Loop - Actions
          • Unit - Remove (Picked unit) from the game
Also, instead of using (Integer A), you should be using some integer variable (Trust me on this- If anything inside
an Integer A loop is called and that trigger/function contains anything that uses an Integer A loop, you're dead.

That's why using an integer per trigger for loops is good (But if you're nesting them, more than one variable is required.)
 
For the trigger Turn1, you have this event:
  • Time - Every 60.00 seconds of game time
But I don't think you need that. (when the event is evaluated, the "triggering unit" is non-existent [so it returns null], so the condition returns false and the actions are unable to be executed)

Also, in your trigger "End", the first action says "ger". lol.

In your trigger "Start", you have this line:
  • Center of TempRegion[1])
Which should be:
  • Center of TempRegion[(Integer A)]
Don't worry, we're almost done. ;)

@Magtheridon: You can use Integer A when there is no chance of collision. If there is a chance of collision, then use Integer B. You only need to supply a separate integer for the loop if you have a loop that is calling/within a loop that is calling/within another loop. (or non-instantaneous loops, but that doesn't make sense anyway)

While it can be a good practice, the fact that it uses up more globals and is more difficult for the user to input makes it unnecessary unless needed. =) In the examples provided, Integer A should work just fine.
 
set bj_wantDestroyGroup = true is a JASS custom script that allows you to automatically destroy a group after you are done performing the actions for it. (after the loop - actions finish) You just put it before your "Pick every... action", and it means you don't have to assign the group to a variable. (the grouping function will check if bj_wantDestroyGroup is true for the group, and if so, it will destroy it after executing the actions)

Whether you use a global or the bj_wantDestroyGroup doesn't matter too much. The latter means that you won't have to use a global, which can be nice. It is up to you which you want to use.

Speaking of the trigger, "Leaver", the grouping should occur after the wait to make sure it is multi-player instanceable. (or you can use Magtheridon's trigger) Basically, if a player leaves, and another player leaves within 1 second of the previous player, it will remove only the second players units since the global would be overwritten. You can fix it by putting all grouping actions after the wait, since GetTriggerPlayer() is local to the function so it will return the correct player. (if i recall correctly)

After that, it is ready for approval! :)
 
Level 7
Joined
Jun 23, 2009
Messages
297
set bj_wantDestroyGroup = true is a JASS custom script that allows you to automatically destroy a group after you are done performing the actions for it. (after the loop - actions finish) You just put it before your "Pick every... action", and it means you don't have to assign the group to a variable. (the grouping function will check if bj_wantDestroyGroup is true for the group, and if so, it will destroy it after executing the actions)

Whether you use a global or the bj_wantDestroyGroup doesn't matter too much. The latter means that you won't have to use a global, which can be nice. It is up to you which you want to use.

Speaking of the trigger, "Leaver", the grouping should occur after the wait to make sure it is multi-player instanceable. (or you can use Magtheridon's trigger) Basically, if a player leaves, and another player leaves within 1 second of the previous player, it will remove only the second players units since the global would be overwritten. You can fix it by putting all grouping actions after the wait, since GetTriggerPlayer() is local to the function so it will return the correct player. (if i recall correctly)

After that, it is ready for approval! :)


Oh, I see.
I'd preffer to leave the "destroygroup" as it is, since I think it's a good idea to get new triggerers used to store everything that leaks in variables.
Regarding the leaver trigger, thank you very much for that tip, just a slight detail that would've ruined the whole system.
 
Level 2
Joined
Oct 19, 2010
Messages
9
every single part of the trigger from "For each (Interger A) from 1 to 4, do (actions)" to the end of the trigger.
 
Level 1
Joined
Oct 29, 2012
Messages
6
I'm having problems with the creeps, they won't move from the spawn, only 1 creep in wave 2 and 4 will move, is there a way to fix it? i can't see the problem
 
Level 1
Joined
Oct 29, 2012
Messages
6
  • Upper Spawn
    • Events
      • Unit - A unit enters Spawn 2 <gen>
      • Time - Elapsed game time is 0.20 seconds
    • Conditions
    • Actions
      • Set AliveCreeps = (AliveCreeps + 1)
      • Set TempGroup = (Units in Spawn 2 <gen> owned by Player 12 (Brown))
      • Set TempPoint = (Center of Upper turn 1 <gen>)
      • Unit Group - Pick every unit in TempGroup and do (Actions)
        • Loop - Actions
          • Unit - Order (Picked unit) to Move To TempPoint
          • Custom script: call DestroyGroup(udg_TempGroup)
          • Custom script: call RemoveLocation( udg_TempPoint)
I am not really sure wich one you want
 
Last edited:
Level 7
Joined
Jun 23, 2009
Messages
297
  • Upper Spawn
    • Events
      • Unit - A unit enters Spawn 2 <gen>
      • Time - Elapsed game time is 0.20 seconds
    • Conditions
    • Actions
      • Set AliveCreeps = (AliveCreeps + 1)
      • Set TempGroup = (Units in Spawn 2 <gen> owned by Player 12 (Brown))
      • Set TempPoint = (Center of Upper turn 1 <gen>)
      • Unit Group - Pick every unit in TempGroup and do (Actions)
        • Loop - Actions
          • Unit - Order (Picked unit) to Move To TempPoint
          • Custom script: call DestroyGroup(udg_TempGroup)
          • Custom script: call RemoveLocation( udg_TempPoint)
I am not really sure wich one you want

Yeah that trigger, I think you have to remove the custom scripts from the loop, they're both inside the Loop Actions, they're supposed to go outside the loop.
 
Level 1
Joined
Oct 29, 2012
Messages
6
  • EndZone
    • Events
      • Unit - A unit enters End Zone <gen>
    • Conditions
      • (Owner of (Entering unit)) Equal to Player 12 (Brown)
    • Actions
      • Unit - Kill (Entering unit)
      • Set AliveCreeps = (AliveCreeps - 1)
      • Set LivesLeft = (LivesLeft - 1)
      • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
        • If - Conditions
          • LivesLeft Equal to 0
        • Then - Actions
          • Game - Defeat Player 1 (Red) with the message: You failed to slaug...
          • Game - Defeat Player 2 (Blue) with the message: You failed to slaug...
          • Game - Defeat Player 3 (Teal) with the message: You failed to slaug...
        • Else - Actions
  • Kill
    • Events
      • Unit - A unit owned by Player 12 (Brown) Dies
    • Conditions
    • Actions
      • Set AliveCreeps = (AliveCreeps - 1)
      • Leaderboard - Change the value for Player 12 (Brown) in Leaderboard to AliveCreeps
      • For each (Integer A) from 1 to 3, do (Actions)
        • Loop - Actions
          • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
            • If - Conditions
              • (Owner of (Killing unit)) Equal to (Player((Integer A)))
            • Then - Actions
              • Set PlayerKills[(Integer A)] = PlayerKills[((Integer A) + 1)]
              • Leaderboard - Change the value for (Player((Integer A))) in Leaderboard to PlayerKills[(Integer A)]
            • Else - Actions
This will not change in the leaderboard and i can't find the problem, i've been trying to solve this for 2 days now, If anyone can spot it please light it up to me :)
 
Level 29
Joined
Oct 24, 2012
Messages
6,543
  • EndZone
    • Events
      • Unit - A unit enters End Zone <gen>
    • Conditions
      • (Owner of (Entering unit)) Equal to Player 12 (Brown)
    • Actions
      • Unit - Kill (Entering unit)
      • Set AliveCreeps = (AliveCreeps - 1)
      • Set LivesLeft = (LivesLeft - 1)
      • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
        • If - Conditions
          • LivesLeft Equal to 0
        • Then - Actions
          • Game - Defeat Player 1 (Red) with the message: You failed to slaug...
          • Game - Defeat Player 2 (Blue) with the message: You failed to slaug...
          • Game - Defeat Player 3 (Teal) with the message: You failed to slaug...
        • Else - Actions
  • Kill
    • Events
      • Unit - A unit owned by Player 12 (Brown) Dies
    • Conditions
    • Actions
      • Set AliveCreeps = (AliveCreeps - 1)
      • Leaderboard - Change the value for Player 12 (Brown) in Leaderboard to AliveCreeps
      • For each (Integer A) from 1 to 3, do (Actions)
        • Loop - Actions
          • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
            • If - Conditions
              • (Owner of (Killing unit)) Equal to (Player((Integer A)))
            • Then - Actions
              • Set PlayerKills[(Integer A)] = PlayerKills[((Integer A) + 1)]
              • Leaderboard - Change the value for (Player((Integer A))) in Leaderboard to PlayerKills[(Integer A)]
            • Else - Actions
This will not change in the leaderboard and i can't find the problem, i've been trying to solve this for 2 days now, If anyone can spot it please light it up to me :)

u should create ur own thread in the triggers and scripts forum.
dont use integer A/B instead make ur own integer and use that.
also dont do it this way it is very inefficient.
Instead store player number of triggering player into an integer variable and use that as ur array index value( the integer inside this [])
and ur problem is right here
  • Set PlayerKills[(Integer A)] = PlayerKills[((Integer A) + 1)]
. u need to add the kills not change the index number. should be like this
  • Set PlayerKills[(Integer A)] = (PlayerKills[(Integer A)] + 1)
 
Top