City 17 TD


Summary

  • Name: City 17 Tower Defense
  • Development Time: 120+ Hours (WIP)
  • Genre: Tower Defense
  • Playtime: 10 minutes
  • Engine:Hammer
Download
.zip File
Design Goals

  • Built a Hammer Level, without mods, that plays like a tower defense game
  • Scripted a resource system
  • Scripted a spawn waves system
  • Scripted a ‘Tower’ spawn system

 

Layout/Design

A top down and side view of the map.

A top down and side view of the map in editor.

The layout of the map is a simple course that takes enemy NPC’s past tower positions. Alyx serves as the players life with a glowing orb above her head to indicate her health, green while healthy and red when hurt. Each wave increasing in Health and number with 10 waves in total. At the end of the 3rd and 6th waves Alyx will run further down the course giving the player more time to deal with each wave. Resource is gathered by killing enemies with towers and a small amount is given at the start to facilitate the building of a tower or two.

Scripting: Resource System Wiki


The following wiki entry was created after research and prototyping of the resource system for City 17 TD

 

Building a Resource System

BRSOverview

Overview

This tutorial covers the creation of a resource system that can be added to and subtracted from. This can be used for any kind of game where time, counting, or gathering and spending resources is desired. Once the skeleton of the system is set up triggering additions or subtractions is a simple task.
You will need the following entities to perform this task

  • 3 game_text entities
  • 3 logic_case entities
  • 3 math_counter entities
  • 1 logic_timer entity
  • 2 func_button entities or some other method of interacting with the system

Setting up entities

Game_text

The game_text entities are the simplest entities we need to set up.
They will occupy the 1’s, 10’s, and 100’s portions of the resource
value.

Set up each of the three game_text entities as such

Class Info

NSgame_text

Add 3 game_text entities and set up their values as such

  • Name: use any three names with each one representing a digit slot. ex. txt_text1s, txt_text10s, txt_text100s
  • Message Text: set to either “0” or if filling in the 100’s slot “<Resource Name> 0”.
  • Fade In: 0
  • Fade Out: 0
  • Hold Time: 0.125
  • Text Channel: use a unique channel for each game_text entity. I used 1 through 3.

Once setup your done with the game_text entities.

 

Math_counter

The math_counter entities are doing the actual keeping of the values for the 1’s, 10’s, and 100’s. They will also be broadcasting their value to the logic_case entities. As well as managing the movement of digits from one math_counter to another.

Set up each of the three math_counter entities as such

Class Info

NSmath_counter_classinfo

  • Name: again name them different names with each one representing a digit slot. ex. math_count1s, math_count10s, math_count100s
  • Initial Value: 1
  • Minimum Legal Value: 0
  • Maximum Legal Value: 11

The counter is set up to go from 1 to 10 with a buffer number in front and in back. This is done to allow for rolling up and down without compromising the value stored within.
This should become clearer once we get to the…

Outputs

Each Output is configured differently.

NSmath_counter_output1

For the 1s counter add the following outputs.

  • Name: OnHitMax
  • Target: this counter
  • Input: SetValue: 1

 

  • Name: OnHitMax
  • Target: the 10’s counter
  • Input: Add: 1

 

  • Name: OnHitMin
  • Target: this counter
  • Input: SetValue: 10

 

  • Name: OnHitMin
  • Target: the 10’s counter
  • Input: Subtract: 1

 

  • Name: OutValue
  • Target: the logic_case for the 1s
  • Input: InValue

 

Basically, this says if the counter reaches max (11) then set this counter to 1 (value for 0) and add 1 to the 10’s counter. If you hit the minimum set this counter to 10 (value for 9) and subtract 1 from the 10’s counter.

The last output, the OutValue to the logic_case, is to update the game_text with what is contained inside the logic_case. This will be explained in more detail in the logic_case section.

NSmath_counter_output10

