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

[Mapping] Making an efficient TD

Level 14
Joined
Jan 5, 2009
Messages
1,127

Making an Efficient TD

By Crazed_seal

Whats a TD

A TD or Tower Defense is map were the players have to build towers to stop creeps(runners, enemies ect...) Thus the name Tower Defense, this type of game can be either really easy or hard to make. Although all TD's basically do the same thing some have gone out of the box. Such as Wintermaul Wars, you not only have to defend, you have to attack. But in this tutorial we're doing a basic one.

Initiazation

Ok first, we have to set the points that the creeps will run to and where they will spawn. If we don't set the points to a variable it will create leaks, leaks create lag and eventually if there is enough lag it can crash the game.
Variables Needed.
These are the Variables needed in setting the points.
One has to be:
Name Type Array? Array Ammount

Spawn_Areas
Point Yes As many spawn areas you have

Movement_Areas
Point YesThe amount of places a creep will move to

Last_Point
Point No0

Life_Pool
Point No0

Lives
Integer No0
  • Init
  • Events
    • Map initialization
  • Conditions
  • Actions
    • Set Spawn_Areas[1] = (Center of( Spawn1 <gen> ))
    • Set Spawn_Areas[2] = (Center of( Spawn2 <gen> ))
    • Set Spawn_Areas[3] = (Center of( Spawn3 <gen> ))
    • -------- I have 3 Spawn areas --------
    • Set Movement_Areas[1] = (Center of( Move1 <gen> ))
    • Set Movement_Areas[2] = (Center of( Move2 <gen> ))
    • Set Movement_Areas[3] = (Center of( Move3 <gen> ))
    • Set Movement_Areas[4] = (Center of( Move4 <gen> ))
    • Set Movement_Areas[5] = (Center of( Move5 <gen> ))
    • Set Movement_Areas[6] = (Center of( Move6 <gen> ))
    • Set Lives = (How many lives you want there to be)
    • Set Last_Point = (Center of( Last <gen> )) - This is not end, this is the area before the life pool, boat, ect...
    • Set Life_Pool = (Center of( Life Pool <gen> ))
    • -------- You would place Move1, Move2, and Move3 outside the Spawn Areas --------
The Trigger above sets all the variables you need for spawn, life and other triggers.
Create an integer Variable called Spawn
Now onto the Spawn Triggers:
  • Spawn
  • Time - Game time elapsed is 20.00 seconds
  • Conditions
  • Actions
  • For each (Integer Spawn) from 1 to 20, do (Actions)
    • loop
      • Unit - Create 1 Level1Creep for Player 12 (Brown) at Spawn_Areas[1] facing Default building facing degrees
      • Unit - Order (Last created unit) to Move To Movement_Areas[1]
      • Unit - Create 1 Level1Creep for Player 12 (Brown) at Spawn_Areas[2] facing Default building facing degrees
      • Unit - Order (Last created unit) to Move To Movement_Areas[2]
      • Unit - Create 1 Level1Creep for Player 12 (Brown) at Spawn_Areas[3] facing Default building facing degrees
      • Unit - Order (Last created unit) to Move To Movement_Areas[3]
      • Wait - 1.00
      • -------- This makes the creeps or runners spawn one by one every 1.00 second --------
  • Wait until ((Player 12 (Brown) Food used) Equal to 0), checking every 1.00 seconds
  • Game - Display to (All players) the text: Level 1 Complete
  • Wait 20.00 seconds
  • For each (Integer Spawn) from 1 to 20, do (Actions)
    • loop
      • Unit - Create 1 Level2Creep for Player 12 (Brown) at Spawn_Areas[1] facing Default building facing degrees
      • Unit - Order (Last created unit) to Move To Movement_Areas[1]
      • Unit - Create 1 Level2Creep for Player 12 (Brown) at Spawn_Areas[2] facing Default building facing degrees
      • Unit - Order (Last created unit) to Move To Movement_Areas[2]
      • Unit - Create 1 Level2Creep for Player 12 (Brown) at Spawn_Areas[3] facing Default building facing degrees
      • Unit - Order (Last created unit) to Move To Movement_Areas[3]
      • Wait - 1.00
  • Wait until ((Player 12 (Brown) Food used) Equal to 0), checking every 1.00 seconds
  • Game - Display to (All players) the text: Level 1 Complete
  • Wait 20.00 seconds
  • -------- Just keep doing this for every level updating the runners though --------
