EternalTD-Wellen & Gegner
Eine Wellen-Datei unter plugins/EternalTD/waves/ definiert das gesamte Gegneraufgebot für ein Level, einschließlich normaler Wellen, Sudden-Death-Wellen und optionaler Vorwellen- oder Wellennachrichten. Jede Level-Konfiguration verweist über wavesConfigFile: auf eine Wellen-Datei.
Felder auf oberster Ebene
| Feld | Typ | Standard | Hinweise |
|---|---|---|---|
isEnabled | bool | true | Wird hier deaktiviert, wird auch das davon abhängige Level deaktiviert |
baseMobAmount | int | 20 | Standardmenge, die verwendet wird, wenn ein Eintrag kein amount= angibt |
waveEntities | string list | erforderlich | Gegnereinträge welle für welle |
suddenDeathWaveEntities | string list | optional | Optionaler zyklischer Wellenpool, der nach Erschöpfung der konfigurierten Wellen läuft |
prewaveMessages | list of maps | optional | Nachrichten, die vor dem Start einer bestimmten Welle angezeigt werden |
waveMessages | list of maps | optional | Nachrichten, die zu Beginn einer Welle angezeigt werden |
Wenn die Wellen-Datei keine Sudden-Death-Einträge definiert, endet das Level, sobald die konfigurierten Wellen erschöpft sind.
Wellen-Entitätseintragsformat
Jede Zeile in waveEntities (oder suddenDeathWaveEntities) ist ein durch Doppelpunkte getrennter Eintrag:
- 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
| Schlüssel | Typ | Hinweise |
|---|---|---|
wave | int | Erforderlich. Nummer der Welle, zu der dieser Eintrag gehört |
entityType | enum | Erforderlich. Bukkit-EntityType-Enum-Wert |
healthMultiplier | double | Optional, Standard 1.0. Multipliziert die maximale Lebensenergie der Entität |
amount | int | Optional. Überschreibt baseMobAmount für diesen Eintrag |
name | string | Optional. Benutzerdefinierter Namens-String. Wird geparst und gespeichert, das Plugin wendet ihn derzeit aber nicht auf den gespawnten Mob an (Namensschilder sind stattdessen die Lebens-/Rüstungsleisten) |
resist | flag | Markiert die Entität als immun gegen Verlangsamung |
fast | flag | Erhöht die Bewegungsgeschwindigkeit |
treasure | flag | Verdoppelt das Gold-Kopfgeld bei der Tötung |
boss | flag | Spawnt als einzelner Boss mit skalierter Lebensenergie und einer Boss-Leiste |
horde | flag | Verdoppelt amount und halbiert die Lebensenergie |
air | flag | Die Entität spawnt 4 Blöcke über dem Pfad und ignoriert Bodenmauern |
Interne Mengenberechnung
amountwird umwave / 10erhöht und anschließend auf eine ganze Zahl abgeschnitten, sodass ein Eintrag mitamount=20bei Welle 15 21 Mobs und bei Welle 20 22 Mobs ergibt.boss-Einträge überschreibenamountaufmax(1, floor(wave / 10)).horde-Einträge verdoppeln den finalenamount.- Zusätzlich zur Menge pro Eintrag fügt die Wellen-Laufzeit beim Aufbau der Welle Duplikate hinzu. Beachte, dass die Liste, in die dabei indiziert wird, die vollständig expandierte Mob-Liste ist — der Konfigurationsparser hat bereits ein Objekt pro Mob erzeugt, sodass eine einzelne
amount=20-Zeile 20 aufeinanderfolgende Indizes beisteuert, nicht einen. Für jeden geraden Indexi(0, 2, 4, ...), der sowohl ein gültiger Index in dieser expandierten Liste als auch kleiner als die Wellennummer ist, wird ein zusätzlicher Klon des Mobs an Indexihinzugefügt. Boss-Einträge werden auf diese Weise nie geklont. Die Anzahl der Bonus-Mobs beträgt also ungefährceil(min(waveNumber, listSize) / 2): 1 zusätzlicher Mob bei Welle 1, 2 bei den Wellen 3–4, 5 bei den Wellen 9–10, 8 bei den Wellen 15–16 und so weiter, bis die Wellennummer über die Liste hinauswächst.
Die Spawn-Taktung innerhalb einer Welle beträgt min(200 / totalEntities, 20) Ticks, und die Laufzeit wartet das Doppelte davon ab, bevor sie jeden Mob freigibt. horde-Wellen halbieren den Abstand und lassen ihre Mobs mit doppelter Normalrate los. Jeder Mob wählt beim Spawnen zufällig eines der Startfelder des Levels.
Nachrichtenblockformat
Sowohl prewaveMessages als auch waveMessages akzeptieren eine Liste von Maps:
prewaveMessages:
- wave: 1
message:
- "&aWelcome! Build a couple of basic towers along the path."
- wave: 5
message:
- "&6Heads up: a boss is coming next wave."
prewaveMessages wird zu Beginn der Konstruktionsphase dieser Welle ausgeführt. waveMessages wird in dem Moment ausgeführt, in dem die Verteidigungsphase beginnt.
Lebenszyklus einer Welle
Eine Sitzung durchläuft folgende Zustände:
STARTING— bevor der Spieler/etd startzum ersten Mal ausführt.CONSTRUCTION_PHASE— 10-sekündiges Baufenster zwischen Verteidigungsphasen.DEFENSIVE_PHASE— Gegner spawnen und laufen den Pfad entlang.ENDING— der Spieler hat aufgegeben, verloren oder das Level ist ohne Wellen.
Die Konstruktionsphase dauert immer 10 Sekunden, es sei denn, das Tutorial hält sie an (siehe Sonderfall Tutorial-Level).
Verhalten am Wellenende:
- Das Abschließen einer Welle gewährt
waveNumber * 10Gold. - Wenn du während der Welle keine Leben verloren hast, erhältst du einen "Perfekt"-Bonus in Höhe der Hälfte des Wellenbonus (
waveNumber * 10 * 0.5). Die angekündigte Zahl und das tatsächlich gewährte Gold stimmen jetzt überein. - Jede Welle kann nur einmal auszahlen — eine Welle, die aus irgendeinem Grund zweimal als abgeschlossen gemeldet wird, wird beim zweiten Mal ignoriert, und sobald die Sitzung endet, findet überhaupt keine Auszahlung mehr statt.
- Die Modifikatorliste der nächsten Welle wird nach jedem Wellenende angekündigt.
Wann ein Level endet
Die Sitzung rückt nur vor, wenn die nächste Wellennummer als Schlüssel in waveEntities existiert, daher müssen die Wellennummern lückenlos ab 1 laufen. Fehlt die nächste Nummer:
- geht der Lauf in Sudden Death über, wenn die Datei
suddenDeathWaveEntitiesdefiniert; - andernfalls endet das Level sofort, ohne die nie gelaufene Welle mitzuzählen. Der gespeicherte Highscore und der Abschlusstitel verwenden die letzte Welle, die der Spieler tatsächlich gespielt hat.
Sudden Death
Wenn suddenDeathWaveEntities definiert ist, läuft das Level über die konfigurierte Wellenliste hinaus weiter.
Der Sudden-Death-Pool zykliert nach konfigurierter Wellennummer, nicht über einen laufenden Zähler: Jedes Mal, wenn eine Sudden-Death-Welle benötigt wird, wählt EternalTD die niedrigste wave=-Nummer im Pool, die größer als die aktuelle ist, und springt zur niedrigsten konfigurierten Nummer zurück, wenn es nichts Höheres gibt. Der Pool muss daher nicht mit 1, 2, 3, ... durchnummeriert sein — Lücken und beliebige Startnummern zyklieren korrekt.
Die angezeigte Wellennummer zählt weiterhin von der regulären Wellenliste hoch; nur der gespawnte Pool-Eintrag zykliert.
Elementare Ausrichtung bei Welleneinheiten
Jede Welle hat ihre eigene elementare Ausrichtung, die pro Welle rotiert:
- Welle 1 → Feuer
- Welle 2 → Luft
- Welle 3 → Wasser
- Welle 4 → Erde
- (dann wiederholt sich das)
Wenn eine Welleneinheit spawnt, besteht eine Chance von waveNumber / 100, dass die Entität die elementare Ausrichtung der Welle erbt, angezeigt als farbiges Tag, das über dem Mob schwebt.
Die Regeln für elementaren Schaden werden von der DamageTower-Klasse des Turms verwaltet:
- Gleiche Ausrichtung Angreifer gegen gleiche Ausrichtung Ziel — 0,5× Schaden (Resistenz).
- Entgegengesetzte einzelne Elemente (Feuer gegen Wasser, Luft gegen Erde) — 2× Schaden (Krit).
- Fusionsausrichtungen (Magma, Druckwelle, Sturm, Schlamm) folgen paarweisen Wechselwirkungen; die vollständige Matrix findest du im Quellcode.
- Ein Turm ohne Ausrichtung verursacht 1× Schaden gegen alle.
Fusionsausrichtungen entstehen, wenn ein Basisturm von Unterstützungstürmen mit kombinierbaren elementaren Ausrichtungen berührt wird:
| Kombination | Resultierende Fusion |
|---|---|
| Feuer + Erde | Magma |
| Feuer + Luft | Druckwelle |
| Wasser + Luft | Sturm |
| Wasser + Erde | Schlamm |
Die Konfliktregeln sind enger gefasst, als sie aussehen:
- Erde + Luft am selben Turm setzt ihn immer auf „Ohne Ausrichtung" zurück, ganz gleich, was sonst noch anliegt.
- Feuer + Wasser setzt nur dann auf „Ohne Ausrichtung" zurück, wenn drei oder mehr verschiedene Ausrichtungen im Spiel sind. Ein Turm, der von genau einem Feuer- und einem Wasser-Unterstützungsturm berührt wird, behält willkürlich eine der beiden, weil der Code auf „nimm die erste Ausrichtung in der Menge" durchfällt und diese Menge ungeordnet ist.
- Unterstützungstürme ohne Ausrichtung (Fernrohrturm, Goldmine) beeinflussen das Ergebnis nie; sie fallen aus der Menge heraus, sobald irgendein ausgerichteter Turm anliegt.
Skalierung von Lebensenergie, Rüstung und Kopfgeld
WaveEntity wendet diese Schritte beim Spawnen in genau dieser Reihenfolge an:
- Die Grundlebensenergie beginnt bei
0.5und wächst mit der Welle:health = 0.5 + ((wave - 1)^1.2) / 2. - Boss-Entitäten multiplizieren das mit
baseMobAmount × 0.5. - Horde-Entitäten halbieren es.
- Hier wird das Kopfgeld berechnet, als
ceil(health)— vorhealthMultiplierund vor der Luft-Halbierung.treasure-Einträge verdoppeln es anschließend. maxHealth = health × healthMultiplier.- Luft-Entitäten halbieren
maxHealthnoch einmal. - Rüstung erscheint erst ab Welle 10 und ist auf
maxHealth / 80gesetzt.
Die Reihenfolge in Schritt 4 ist entscheidend: Ein healthMultiplier von 3.0 verdreifacht die Lebensenergie eines Gegners, ohne seine Goldauszahlung zu ändern, und Luft-Gegner zahlen dasselbe Kopfgeld wie ihre Boden-Entsprechungen, obwohl sie nur die halbe Lebensenergie haben. Goldminen-Unterstützungstürme addieren ihren Bonus im Moment des tödlichen Schlags auf das Kopfgeld.
Die Bewegungsgeschwindigkeit beträgt:
speed = 0.3 × (1 - slow)
× 1.5 × (1 - slow) if fast
× 0.5 if air
+ wave / 1000
Der abschließende Term wave / 1000 bedeutet, dass Gegner unabhängig von ihren Flags mit jeder Welle ein klein wenig schneller werden, und er wird nach den Luft- und Verlangsamungsmultiplikatoren angewendet, statt von ihnen skaliert zu werden.
Splitterlinge
Ab Welle 20 spawnen Nicht-Luft-Gegner beim Tod zusätzliche kleine Mobs ("Splitterlinge").
- Anzahl:
floor(wave / 20)pro Tötung. - War das Elternteil ein
CAVE_SPIDER, sind die SplitterlingeSILVERFISH. Andernfalls sind esCAVE_SPIDER. - Splitterlinge spawnen mit
wave / 2der Welle des Elternteils, sodass ein tiefer Lauf einen Splitterling immer noch in weitere Splitterlinge bei seinem eigenen Tod verketten kann. - Splitterlinge geben beim Tod 0 Gold, und Luft-Gegner spawnen niemals Splitterlinge.
Sonderfall Tutorial-Level
Die mitgelieferte Tutorial-Karte läuft über ein fest codiertes Tutorial-Wellenskript:
- Die Konstruktionsphase endet nicht automatisch, bis du die genau erforderlichen Türme auf den hervorgehobenen Feldern platziert hast.
- Fest codierte Türme werden durch farbige Betonflicken unter dem anvisierten Rasterfeld angezeigt und, falls FMM installiert ist, durch ein nach unten zeigendes rotes Pfeil-Modell, das darüber schwebt.
- Das Tutorial schiebt in frühen Wellen zusätzliches Gold nach, sodass das geskriptete Turm-Aufgebot immer erschwinglich ist:
+100in den Wellen 1, 2 und 3 sowie+200in Welle 4. Spätere Wellen erhalten nichts extra. - Jedes benötigte Turmfeld ist nach dem gewünschten Turm eingefärbt: grüner Beton für den Basisturm, braun für die Barrikade, weiß für Zucker, cyan für das Fernrohr, gelb für den Strahlengenerator, rot für die Explosionsfabrik, blau für die Eisbox, grau für den Rüstungsbrecher, orange für die Goldmine, violett für den Obsidiansteinbruch, schwarz für alles andere.
Spielerleben und Gold
- Startleben: 20.
- Startgold: 150.
- Boss-Mobs kosten 5 Leben, wenn sie das Ende erreichen. Alle anderen Mobs kosten 1 Leben.
- Cheaten (
/etd cheat) setzt Gold auf10.000.000und Leben auf1.000.000und markiert die Sitzung für Highscore-Zwecke als gecheatet. Den Cheat-Modus wieder auszuschalten stellt die ursprünglichen Werte nicht wieder her, und die Cheat-Markierung ist für diese Sitzung dauerhaft. /etd setwave <n>setzt ebenfalls die Cheat-Markierung und verschiebt die Wellenbelohnungs-Sperre so, dass die Welle, zu der du springst, bei ihrem Abschluss trotzdem auszahlt.
Highscore-Tracking
Jede Level-Konfiguration speichert highscoreWave und highscorePlayerName. Am Ende einer Nicht-Cheat-Sitzung speichert das Plugin die neue Wellennummer in der Level-Datei und sendet eine serverweite Nachricht, wenn der bisherige Punktestand übertroffen wurde.