For the 10s counter add the following outputs.

  • Name: OnHitMax
  • Target: this counter
  • Input: SetValue: 1

 

  • Name: OnHitMax
  • Target: the 100’s counter
  • Input: Add: 1

 

  • Name: OnHitMin
  • Target: this counter
  • Input: SetValue: 10

 

  • Name: OnHitMin
  • Target: the 100’s counter
  • Input: Subtract: 1

 

  • Name: OutValue
  • Target: the logic_case for the 1s
  • Input: InValue

 

This says if the counter reaches max (11) then set this counter to 1 (value for 0) and add 1 to the 100’s counter. If you hit the minimum set this counter to 10 (value for 9) and subtract 1 from the 100’s counter.

The last output, the OutValue to the logic_case, is to update the game_text with what is contained inside the logic_case. This will be explained in more detail in the logic_case section.

NSmath_counter_output100

For the 100s counter add the following outputs.

  • Name: OutValue
  • Target: the logic_case for the 1s
  • Input: InValue

The purpose of the OutValue to the logic_case is to update the game_text with what is contained inside the logic_case. This will be explained in more detail in the logic_case section.

Logic_case

The logic_case entities are what take the number from the counter and turn it into a value that is readable by the game_text entities, as the math_counter entities are integers and the game_text is a string.
Each value from 0 to 9 must be accounted for.

Class Info

NSmath_case_classinfo

For each logic_case do the following

  • Name: Name them different names with each one representing a digit slot. ex. log_case1s, log_case10s, log_case100s
  • Case 01: 1
  • Case 02: 2
  • Case 03: 3
  • Case 04: 4
  • Case 05: 5
  • Case 06: 6
  • Case 07: 7
  • Case 08: 8
  • Case 09: 9
  • Case 10: 10

Even though the math_counters we setup went from 0 to 11 we are only interested in 1 to 10. The 0 and the 11 values are held to allow the counter to go from 9 to 0 or 0 to 9 while adding/subtracting 1 from the next highest digit (see Math_counter for more info)

Outputs

NSmath_case_output
For the 1’s and 10’s logic_case entities create the following outputs

  • Output: OnCase01
  • Target: either the 1’s or 10’s game_text depending on which case this is for
  • Input: AddOutput
  • Parameter: message 0

 

  • Output: OnCase02
  • Target: either the 1’s or 10’s game_text depending on which case this is for
  • Input: AddOutput
  • Parameter: message 1

 

  • Output: OnCase03
  • Target: either the 1’s or 10’s game_text depending on which case this is for
  • Input: AddOutput
  • Parameter: message 2

*Output: OnCase04

  • Target: either the 1’s or 10’s game_text depending on which case this is for
  • Input: AddOutput
  • Parameter: message 3

*Output: OnCase05

  • Target: either the 1’s or 10’s game_text depending on which case this is for
  • Input: AddOutput
  • Parameter: message 4

*Output: OnCase06

  • Target: either the 1’s or 10’s game_text depending on which case this is for
  • Input: AddOutput
  • Parameter: message 5

*Output: OnCase07

  • Target: either the 1’s or 10’s game_text depending on which case this is for
  • Input: AddOutput
  • Parameter: message 6

Output: OnCase08

  • Target: either the 1’s or 10’s game_text depending on which case this is for
  • Input: AddOutput
  • Parameter: message 7

Output: OnCase09

  • Target: either the 1’s or 10’s game_text depending on which case this is for
  • Input: AddOutput
  • Parameter: message 8

Output: OnCase10

  • Target: either the 1’s or 10’s game_text depending on which case this is for
  • Input: AddOutput
  • Parameter: message 9

 

These outputs will change the text value stored in the game_text it targets.

For the 100’s logic_case there is a small change.

NSmath_case_output100

For the 1’s and 10’s logic_case entities create the following outputs

  • Output: OnCase01
  • Target: either the 1’s or 10’s game_text depending on which case this is for
  • Input: AddOutput
  • Parameter: message Resource 0

 

  • Output: OnCase02
  • Target: either the 1’s or 10’s game_text depending on which case this is for
  • Input: AddOutput
  • Parameter: message Resource 1

 

  • Output: OnCase03
  • Target: either the 1’s or 10’s game_text depending on which case this is for
  • Input: AddOutput
  • Parameter: message Resource 2

