For the purpose of allowing players to create tower defence minigames, i have created several assets.
The assets include:
- 5 YAML files
- 5 SHPs
- 17 lua scripts
The download for the assets alone is available in two formats:
[font=Arial]Adding the assets[/font]
Ensure that your map in in an unpacked state before doing the following:
- Download and unpack the assets.
- Add the asset files to your map's directory. If there are any file name disputes then rename file appropriately
- Add the following lines to the bottom of your map.yaml file, making sure to substitute any new file names due to disputes:
Code: Select all
Rules: rules.yaml, overrides.yaml, towers.yaml Sequences: sequences.yaml Weapons: weapons.yaml
The rules.yaml file includes several definition of actors that are custom to tower defence:
SPAWN: This actor is the entrance for enemies into the map
TARGET: An enemy actor's goal is to enter this actor, make sure it is accessible.
PATH: This actor should be placed onto every tile on every tile you do not want players to be build on. See path.lua.
BORDER: This actor should be placed to limit the movement of enemies. See path.lua.
CONTROLLER: This actor provides the build queue for the player. See controller.lua.
MODE_BUILD: This actor is used to enable the controller's building functionality. See controller.lua.
MODE_WAVE: This actor is used to disable the controller's building functionality. See controller.lua.
Here is an example of what your map may look like:
The overrides.yaml file includes redefinitions for several actors to make them work better with tower defence:
BRIK: Removes buildability.
SILO: Removes buildability.
MSLO: Remove buildability.
^ENEMY: Make enemies block projectiles.
^Infantry: Inherit ^ENEMY and remove bounty.
^Vehicle: Inherit ^ENEMY, remove bounty and share cell.
^Ship: Remove bounty.
^NeutralPlane: Remove bounty.
^BasicBuilding: Remove bounty.
1TNK: Don't spawn actor on death.
2TNK: Don't spawn actor on death.
3TNK: Don't spawn actor on death.
4TNK: Don't spawn actor on death.
Zombie: Scale up 3x.
The towers.yaml file includes a towers super-definition and a few example towers.
^Tower: Tower actor super-definition.
TOWER.MACHINE: Machine gun tower.
TOWER.LASER: Laser tower.
TOWER.TRACTOR: Slow tower, commented out as it has been superceded by the tesla tower.
TOWER.FOUNTAIN: Flame tower.
TOWER.MORTAR: Artillery tower.
TOWER.TESLA: Tesla tower.
DUMMY.TESLA: Dummy tesla weapon actor.
sequences.yaml contains sequence definitions for custom actors defined in rules.yaml.
weapons.yaml contains weapon definitions for the towers defined in towers.yaml.
The first version of tower defence had a single, monolithic, script accomanied
by a couple of supplementary scripts. Version 2 features script modules which
each add something to the game but can (mostly) be removed without breaking
the game. This means modders should have an easier time adding custom content.
However it is difficult to ensure that core modules aren't dependent on one
another so it may take a while for updates.
The config.lua script contains several global variables that can be set to
modify the game and it's core modules. At a later date config files will be
separated per module.
Config.lives: Sets the number of lives the player has. (Requires
Config.maxLives: Sets the max lives the player has. (Requires lives.lua)
Config.player: Sets the player player.
Config.enemy: Sets the enemy player.
Config.neutral: Sets the neutral player.
Config.wavesToSurvive: Sets the number of waves the player must survive
to win. Set this to nil to make it endless.
wave-config.lua is the wave-specific config file. It contains several global variables
that have an effect on how waves are generated.
Config.initWaveNum: Sets the initial wave number.
[n]Config.waveOwner:[/b] Sets the player owner of the spawned wave actors.
Config.spawnDelay: Sets the delay between spawning enemies. (Requires
Config.waveTypes: Sets the actor types that can be generated using wave-maker.lua. The cost field specifies the cost of the unit in the budget calculation, the shares field specifies the chance the type is chosen (the higher, the more likely), the minWave field specifies the minimum wave this type can be spawned, the maxWave field specifies the maximum wave that the type can be spawned in. Cost is required.
The interface.lua script manages the user interface.
Interface.update(): Spdates the user interface.
Interface.output(): Returns a string to be displayed on screen.
Interface.setOutputFunc(func): Sets Interface.output to the function
The utility.lua script provides a functions with broad use cases.
The array.lua script provides utility functions with broad use cases for
array-like tables. Since this is for utility use I will not be documenting it.
The functions are all small and usually self-explanitory.
The set.lua script provides utility functions with broad use cases for
set-like tables. Since this is for utility use I will not be documenting it.
The functions are all small and usually self-explanitory.
The tesla.lua script makes the tesla weapon bounce between struck targets.
Tesla.hitTrigger(actor, n): Adds a trigger to actor which bounces tesla
hits to n other targets.
Tesla.addTriggers(actors, n): Calls Tesla.hitTrigger(actor, n) for each
actor in actors.
The map-utility.lua script provides several functions to make your life a
little easier when working with the map.
MapUtility.width(): Returns the map's width in cells.
MapUtility.height(): Returns the map's height in cells.
MapUtility.centre(): Returns the map's centre WPos.
MapUtility.inBounds(pos): Returns true if pos (CPos) is in the map's
bounds, returns false otherwise.
The camera.lua script provides a function to centre the camera.
Camera.centre(): Centres the camera.
The path.lua script provides functionality for the PATH and BORDER actors,
using them to control passability and builability.
Path.updatePath(): Updates the table of PATH actors controlled by this
Path.updateBorder(): Updates the table of BORDER actors controlled by
Path.pathEnabled(): Returns true if PATH actors are in the world,
returns false otherwise.
Path.setPathEnabled(state): Sets all PATH actors' IsInWorld to state.
Path.borderEnabled(): Returns true if BORDER actors are in the world,
return false otherwise.
Path.setBorderEnabled(state): Sets all BORDER actors' IsInWorld to state.
The controller.lua script provides functions for controlling a single
CONTROLLER actor, which manages production, for the player. This script keeps
track of a mode actor which provides prerequisites for production.
Controller.init(mode, func): Creates the CONTROLLER actor for the
player player defined in config.lua and gives it the mode actor mode. When
a non-building actor is produced, func is called with the actor as a
parameter. The controller actor is returned.
Controller.getMode(): Returns the mode actor of the controller.
Controller.setMode(mode): Sets the controller's mode actor to mode
and destroys the previous mode actor.
The target.lua script keeps track of valid target actors for enemies to head
towards. TARGET actors are not automatically tracked as targets, instead they
need to be added manually. This allows you to enable/disable targets as you
Target.isTarget(actor): Returns true if the actor has been added as a
Target.makeTarget(actor, func): Adds the actor as a target if it is not
already tracked as a target. func is the callback function for
Target.makeTargets(actors, funcs): Calls Target.makeTarget(actor, func)
for each actor in actors.
Target.removeTarget(actor): Removes actor from the table of tracked
target actors if it is being tracked.
Target.removeTargets(actors): Calls Target.removeTargets(actor) for
each actor in actors.
Target.getTargets(): Returns a table of currently tracked target
The spawn.lua script keeps track of valid spawn actors for enemies to spawn
from. SPAWN actors are not automatically tracked as spawns, instead they need
to be added manually. This allows you to enable/diable spawns as you wish.
Spawn.isSpawn(actor): Returns true if the actor has been added as a
Spawn.makeSpawn(actor, targets): Adds the actor as a spawn if it is not
already tracked as a spawn. targets is a table of target actors that enemies spawned
from actor can head towards.
Spawn.makeSpawns(actors, targets): Calls Spawn.makeSpawn(actor,
targets) for each actor in actors.
Spawn.removeSpawn(actor): Removes actor from the table of tracked spawn
Spawn.removeSpawns(actors): Calls Spawn.removeSpawn(actor) for each
actor in actors.
Spawn.getSpawns(): Returns a table of currently tracked spawn actors.
Spawn.getSpawnTargets(actor): Returns a table of valid targets for
actor if it is being tracked.
The wave-manager.lua script handles waves and keeps track of wave information.
WaveManger.getWaveNum(): Returns the number of wave that the player is currently
WaveManager.getTime(): Returns the time left (in ticks) for the current
wave to be completed if it is a timed wave.
WaveManager.getWave(num): Returns wave number num. Returns nil if the wave
has not been set.
WaveManager.setWaveNum(value): Sets the wave number to value.
WaveManager.setTime(value): Sets the time left to value.
WaveManager.setWave(num, types): Sets wave number num to types.
WaveManager.incWaveNum(value): Increments the wave number by value or 1 if value
is not provided. Use this to decrement by giving negative values of value.
WaveManager.sendWave(wave, time, deadFunc): Spawns actors from currently tracked
spawns and sends them towards currently tracked targets. If wave is provided then the wave is
recorded, otherwise it uses one previously set. If none have been set an error occurs. If time is
provided the wave will end after time ticks, otherwise it ends after all actors are dead. deadFunc
is called at the end of the wave and must be provided.
The wave-maker.lua script provides functions for generating waves for use with wave-manager.lua.
If Config.waveTypes has been provided they will be automatically loaded in at the start of the map.
WaveMaker.getTypes(): Returns a table of added types.
WaveMaker.getCost(type): Returns the cost of type if it was defined.
WaveMaker.getShares(type): Returns the shares of type if it was defined.
WaveMaker.getMinWave(type): Returns the minWave of type if it was defined.
WaveMaker.getMaxWave(type): Returns the maxWave of type if it was defined.
WaveMaker.createWave(budget): Returns a table of types based on Config.waveTypes
and it's limitations. Budget is how much can be "spent" on units. The cost of a unit is deducted
from the budget when it is added to the wave.
The lives.lua script keeps track of the player's lives and provides several
functions for manipulating them.
Lives.init(lives, maxLives): Sets the player's current lives to lives
and their max number of lives to maxLives.
Lives.isAlive(): Returns true if the number of lives is greater than 0,
returns false otherwise.
Lives.getLives(): Returns the number of lives the player has left.
Lives.getMaxLives(): Returns the max number of lives the player can
Lives.setLives(value): Sets the player's lives to value.
Lives.setMaxLives(value): Sets the player's max lives to value.
Lives.incLives(value): Increments the player's lives by value or 1 if
value is not provided.
Lives.decLives(value): Decrements the player's lives by value or 1 if
value is not provided.
Lives.toString: Returns a string representative of the lives remaining.
Must be set using Lives.setToStringFunc before use.
Lives.setToStringFunc(func): Sets Lives.toString to return func(lives,
Lives.setIncFunc(func): func is called when Lives.incLives is called.
Lives.setDecFunc(func): func is called when Lives.decLives is called.
Lives.setDeathFunc(func): func is called when the number of lives the
player has reaches 0 after a decrementation or a set.
The main.lua script should, ideally be created by you. The modules described
above give a lot of functionality that can be utilised to create a custom
tower defence game. However, this is nothing stopping you from using the
provided main.lua instead.
Feedback is welcome and so are suggestions. Don't be scared to comment/ask! If you have errors then please use www.pastebin.com to record them and then send me a link via IRC or comment here.