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

Ralle's Tower Defence Guide

Ralle

Owner
Level 77
Joined
Oct 6, 2004
Messages
10,096
Ralle's Tower Defence Guide

Table of Contents

Intro


I will start off by explaining what a Tower Defense is. A Tower Defense (or TD) is a genre of WarCraft 3 Custom Scenarios (maps). All towers, upgrades, builders creeps are different. You usually start with some unit called a builder which you can build towers with. The towers you can build vary in quality, skills, speed etc.. and ofcourse, the price. After around 30 seconds to 1 minute monsters spawn in different locations and start moving. These monsters don't attack unless you block their way of moving. This means that you can make a maze for the monsters to stay for a longer time in your area:

image1.jpg
Example #1 (a maze)

image2.jpg
Example #2 (a lineup)
As you see in these two examples the units will have to move much longer to escape the towers in example #1. If you count the squares the units have to move to, until they are safe, it will be:
example #1: 13
example #2: 6
This means that the towers in example #1 can hit the creeps for a greater amount of time than the towers in example #2.

So if monsters pass your maze they will most likely walk into another players maze and probably after that walk into some kind of gate or boat. When they enter it, all players will lose a life which they have a limited amount of. So when the amount of lives pass 0, all players will lose the game.

When all creeps in a TD are dead, the next level will start, this level have either stronger or more creeps. After around 20-30 levels of creeps you will often win the game.

Normally every player in a TD each have their own spot and a creep resource. But sometimes people like to build in eachother's spots which cause lots of angry faces. This is also a thing we can prevent in the coming tutorial.



Terrain


The terrain is very important for a TD. It needs to be fair for all players though it not always is. Some player spots are often the "best" and in some spots people often leave because they are bored in that spot. But making all spots equal is a good thing. There is no formula of making the terrain so I will just show you 3 examples of how the terrain could look like:

Balanced Terrain

burbenog.jpg

wintermaul.jpg

warhammer.jpg


Example #1 (Burbenog TD)
Burbenog TD is quite hard, but it features some good things. All player spots are 100% fair to each other. Every player gets an equal amount of creeps and have equal starting points. This is the only TD of it's kind.


Example #2 (Wintermaul TD)
Wintermaul have very different spots. Some players only gets their creeps but they get a lot. Then some players get the leaks of other players + a little resource from their own spawn. And Player 9 (gray) only get leaks from other players.


Example #3 (Warhammer 40k TD)
Warhammer 40k TD have quite equal spots for all players except for Player 9 (gray) he gets everyone's leaks which can vary a lot. Sometimes everyone leaks and he gets it all (if he can handle it) and sometimes he gets nothing.
Terrain Creation
Now I am going to make a very simple terrain. I will make a spawn for units a place they go to and turn around and walk into a base which is where they have to go in order to make you lose a life.

1.jpg
Progress #1 (just terrain)

2.jpg
Progress #2 (now I added regions)
After making the terrain I added 3 regions. Red, Blue and Green.
The Red one is the place where the creeps spawn.
The Blue one is where the creeps go into and then go on to the green place.
The Green is the place they enter to make you lose a life and then disappear.



The Trigger Core


Every TD needs triggers to make the creeps move the right way, not attacking, take lives from the team etc.. No Custom Map will work without triggers. You can learn about triggers other places in the trigger tutorial forum.

Notes
The Tower Defense system in this tutorial was based on what I used for Warhammer 40,000 TD and what DukeWintermaul did on his as well.

Variables
Below is a list of the variables we are going to use for this tutorial:
NameTypeInitial ValueArray
LivesInteger25No
Levels_AmountInteger3No
Levels_UnitsUnit-TypeN/AYes 3 (same as above)
Levels_Units_CountIntegerN/AYes 3 (same as above)
Levels_CurrentInteger0No
TimerTimerN/ANo
locPointN/ANo

Initialization
The trigger below will set our values.
  • Initialization
    • Events
      • Map initialization
    • Conditions
    • Actions
      • -------- This is where we set which unit spawns on each level --------
      • Set Levels_Units[1] = Peasant
      • Set Levels_Units[2] = Footman
      • Set Levels_Units[3] = Knight
      • -------- This is the amount of units to spawn on each level --------
      • Set Levels_Units_Count[1] = 10
      • Set Levels_Units_Count[2] = 10
      • Set Levels_Units_Count[3] = 40
Start Game
A unit is from beginning, placed on a location in the map. This is because we will trigger our "Next Level" trigger by killing that unit which leads to Player 12's food used becoming 0.
  • StartGame
    • Events
      • Time - Elapsed game time is 1.00 seconds
    • Conditions
    • Actions
      • Unit - Kill Peasant 0000 <gen>
      • Game - Display to (All players) the text: Welcome to ....