The Trigger Above, spawns 1 unit per ever second, untill 20 units have beens spawned per action inside(Not the order actions, also can you see we are using point variables instead of center of regions, this is to stop leaks, leaks are data that has been created and used but not destroyed)

Movement

You got to make 7 Triggers.
These seven triggers, when the unit enters a region it is ordered to move to the next point.
  • Movement Column 1 1
  • Events
    • Unit - Enters region Move1 <gen>
  • Conditions
    • (Owner of( Triggering Unit)) Equal to (Player{12}Brown)
  • Actions
    • Unit - Order ( Triggering Unit ) to Move To Movement_Areas[4]
  • Movement Column 2 1
  • Events
    • Unit - Enters region Move2 <gen>
  • Conditions
    • (Owner of( Triggering Unit)) Equal to (Player{12}Brown)
  • Actions
    • Unit - Order ( Triggering Unit ) to Move To Movement_Areas[5]
  • Movement Column 3 1
  • Events
    • Unit - Enters region Move3 <gen>
  • Conditions
    • (Owner of( Triggering Unit)) Equal to (Player{12}Brown)
  • Actions
    • Unit - Order ( Triggering Unit ) to Move To Movement_Areas[6]
  • Movement Column 1 2
  • Events
    • Unit - Enters region Move4 <gen>
  • Conditions
    • (Owner of( Triggering Unit)) Equal to (Player{12}Brown)
  • Actions
    • Unit - Order ( Triggering Unit ) to Move To Last_Point
  • Movement Column 2 2
  • Events
    • Unit - Enters region Move5 <gen>
  • Conditions
    • (Owner of( Triggering Unit)) Equal to (Player{12}Brown)
  • Actions
    • Unit - Order ( Triggering Unit ) to Move To Last_Point
  • Movement Column 3 2
  • Events
    • Unit - Enters region Move6 <gen>
  • Conditions
    • (Owner of( Triggering Unit)) Equal to (Player{12}Brown)
  • Actions
    • Unit - Order ( Triggering Unit ) to Move To Last_Point
  • Last Move
  • Events
    • Unit - Enters region Last <gen>
  • Conditions
    • (Owner of( Triggering Unit)) Equal to (Player{12}Brown)
  • Actions
    • Unit - Order ( Triggering Unit ) to Move To Life_Pool
Now finally the lives:
  • Life Taken
  • Events
    • Unit - Enters region Life Pool <gen>
  • Conditions
    • (Owner of( Triggering Unit)) Equal to (Player{12}Brown)
  • Actions
    • Set Lives = ( Lives - 1 )
^ This trigger handles the lifes.
When a unit enters the region it takes -1 away from the life.
  • Lose
  • Events
    • Time - Every 0.25 seconds of game time
  • Condition
    • Lives Less than or equal to 0
  • Actions
    • Player Group - Pick every player in (All players) and do (Game - Defeat (Picked player) with the message: You Lose)
Ok. Hopefully you have enjoyed this tutorial and learned something.
~Crazed_seal2 Out~
 
Last edited:
Level 24
Joined
May 9, 2007
Messages
3,563
Formatting and therefore readability is poor. You don't explain the triggers, and what explanation you do give is poor.

Initiazation is spelled wrong, and should be Initialization.

I recommend that you spend more time explaining what the triggers are, and what you are doing in them. Look at the formatting on some approved tutorials to get an idea of what it should look like.
 
Generally, this covers spawning and movement where the title says "Making an Efficient TD". Spawning and movement isn't the only thing to a TD. Since there are enough spawning/movement tutorials, I think this should either be expanded more to show several of the aspects of a TD. (Even though there are still tutorials like that)

Please notify me if you will update it or just update it in general, else it will be graveyarded after a week.
 
Level 31
Joined
May 3, 2008
Messages
3,155
Well with using the waits allows the entire spawning process inside one trigger and the waits in the loops make the monsters spawn one by one instead of a huge bunch.

wait are inaccurate in timing and it could overwrite the execution process, which it was a rather bad idea.

this isn't such a good method in developing TD. :hohum:
 
Level 28
Joined
Jan 26, 2007
Messages
4,789
Better idea: add 1 extra trigger called "Timer" (or whatever, name doesn't really matter, as long as it fits it's purpose).
Make the timer loop every 0.05 seconds and increase a real variable by 0.05 every time it loops.
Once the real variable = CreepDelay[Level] (another real variable to indicate the time between each spawn - note: spawn, not wave), then activate the trigger with the actual spawns.

