Skip to main content

EternalTD Waves & Enemies

A wave file under plugins/EternalTD/waves/ defines the entire enemy lineup for a level, including normal waves, sudden-death waves, and optional pre-wave or wave messages. Each level config references one wave file through wavesConfigFile:.

Top-Level Fields​

FieldTypeDefaultNotes
isEnabledbooltrueDisabled wave files are not loaded; dependent levels cannot start with that missing wave configuration
baseMobAmountint20Default amount used when an entry doesn't specify amount=
waveEntitiesstring listrequiredWave-by-wave enemy entries
suddenDeathWaveEntitiesstring listoptionalOptional cyclic wave pool that runs after the configured waves are exhausted
prewaveMessageslist of mapsoptionalMessages keyed by the current counter: 0 on entry, N after wave N ends
waveMessageslist of mapsoptionalMessages shown when a wave begins

Without sudden-death entries, the session ends when the next-wave transition finds no configured next wave. This normally follows the final construction window, unless the player advances early.

Wave Entity Entry Format​

Each line in waveEntities (or suddenDeathWaveEntities) is a colon-separated entry:

- wave=1:entityType=ZOMBIE:healthMultiplier=1.0:amount=10
- wave=2:entityType=SKELETON:fast:treasure
- wave=5:entityType=WITHER_SKELETON:boss
- wave=8:entityType=PHANTOM:air:horde
KeyTypeNotes
waveintRequired. Wave number this entry belongs to
entityTypeenumRequired. Exact Bukkit EntityType enum value; choose a spawnable living entity
healthMultiplierdoubleOptional, default 1.0. Multiplies the entity's max health
amountintOptional. Overrides baseMobAmount for this entry
namestringOptional. Custom name string. Parsed and stored, but the plugin does not currently apply it to the spawned mob (nameplates are the health/armor bars instead)
resistflagMarks the entity as slow-immune
fastflagIncreases movement speed
treasureflagDoubles the gold bounty on kill
bossflagUses the boss quantity rule below, scaled health and a boss bar for each boss
hordeflagDoubles amount and halves health
airflagEntity spawns 4 blocks above the path and ignores ground walls

Keep keys and flags free of surrounding spaces, use uppercase entity types, positive wave numbers and positive amounts and health multipliers. The parser does not trim tokens or reject every invalid range. Unknown keys are ignored. A malformed normal entry disables the wave configuration; a malformed sudden-death entry logs a warning and can leave earlier parsed entries in that pool. A parsed file is not proof that its entities can spawn.

Internal Quantity Math​

  • amount is incremented by wave / 10 and then truncated back to a whole number, so an entry with amount=20 yields 21 mobs at wave 15 and 22 at wave 20.
  • boss entries override amount to max(1, floor(wave / 10)).
  • horde entries double the final amount.
  • On top of the per-entry amount, the wave runtime adds duplicates when the wave is built. Note that the list it indexes into is the fully expanded mob list — the config parser has already emitted one object per mob, so a single amount=20 line contributes 20 consecutive indices, not one. For each even index i (0, 2, 4, ...) that is both a valid index in that expanded list and smaller than the wave number, one extra clone of the mob at index i is added. Boss entries are never cloned this way. So the number of bonus mobs is roughly ceil(min(waveNumber, listSize) / 2): 1 extra mob at wave 1, 2 at waves 3-4, 5 at waves 9-10, 8 at waves 15-16, and so on until the wave number outgrows the list.

The spawn interval is min(floor(200 / totalEntities), 20) ticks. The counter must exceed twice that interval for a normal spawn; for horde pacing it must exceed twice the integer-halved interval. Because this is a strict comparison, there is an extra counter tick rather than an exact two-times interval. Horde pacing is selected from the first remaining mob in the wave list, so mixing horde and ordinary entries can change pacing as that list changes. Every mob picks one of the level's start tiles at random when it spawns.

Message Block Format​

Both prewaveMessages and waveMessages accept a list of maps:

prewaveMessages:
- wave: 0
message:
- "&aWelcome! Build a couple of basic towers along the path."
- wave: 4
message:
- "&6Heads up: a boss is coming next wave."