Next Level
This trigger will execute every time Player 12 has 0 units. Which means every time a level is over and when the dummy peasant dies.
The level will be increased and a timer for the next level has begun.
  • NextLevel
    • Events
      • Player - Player 12 (Brown)'s Food used becomes Equal to 0.00
    • Conditions
    • Actions
      • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
        • If - Conditions
          • Levels_Current Equal to Levels_Amount
        • Then - Actions
          • Player Group - Pick every player in (All players) and do (Actions)
            • Loop - Actions
              • Game - Victory (Picked player) (Show dialogs, Show scores)
        • Else - Actions
      • Set Levels_Current = (Levels_Current + 1)
      • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
        • If - Conditions
          • Levels_Current Equal to 1
        • Then - Actions
          • -------- Give everyone a few more seconds to start their base --------
          • Countdown Timer - Start Timer as a One-shot timer that will expire in 50.00 seconds
          • Game - Display to (All players) the text: The game will start...
        • Else - Actions
          • -------- Normal start --------
          • Countdown Timer - Start Timer as a One-shot timer that will expire in 25.00 seconds
          • Game - Display to (All players) the text: The next level will...
      • Countdown Timer - Create a timer window for Timer with title Level
Timer Expires
  • NextLevel Timer
    • Events
      • Time - Timer expires
    • Conditions
    • Actions
      • Countdown Timer - Destroy (Last created timer window)
      • Unit - Create Levels_Units_Count[Levels_Current] Levels_Units[Levels_Current] for Player 12 (Brown) at (Center of Red <gen>) facing Default building facing degrees
      • Game - Display to (All players) the text: The level has begun!
Red To Blue
This trigger will run every time a unit owned by Player 12 (creeps) enters region Red. It will then be ordered to enter region Blue:
  • RedToBlue
    • Events
      • Unit - A unit enters Red <gen>
    • Conditions
      • (Owner of (Entering unit)) Equal to Player 12 (Brown)
    • Actions
      • Set loc = (Center of Blue <gen>)
      • Unit - Order (Entering unit) to Move To loc
      • Custom script: call RemoveLocation(udg_loc)
Blue To Green
This trigger will run every time a unit owned by Player 12 (creeps) enters region Blue. It will then be ordered to enter region Green:
  • BlueToGreen
    • Events
      • Unit - A unit enters Blue <gen>
    • Conditions
      • (Owner of (Entering unit)) Equal to Player 12 (Brown)
    • Actions
      • Set loc = (Center of Green <gen>)
      • Unit - Order (Entering unit) to Move To loc
      • Custom script: call RemoveLocation(udg_loc)
Green -> Lives Lost
When a unit owned by Player 12 enters region Green, the variable called "lives" will be set to "lives"-1 and the unit will be killed.
If then "lives" equal to 0, it will pick al players and defeat them.
  • GreenToDead
    • Events
      • Unit - A unit enters Green <gen>
    • Conditions
      • (Owner of (Entering unit)) Equal to Player 12 (Brown)
    • Actions
      • Unit - Kill (Entering unit)
      • Set Lives = (Lives - 1)
      • Game - Display to (All players) the text: (You have lost a life! You currently have + ((String(Lives)) + lives left!))
      • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
        • If - Conditions
          • Lives Equal to 0
        • Then - Actions
          • Player Group - Pick every player in (All players) and do (Actions)
            • Loop - Actions
              • Game - Defeat (Picked player) with the message: Defeat!
        • Else - Actions


Builders and Towers


Making builders and towers for a TD is straight forward and the easiest part but I still have a few things to say about it.
The builder in a Tower Defense is often an invulnerable, non-blocking, non-attacking unit which you use for building your towers. It is often nescessary to build more than one tower at a time, which is a hell if you cannot. If you want your builder to build like the undead acolyte, simply change the race of your builder to undead.
The builder should definitely be an air unit so it can move around on the whole map with no problems. Having the builder stuck between two towers defines a poor TD.
Base all your towers off a Sentry Tower and you will be okay.


Bonus Features



Sell Tower System
Making a sell-system for your Tower Defense takes time, but is worth it.
Go through ALL your towers and set
Code:
[B]Stats - Point Value[/B] = [B]Stats - Gold Cost[/B]
If the unit is an upgrade, set it to this:
Code:
[B]Stats - Point Value[/B] = [B]Stats - Gold Cost[/B] (Base Unit) + [B]Stats - Gold Cost[/B] (Upgrade Unit).
But only if you want the player to receive the full amount paid for the upgrade + the base unit.