Lol, this is probably a huge mess to anyone who isn't on the same wavelength as me, but it really works :D (and better than with using waits + you can choose the delay for each level).

  • Timer
    • Events
      • Time - Every 0.05 seconds of game time
    • Conditions
    • Actions
      • Set Timer = (Timer + 0.05)
      • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
        • If - Conditions
          • Timer Greater than or equal to SpawnInterval[Level]
        • Then - Actions
          • Trigger - Run Spawn Creeps <gen> (checking conditions)
          • Set Timer = 0.00
        • Else - Actions
Okay, I hope this makes everything more clear than my stupid explanation.
I'm a horrible teacher, I know...


Major Edit:


Ohh, by the way: instead of 7 triggers for the movement, you might as well use this:

At map init:
  • Actions
    • Set Region[1] = SpawnRed <gen>
    • Set Region[2] = SpawnBlue <gen>
    • Set Region[3] = Red CP1 <gen>
    • Set Region[4] = Blue CP1 <gen>
    • Set Region[5] = Red CP2 <gen>
    • Set Region[6] = Blue CP2 <gen>
    • Set Region[7] = Red CP3 <gen>
    • Set Region[8] = Blue CP3 <gen>
    • Set Region[9] = Red CP4 <gen>
    • Set Region[10] = Blue CP4 <gen>
    • Set Region[11] = Red CP5 <gen>
    • Set Region[12] = Blue CP5 <gen>
    • Set Region[13] = Red CP6 <gen>
    • Set Region[14] = Blue CP6 <gen>
    • Set Region[15] = EndRed <gen>
    • Set Region[16] = EndBlue <gen>
This is just an example: the order of the regions is very important though.
It's something like this:
StartPoint (player 1)
Startpoint (player 2)
StartPoint (player x)
Checkpoint 1 (player 1)
Checkpoint 1 (player 2)
Checkpoint 1 (player x)
etc...

Then just use this trigger (with a few adjustments: 14 should be the total amount of regions without end regions, all 2's should be the amount of players):
  • Checkpoints
    • Events
      • Unit - A unit enters Red Checkpoint 1
      • Unit - A unit enters Red Checkpoint 2
      • ... etc (add all checkpoint regions here)
    • Conditions
    • Actions
      • -------- Set the "14" to the amount of regions there are (End regions not included) --------
      • For each (Integer LoopInt) from 1 to 14, do (Actions)
        • Loop - Actions
          • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
            • If - Conditions
              • (Custom value of (Entering unit)) Equal to LoopInt
            • Then - Actions
              • Set loc1 = (Center of Region[(2 + LoopInt)])
              • Unit - Order (Entering unit) to Move To loc1
              • Custom script: call RemoveLocation(udg_loc1)
              • Set TempInt = LoopInt
            • Else - Actions
      • Unit - Set the custom value of (Entering unit) to (2 + TempInt)
And all units will move to the correct region.
 
Level 17
Joined
Jun 17, 2007
Messages
1,433
  • You're correct in using static locations (points), but other than that, most triggers in the tutorial could be done more efficiently.
  • Your loops are not the way they should look. Instead of "Loop - Actions", you just have "loop".
  • I would not use an array here. Use an array when the index is needed, not to replace variables.
  • The "Wait until ((Player 12 (Brown) Food used) Equal to 0), checking every 1.00 seconds" is not ideal.
  • I think a better alternative to this system would be a single, short trigger that was executed when brown loses all of his units. Each execution would increase the "Wave_Count" integer variable by one. A unit type array and an integer array would be used to store data relating to that wave. When the trigger is executed, it would access the array with the same index of the "Wave_Count" variable.
 
Level 8
Joined
Jun 30, 2010
Messages
259
Misses in your tutorial:
-In the spawn you missed that it should be "wave 2 complete" instead of wave 1.
-Huge miss: You did NOT remove units that takes a life.

Tutorial name: Making an efficient TD should mean it covers nearly every aspect of a TD, but you missed:
-How to make towers/creeps and how to proper balance them between eachother and creep wave/tower level.
-You should also have an advanced part where you explain how to make "builder races" with different towers, and this should also include ability towers.
-You should also include how you make creeps use abilitys, which can be very easy or very hard, for example, play the "blizzard tower defence" map and look at their "blink" ability.
-You should include build zones, which makes no one else then you able to build in a certain region, or being able to use a command which removes all allied towers from your build zone.

This is about half of everything you did not include in your tutorial.
 
Top