*Output: OnCase04

  • Target: either the 1’s or 10’s game_text depending on which case this is for
  • Input: AddOutput
  • Parameter: message Resource 3

*Output: OnCase05

  • Target: either the 1’s or 10’s game_text depending on which case this is for
  • Input: AddOutput
  • Parameter: message Resource 4

*Output: OnCase06

  • Target: either the 1’s or 10’s game_text depending on which case this is for
  • Input: AddOutput
  • Parameter: message Resource 5

*Output: OnCase07

  • Target: either the 1’s or 10’s game_text depending on which case this is for
  • Input: AddOutput
  • Parameter: message Resource 6

 

  • Output: OnCase08
  • Target: either the 1’s or 10’s game_text depending on which case this is for
  • Input: AddOutput
  • Parameter: message Resource 7

 

  • Output: OnCase09
  • Target: either the 1’s or 10’s game_text depending on which case this is for
  • Input: AddOutput
  • Parameter: message Resource 8

 

  • Output: OnCase10
  • Target: either the 1’s or 10’s game_text depending on which case this is for
  • Input: AddOutput
  • Parameter: message Resource 9

 

These outputs will change the text value stored in the game_text it targets.

Logic_timer

The logic_timer entity controls the refresh rate of the game_text entities.

Class Info

NSlogic_timer_classinfo

  • Name: log_timer or any other representative name
  • Refire Interval: 0.1

With a refire interval of 0.1 this timer will fire 10 times a second.

Outputs

NSlogic_timer_output

  • Output: OnTimer
  • Target: game_text for the 1’s
  • Input: Display

 

  • Output: OnTimer
  • Target: game_text for the 10’s
  • Input: Display

 

  • Output: OnTimer
  • Target: game_text for the 100’s
  • Input: Display

With these outputs, the game_text will update every time the timer goes off (every 0.1 seconds)

Func_button

The func_button is a placeholder for any other entity that you want to initiate the adding or subtracting.

Outputs

NSbutton_add

NSbutton_sub

The outputs at this point are a bit different. There is only one output that can be repeatedly used depending on how many points you wish to add/subtract. In the examples above if you hit the add button it adds 7 while the subtract button removes 5.

  • Output: OnPressed (or any other action you wish to award/use resources for)
  • Target: math_counter for the 1’s. ex. math_count1s
  • Input: Add or Subtract
  • Parameter: 1
  • Delay: The first Output has a delay of 0.00 with each consecutive output having an additional 0.02 (this is cumulative, See example images)

Reminder: These outputs can be added to any button, enemy death, etc. These outputs must follow this format.

Running the Resource System

  • Click on the add button to add to the total.
  • Click the subtract button to remove from the total.

Scripting: Towers

This is the spawning system for ally towers, as well as the resource system and game wave managers. The allies are housed inside of a trigger, when a tower is called the npc spawns right where it’s standing in the image, gets scooped up by the trigger and teleported to the proper location. The resource system is explained above.

teleport button

The towers were built as a prefab and then placed on the map. As part of the prefab, I inserted script nodes to facilitate the prefabs role as a Tower.  As an example of one of the functions of building towers this way, each of the scripted elements can be coded to automatically assign sequential numbers to each new prefab’d script if given the correct characters(&& in hammer). Teleporting it to the right tower platform is accomplished by the buying action’s script. Each button changes the destination of teleport_ally to the teleport_dest_# that it is built with. So as each new tower platform is created all of it’s component pieces are built with it as well.

Scripting: Wave Spawn System

This is the basic arrangement of the spawning system for the enemy. Each different enemy has a set of triggers and counters used in spawning waves of enemies.
This is the spawning system for the enemies.

A wave relies on a single Relay that when called would spawn a predetermined number of enemies with a specific amount of health.

As the game progresses a counter keeps track of the wave number and when a wave is completed it prepares the next wave for deployment.

This happens in a loop until either the victory  after 10 waves or the loss condition is achieved.