When all this is done, create an ability, base it off Warstomp and set all the values to neutral values (damage, animation, effect, hero ability).
Then make a trigger like this:
  • SellTower
    • Events
      • Unit - A unit Begins casting an ability
    • Conditions
      • (Ability being cast) Equal to Sell Tower
      • ((Casting unit) is A structure) Equal to True
    • Actions
      • Player - Add ((Point-value of (Casting unit)) x (3 / 4)) to Player 1 (Red) Current gold
      • Unit - Remove (Triggering unit) from the game
Look at the first action. I am multiplying the Point Value with 3/4 which means the player receives 75% of the price I paid for it. It is better to set the amount of money received in the trigger instead of doing it when setting the point value.

Boot Player System
Booting players is always nice, in this system I will set an admin to do the booting, the default admin will be Player 1, but if you are in the game, it will assign you instead.
For this system, you will need a variable:
NameTypeInitial ValueArray
AdminPlayerN/ANo
Here's the triggers:

Assign Admin
You will ofcourse need to add more of the events if you are more than 3 players.
  • Assign Admin
    • Events
      • Time - Elapsed game time is 1.00 seconds
      • Player - Player 1 (Red) leaves the game
      • Player - Player 2 (Blue) leaves the game
      • Player - Player 3 (Teal) leaves the game
    • Conditions
    • Actions
      • -------- Set default admin --------
      • Set Admin = Player 1 (Red)
      • Player Group - Pick every player in (All players) and do (Actions)
        • Loop - Actions
          • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
            • If - Conditions
              • Or - Any (Conditions) are true
                • Conditions
                  • (Admin slot status) Not equal to Is playing
                  • (Name of (Picked player)) Equal to Ralle
            • Then - Actions
              • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
                • If - Conditions
                  • ((Picked player) slot status) Equal to Is playing
                • Then - Actions
                  • Set Admin = (Picked player)
                • Else - Actions
            • Else - Actions
Boot Player
When typing "-boot #" a player with the id of # will be booted.
You will ofcourse need to add more of the events if you are more than 3 players.
  • BootPlayer
    • Events
      • Player - Player 1 (Red) types a chat message containing -boot as A substring
      • Player - Player 2 (Blue) types a chat message containing -boot as A substring
      • Player - Player 3 (Teal) types a chat message containing -boot as A substring
    • Conditions
      • (Substring((Entered chat string), 1, 6)) Equal to -boot
    • Actions
      • Player Group - Pick every player in (All players) and do (Actions)
        • Loop - Actions
          • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
            • If - Conditions
              • ((Picked player) slot status) Equal to Is playing
            • Then - Actions
              • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
                • If - Conditions
                  • (Substring((Entered chat string), 7, 8)) Equal to (String((Player number of (Picked player))))
                • Then - Actions
                  • Game - Defeat (Picked player) with the message: Defeat!
                  • Unit - Remove (Picked unit) from the game
                • Else - Actions
            • Else - Actions
I added the map I made all the triggers with. If you test it, better type in 'iseedeadpeople' because you will have no units to work with ;)

~by Ralle
 

Attachments

  • ralles_td_tutorial_demo.w3x
    21 KB · Views: 1,161
Last edited:
Level 21
Joined
Jan 5, 2005
Messages
3,515
Leaks are like those cartons of milk that you open and then leave at the back of your fridge, or behind your sofa, or in some forgotten corner of your room. eventually these milk cartons build up and start to smell which creates a bad situation for everybody.

using that analogy, switch milk carton for memory address and smell for lag.

one way i know leaks occur is when you create a location by making something happen at a place on the map. this location is written to the memory but is not removed so it just clogs it up. in your case it is ordering the units to move i think. to get rid of them you need to use some custom jass command that i dont know, as i am no expert on leaks.

this is however, a good tutorial, gj :) i would give your rep, but when i try to it complains for some reason.
 
Level 40
Joined
Dec 14, 2005
Messages
10,532
Most common leaks are Unit Groups and Locations.

How to fix locs up (didn't see any Unit Groups)

In;

  • Unit - Create 1 unit at [color=red]Somewhere[/color]
If Somewhere is a function, like (Position of (Unit)) or (Center of (Region)), it will leak.

Instead, first, make a Point variable. (I like to call mine loc)

Then,

  • Set loc = Somewhere
  • Unit - Create 1 unit at loc
  • Custom script: call RemoveLocation( [color=red]udg_[/color]loc )
As you can see, all "global" variables are prefixed by udg_ when used in JASS.

Anyways, that cleans the leak!

Also, sidenote;

Triggering Unit > Casting Unit
 
Top