prewaveMessages[0] runs on entry. After wave N ends, prewaveMessages[N] runs during construction for the next wave: use key 4 to warn about wave 5. waveMessages[N] runs when wave N begins. These keys use the displayed session counter, including in sudden death. Repeated message entries for the same key overwrite earlier ones.

Wave Lifecycle​

A session moves through these states:

  • STARTING — before the player runs /etd start for the first time.
  • CONSTRUCTION_PHASE — 10-second build window between defensive phases.
  • DEFENSIVE_PHASE — enemies are spawning and walking the path.
  • ENDING — player quit, lost, or the level ran out of waves.

The ordinary construction timer is 10 seconds. /etd start or the Next Wave tool can advance early, but tutorial requirements still gate progression (see Tutorial Level). The initial starting phase waits for a start action; the tutorial can advance when its last requirement is accepted.

Wave end behavior:

  • Completing a wave grants waveNumber * 10 gold.
  • If you lost no lives during the wave, you receive a "Perfect" bonus worth half the wave bonus (waveNumber * 10 * 0.5). The announced number and the gold actually granted now match.
  • Each wave can only pay out once — a wave that somehow reports completion twice is ignored the second time, and no payout happens at all once the session is ending.
  • A non-empty next-wave modifier string is announced after wave end; it comes from the first configured enemy, not every entry in a mixed wave.

When a Level Ends​

The session advances only if the next wave number exists as a key in waveEntities, so wave numbers must run contiguously from 1. When the next number is missing:

  • if the file defines suddenDeathWaveEntities, the run rolls into sudden death;
  • otherwise the level ends immediately, without counting the wave that never ran. The persisted high score and the completion title use the last wave the player actually played.

Sudden Death​

If suddenDeathWaveEntities is defined, the level keeps running past the configured wave list.

The sudden-death pool cycles by configured wave number. Each time it is needed, EternalTD chooses the lowest nonnegative key greater than the current pool key, or wraps to the lowest if none is higher. The initial pool counter is 0, so a configured key 0 is skipped on the first pass when positive keys exist. Use positive keys; gaps are supported, and key 0 is also unsuitable for the health formula below.

The displayed wave counter keeps increasing. Enemy health, armor, speed, base bounty and splitterling thresholds use the selected entry's configured wave= value; they do not automatically scale to the displayed counter. Runtime bonus clones and elemental rolls use the displayed counter. For example, pool entries 10 and 20 retain those enemy scaling values even at displayed wave 100. The next-wave lookup still checks for a regular entry at each displayed number, so a later regular key can be used after an earlier gap.

Elemental Attunement on Wave Entities​

Each wave has its own elemental attunement that rotates per wave:

  • Wave 1 → Fire
  • Wave 2 → Air
  • Wave 3 → Water
  • Wave 4 → Earth
  • (then repeats)

When a normal wave entity spawns, its chance of inheriting the wave's element is the displayed waveNumber / 100; from displayed wave 100 onward the roll always succeeds. A colored tag shows the element. Splitterlings are created separately and do not receive this roll.

Elemental damage rules are handled by the tower's DamageTower class:

  • Same attunement attacker vs same attunement target — 0.5× damage (resist).
  • Opposite single elements (Fire vs Water, Air vs Earth) — 2× damage (crit).
  • Fusion attunements follow the table below. Other unmatched combinations deal 1× damage.
  • An unattuned tower deals 1× damage to everyone.
Tower attunement2× damage against0.5× damage against
MagmaAir, WaterEarth, Fire, Magma
BlastEarth, WaterAir, Fire, Blast
StormFire, EarthAir, Water, Storm
SludgeFire, AirEarth, Water, Sludge

Fusion attunements form when a Basic Tower is touched by support towers with combining elemental attunements:

CombinationResulting fusion
Fire + EarthMagma
Fire + AirBlast
Water + AirStorm
Water + EarthSludge

The conflict rules are narrower than they look:

  • Earth + Air on the same tower always reverts it to Unattuned, whatever else is attached.
  • Fire + Water reverts to Unattuned only when three or more distinct attunements are in play. A tower touched by exactly one Fire support and one Water support keeps one of the two arbitrarily, because the code falls through to "pick the first attunement in the set" and that set is unordered.
  • Unattuned support towers (Spyglass, Gold Mine) never affect the result; they are dropped from the set as soon as any attuned tower is attached.

Every recalculation starts from the Basic Tower's own Unattuned element, so removing the final elemental support returns the tower to Unattuned.

Health, Armor, and Bounty Scaling​

WaveEntity applies these steps at spawn using its configured wave number (or its parent's halved wave for a splitterling), in this order:

  1. Base health starts at 0.5 and grows with the wave: health = 0.5 + ((wave - 1)^1.2) / 2.
  2. Boss entities multiply that by baseMobAmount × 0.5.
  3. Horde entities halve it.
  4. Bounty is computed here, as ceil(health) — before healthMultiplier and before the air penalty. treasure entries then double it.
  5. maxHealth = health × healthMultiplier.
  6. Air entities halve maxHealth again.
  7. Armor only appears from wave 10 onward, set to maxHealth / 80.

The ordering in step 4 matters: a healthMultiplier of 3.0 triples health without changing base bounty, and air enemies pay the same base bounty as equivalent ground enemies despite half the health. Gold Mine support adds its bonus on the killing blow, truncating the result to an integer; small bounties may gain no extra gold.

Movement speed is:

speed = 0.3 × (1 - slow)
× 1.5 × (1 - slow) if fast
× 0.5 if air
+ wave / 1000

The trailing wave / 1000 term uses the enemy's configured wave and is added after air and slow multipliers. This value drives the movement-speed attribute for mobs. The non-Mob fallback instead teleports 0.1 blocks toward its next destination per movement tick, so this formula is not a universal blocks-per-tick speed.

Splitterlings​

From wave 20 onward, non-air enemies spawn additional small mobs ("splitterlings") on death.

  • Count: floor(wave / 20) per kill.
  • If the parent was a CAVE_SPIDER, the splitterlings are SILVERFISH. Otherwise they are CAVE_SPIDER.
  • Splitterlings use floor(parentWave / 2) and inherit the current route position. They use their constructor's health multiplier of 0.5 and do not inherit the parent's flags or elemental attunement. At sufficiently high configured waves, they can produce further splitterlings when killed.
  • Splitterlings give 0 gold on death and air enemies never spawn splitterlings.

Tutorial Level Special Case​

The tutorial.yml level uses a hardcoded script tied to its map coordinates:

  • Required tower types must be placed on the highlighted squares, or upgraded there when that tower is already present. Selling a wrong tower on a required square is allowed; unrelated placements, sales and upgrades are rejected while that scripted stage applies. The last accepted requirement requests the next wave immediately.
  • Colored concrete marks the required squares. If FMM and the reddownarrow model are available, a red arrow indicates the required tower or upgrade above each square.
  • On entering construction after waves 1, 2 and 3, the tutorial adds +100 gold; after wave 4 it adds +200. This is extra income, not an affordability guarantee. Other wave numbers receive no injection.
  • Each required tower square is coloured by the tower it wants: green concrete for Basic Tower, brown for Barricade, white for Sugar, cyan for Spyglass, yellow for Beam Generator, red for Explosion Factory, blue for Ice Box, gray for Armor Crusher, orange for Gold Mine, purple for Obsidian Quarry, black for anything else.
  • During each scripted stage, a green boss bar counts the required towers placed, as Build towers! done/total!. Every two minutes the tutorial reminds you that /etd quit leaves and, while requirements remain, repeats the current pre-wave message.

Player Lives and Gold​

  • Starting lives: 20.
  • Starting gold: 150.
  • Boss mobs cost 5 lives if they reach the end. All other mobs cost 1 life.
  • Every /etd cheat toggle, including switching it off, resets gold to 10,000,000 and lives to 1,000,000. The session remains permanently ineligible for a high score.
  • /etd setwave <n> changes the session counter and reward guard and marks the run cheated; it does not replace active enemies or immediately start that wave. The next transition uses n + 1.

Highscore Tracking​

Each level config persists highscoreWave and highscorePlayerName. At the end of a non-cheating session, the plugin saves the new wave number into the level file and broadcasts a server-wide message if it beat the previous score.