diff --git a/Assets/Luneraria/Core/Content/ContentData.cs b/Assets/Luneraria/Core/Content/ContentData.cs new file mode 100644 index 0000000..003444a --- /dev/null +++ b/Assets/Luneraria/Core/Content/ContentData.cs @@ -0,0 +1,119 @@ +// by tools/port/gen_content.py from the Godot reference (luneraria/g3, 1b540f2). +// Since the port this file is the maintained source of the rule tables; ContentTests compares it +// with the exported reference in Assets/Luneraria/Tests/Core/Golden/content.json. +using System.Collections.Generic; + +namespace Luneraria.Core +{ + /// Rule tables of Champions of Luneraria: troops, monsters, sends, heroes, items, champions, bots. + public static partial class ContentData + { + public static readonly OrderedMap Units = Map( + new UnitDef { Id = "g01", DisplayName = "Kohlenbeißer", Cost = 45, UpgradeId = "g02", MaxHp = 260.0, Damage = 17.0, AttackType = 0, ArmorType = 0, AttackRange = 1.1, Speed = 2.4, Ability = "g01", LeakValue = 0, Bounty = 0, AbilityDescription = "Jeder 3. Treffer: Brand, 4 Schaden/s für 3 s." }, + new UnitDef { Id = "g02", DisplayName = "Schlackenklaue", Cost = 90, UpgradeId = "", MaxHp = 690.0, Damage = 44.0, AttackType = 0, ArmorType = 1, AttackRange = 1.2, Speed = 2.4, Ability = "g02", LeakValue = 0, Bounty = 0, AbilityDescription = "Jeder 3. Treffer: Brand, 12 Schaden/s für 3 s." }, + new UnitDef { Id = "g03", DisplayName = "Schlackenwacht", Cost = 70, UpgradeId = "g04", MaxHp = 650.0, Damage = 11.0, AttackType = 0, ArmorType = 1, AttackRange = 1.2, Speed = 2.4, Ability = "g03", LeakValue = 0, Bounty = 0, AbilityDescription = "Erste 8 s: 15 % weniger erlittener Schaden." }, + new UnitDef { Id = "g04", DisplayName = "Basaltbastion", Cost = 150, UpgradeId = "", MaxHp = 1650.0, Damage = 27.0, AttackType = 0, ArmorType = 1, AttackRange = 1.4, Speed = 2.4, Ability = "g04", LeakValue = 0, Bounty = 0, AbilityDescription = "Erste 10 s: 25 % weniger Schaden, danach 10 %." }, + new UnitDef { Id = "g05", DisplayName = "Funkenlanze", Cost = 65, UpgradeId = "g06", MaxHp = 240.0, Damage = 24.0, AttackType = 1, ArmorType = 0, AttackRange = 5.5, Speed = 2.0, Ability = "g05", LeakValue = 0, Bounty = 0, AbilityDescription = "Jeder 4. Treffer: 50 % zusätzlicher Grundschaden." }, + new UnitDef { Id = "g06", DisplayName = "Glasballiste", Cost = 140, UpgradeId = "", MaxHp = 640.0, Damage = 65.0, AttackType = 1, ArmorType = 0, AttackRange = 6.5, Speed = 2.0, Ability = "g06", LeakValue = 0, Bounty = 0, AbilityDescription = "Jeder 4. Treffer: 75 % zusätzlicher Grundschaden." }, + new UnitDef { Id = "g07", DisplayName = "Aschenwerfer", Cost = 95, UpgradeId = "g08", MaxHp = 310.0, Damage = 23.0, AttackType = 2, ArmorType = 0, AttackRange = 4.5, Speed = 2.0, Ability = "g07", LeakValue = 0, Bounty = 0, AbilityDescription = "Jeder Treffer: 30 % Flächenschaden an bis zu 3 weiteren Zielen in 1,5 m." }, + new UnitDef { Id = "g08", DisplayName = "Kraterrufer", Cost = 190, UpgradeId = "", MaxHp = 820.0, Damage = 58.0, AttackType = 2, ArmorType = 1, AttackRange = 5.0, Speed = 2.0, Ability = "g08", LeakValue = 0, Bounty = 0, AbilityDescription = "Jeder Treffer: 40 % Flächenschaden an bis zu 4 weiteren Zielen in 2 m." }, + new UnitDef { Id = "g09", DisplayName = "Herdhüter", Cost = 85, UpgradeId = "g10", MaxHp = 420.0, Damage = 12.0, AttackType = 2, ArmorType = 2, AttackRange = 3.5, Speed = 2.0, Ability = "g09", LeakValue = 0, Bounty = 0, AbilityDescription = "Alle 6 s: bis zu 3 Verbündete in 3 m erhalten für 4 s +10 % Grundangriffsschaden." }, + new UnitDef { Id = "g10", DisplayName = "Sonnenesse", Cost = 170, UpgradeId = "", MaxHp = 1080.0, Damage = 30.0, AttackType = 2, ArmorType = 2, AttackRange = 4.0, Speed = 2.0, Ability = "g10", LeakValue = 0, Bounty = 0, AbilityDescription = "Alle 6 s: bis zu 4 Verbündete in 4 m erhalten für 4 s +15 % Grundangriffsschaden und 45 Heilung." }, + new UnitDef { Id = "w01", DisplayName = "Dornhopser", Cost = 50, UpgradeId = "w02", MaxHp = 290.0, Damage = 18.0, AttackType = 0, ArmorType = 0, AttackRange = 1.1, Speed = 2.4, Ability = "w01", LeakValue = 0, Bounty = 0, AbilityDescription = "Jeder 3. Treffer: −20 % Bewegung für 2 s." }, + new UnitDef { Id = "w02", DisplayName = "Rankenschnapper", Cost = 100, UpgradeId = "", MaxHp = 800.0, Damage = 47.0, AttackType = 0, ArmorType = 1, AttackRange = 1.3, Speed = 2.4, Ability = "w02", LeakValue = 0, Bounty = 0, AbilityDescription = "Jeder 3. Treffer: −30 % Bewegung und −10 % Angriffstempo für 3 s." }, + new UnitDef { Id = "w03", DisplayName = "Korkrücken", Cost = 75, UpgradeId = "w04", MaxHp = 620.0, Damage = 12.0, AttackType = 1, ArmorType = 1, AttackRange = 1.2, Speed = 2.4, Ability = "w03", LeakValue = 0, Bounty = 0, AbilityDescription = "Heilt sich alle 5 s um 35 HP, sobald er verwundet ist." }, + new UnitDef { Id = "w04", DisplayName = "Ringborke", Cost = 155, UpgradeId = "", MaxHp = 1560.0, Damage = 31.0, AttackType = 1, ArmorType = 1, AttackRange = 1.4, Speed = 2.4, Ability = "w04", LeakValue = 0, Bounty = 0, AbilityDescription = "Heilt sich alle 5 s um 100 HP, sobald er verwundet ist." }, + new UnitDef { Id = "w05", DisplayName = "Samenschleuder", Cost = 60, UpgradeId = "w06", MaxHp = 230.0, Damage = 23.0, AttackType = 1, ArmorType = 0, AttackRange = 5.5, Speed = 2.0, Ability = "w05", LeakValue = 0, Bounty = 0, AbilityDescription = "Jeder 4. Treffer: Keimbrand, 3 Schaden/s für 4 s." }, + new UnitDef { Id = "w06", DisplayName = "Zapfenkrone", Cost = 135, UpgradeId = "", MaxHp = 630.0, Damage = 61.0, AttackType = 1, ArmorType = 0, AttackRange = 6.0, Speed = 2.0, Ability = "w06", LeakValue = 0, Bounty = 0, AbilityDescription = "Jeder 4. Treffer: Keimbrand, 10 Schaden/s für 4 s." }, + new UnitDef { Id = "w07", DisplayName = "Sporenkelch", Cost = 100, UpgradeId = "w08", MaxHp = 370.0, Damage = 22.0, AttackType = 2, ArmorType = 2, AttackRange = 4.0, Speed = 2.0, Ability = "w07", LeakValue = 0, Bounty = 0, AbilityDescription = "Jeder 3. Treffer: 60 % Grundschaden an bis zu 3 weiteren Zielen in 2 m." }, + new UnitDef { Id = "w08", DisplayName = "Pilzkathedrale", Cost = 195, UpgradeId = "", MaxHp = 940.0, Damage = 59.0, AttackType = 2, ArmorType = 2, AttackRange = 4.5, Speed = 2.0, Ability = "w08", LeakValue = 0, Bounty = 0, AbilityDescription = "Jeder 3. Treffer: 80 % Grundschaden an bis zu 4 weiteren Zielen in 2,5 m." }, + new UnitDef { Id = "w09", DisplayName = "Tauhüter", Cost = 90, UpgradeId = "w10", MaxHp = 390.0, Damage = 10.0, AttackType = 2, ArmorType = 0, AttackRange = 4.0, Speed = 2.0, Ability = "w09", LeakValue = 0, Bounty = 0, AbilityDescription = "Alle 4 s: heilt den am stärksten verwundeten Verbündeten in 4 m um 65 HP." }, + new UnitDef { Id = "w10", DisplayName = "Quellgeflecht", Cost = 180, UpgradeId = "", MaxHp = 1000.0, Damage = 27.0, AttackType = 2, ArmorType = 2, AttackRange = 4.5, Speed = 2.0, Ability = "w10", LeakValue = 0, Bounty = 0, AbilityDescription = "Alle 4 s: heilt bis zu 3 verwundete Verbündete in 4,5 m um je 80 HP." } + ); + + public static readonly OrderedMap Enemies = Map( + new UnitDef { Id = "e01", DisplayName = "Splitterling", MaxHp = 90.0, Damage = 6.0, AttackType = 0, ArmorType = 0, AttackRange = 1.0, Speed = 3.0, Ability = "e01", LeakValue = 25, Bounty = 3 }, + new UnitDef { Id = "e02", DisplayName = "Schalenläufer", MaxHp = 240.0, Damage = 9.0, AttackType = 1, ArmorType = 1, AttackRange = 1.2, Speed = 2.0, Ability = "e02", LeakValue = 55, Bounty = 6 }, + new UnitDef { Id = "e03", DisplayName = "Nebelrest", MaxHp = 150.0, Damage = 11.0, AttackType = 2, ArmorType = 2, AttackRange = 3.5, Speed = 2.2, Ability = "e03", LeakValue = 40, Bounty = 5 }, + new UnitDef { Id = "e04", DisplayName = "Fadenschütze", MaxHp = 130.0, Damage = 12.0, AttackType = 1, ArmorType = 0, AttackRange = 6.0, Speed = 2.4, Ability = "e04", LeakValue = 35, Bounty = 5 }, + new UnitDef { Id = "e05", DisplayName = "Bruchstampfer", MaxHp = 480.0, Damage = 16.0, AttackType = 0, ArmorType = 1, AttackRange = 1.4, Speed = 1.6, Ability = "e05", LeakValue = 90, Bounty = 10 }, + new UnitDef { Id = "e06", DisplayName = "Knotenrufer", MaxHp = 190.0, Damage = 7.0, AttackType = 2, ArmorType = 2, AttackRange = 4.0, Speed = 2.0, Ability = "e06", LeakValue = 45, Bounty = 6 }, + new UnitDef { Id = "e07", DisplayName = "Bruchhirsch", MaxHp = 1100.0, Damage = 28.0, AttackType = 0, ArmorType = 0, AttackRange = 1.4, Speed = 1.8, Ability = "e07", LeakValue = 250, Bounty = 30, IsBoss = true }, + new UnitDef { Id = "e08", DisplayName = "Riegelkoloss", MaxHp = 1400.0, Damage = 30.0, AttackType = 1, ArmorType = 1, AttackRange = 1.5, Speed = 1.5, Ability = "e08", LeakValue = 330, Bounty = 40, IsBoss = true }, + new UnitDef { Id = "e09", DisplayName = "Maskenrichter", MaxHp = 1800.0, Damage = 34.0, AttackType = 2, ArmorType = 2, AttackRange = 5.0, Speed = 1.8, Ability = "e09", LeakValue = 400, Bounty = 50, IsBoss = true }, + new UnitDef { Id = "e10", DisplayName = "Schlundkrone", MaxHp = 3000.0, Damage = 50.0, AttackType = 1, ArmorType = 1, AttackRange = 1.5, Speed = 1.3, Ability = "e10", LeakValue = 600, Bounty = 70, IsBoss = true } + ); + + public static readonly OrderedMap Sends = Map( + new UnitDef { Id = "s01", DisplayName = "Nadelspäher", Cost = 20, MaxHp = 100.0, Damage = 8.0, AttackType = 1, ArmorType = 0, AttackRange = 4.5, Speed = 2.8, Ability = "s01", LeakValue = 30, Bounty = 3, IncomeGain = 3 }, + new UnitDef { Id = "s02", DisplayName = "Rostschieber", Cost = 40, MaxHp = 240.0, Damage = 8.0, AttackType = 0, ArmorType = 1, AttackRange = 1.2, Speed = 1.8, Ability = "s02", LeakValue = 55, Bounty = 6, IncomeGain = 5 }, + new UnitDef { Id = "s03", DisplayName = "Dunstsänger", Cost = 80, MaxHp = 320.0, Damage = 10.0, AttackType = 2, ArmorType = 2, AttackRange = 5.0, Speed = 2.0, Ability = "s03", LeakValue = 70, Bounty = 9, IncomeGain = 9 }, + new UnitDef { Id = "s04", DisplayName = "Keilbrecher", Cost = 130, MaxHp = 650.0, Damage = 20.0, AttackType = 1, ArmorType = 1, AttackRange = 1.3, Speed = 1.6, Ability = "s04", LeakValue = 120, Bounty = 14, IncomeGain = 12 }, + new UnitDef { Id = "s05", DisplayName = "Risszehrer", Cost = 200, MaxHp = 1000.0, Damage = 30.0, AttackType = 2, ArmorType = 2, AttackRange = 4.0, Speed = 1.7, Ability = "s05", LeakValue = 180, Bounty = 20, IncomeGain = 17 } + ); + + public static readonly OrderedMap Heroes = Ordered( + new HeroSpec { Id = "held_ringborke", Name = "Ringborke", Title = "Wächterin der Wurzeln", Model = "w04", Cost = 260, RoleText = "Front / Schutz", Provisional = true, Summary = "Hält die Front, heilt sich selbst und schützt nahe Verbündete.", Base = new UnitDef { MaxHp = 2200.0, Damage = 34.0, AttackType = 1, ArmorType = 1, AttackRange = 1.4, Speed = 2.4, Ability = "w04" } }, + new HeroSpec { Id = "held_quellgeflecht", Name = "Quellgeflecht", Title = "Hüterin der Quelle", Model = "w10", Cost = 260, RoleText = "Unterstützung / Heilung", Provisional = true, Summary = "Heilt Verbündete in 4,5 m und stärkt die Armee im Gefecht.", Base = new UnitDef { MaxHp = 1300.0, Damage = 28.0, AttackType = 2, ArmorType = 2, AttackRange = 4.5, Speed = 2.0, Ability = "w10" } }, + new HeroSpec { Id = "held_funkenlanze", Name = "Funkenlanze", Title = "Schützin des Glutpakts", Model = "g05", Cost = 260, RoleText = "Fernkampf / Schaden", Provisional = true, Summary = "Hoher Einzelschaden aus der zweiten Reihe.", Base = new UnitDef { MaxHp = 950.0, Damage = 46.0, AttackType = 1, ArmorType = 0, AttackRange = 6.0, Speed = 2.0, Ability = "g05" } } + ); + + public static readonly int[] LevelXp = { 0, 120, 280, 480, 720, 1000, 1320, 1680, 2080, 2520 }; + public static readonly int[] TalentLevels = { 3, 6 }; + + /// Per hero: tiers of two mutually exclusive choices. + public static readonly Dictionary Talents = new Dictionary + { + { "held_ringborke", new[] + { + new[] { new TalentOption("borkenhaut", "Borkenhaut", "Eigenschutz: +15 % Schadensminderung für die Heldin."), new TalentOption("schutzwurzeln", "Schutzwurzeln", "Gruppenschutz: alle 4 s erhalten bis zu 4 Verbündete in 4 m 10 % Schadensminderung für 4,5 s.") }, + new[] { new TalentOption("stammschlag", "Stammschlag", "Einzelziel: jeder 3. Treffer +60 % Schaden."), new TalentOption("wurzelbeben", "Wurzelbeben", "Fläche: jeder 3. Treffer 50 % Schaden an bis zu 3 Gegner in 2 m.") } + } }, + { "held_quellgeflecht", new[] + { + new[] { new TalentOption("tiefe_quelle", "Tiefe Quelle", "Einzelziel: heilt den schwächsten Verbündeten um 190 statt drei um je 80."), new TalentOption("weite_quelle", "Weite Quelle", "Fläche: heilt bis zu 5 Verbündete in 5,5 m um je 65.") }, + new[] { new TalentOption("quellschild", "Quellschild", "Schutz: Geheilte erhalten 4 s lang einen Schild von 70."), new TalentOption("keimsaat", "Keimsaat", "Druck: jeder 2. Treffer setzt Keimbrand, 9 Schaden/s für 4 s.") } + } }, + { "held_funkenlanze", new[] + { + new[] { new TalentOption("durchschlag", "Durchschlag", "Einzelziel: jeder 4. Treffer ×2,1 statt ×1,5."), new TalentOption("splitterschuss", "Splitterschuss", "Fläche: jeder 4. Treffer zusätzlich 45 % an bis zu 3 Gegner in 2 m.") }, + new[] { new TalentOption("fernsicht", "Fernsicht", "+1,5 m Reichweite."), new TalentOption("glutsalve", "Glutsalve", "+20 % Angriffstempo.") } + } } + }; + + public static readonly OrderedMap Items = Ordered( + new ItemSpec { Id = "basaltschild", Name = "Basaltschild", Cost = 180, Text = "+350 Lebenspunkte", HpFlat = 350.0 }, + new ItemSpec { Id = "glutklinge", Name = "Glutklinge", Cost = 180, Text = "+18 % Schaden", Damage = 0.18 }, + new ItemSpec { Id = "rankenmantel", Name = "Rankenmantel", Cost = 200, Text = "+10 % Schadensminderung", Reduction = 0.1 }, + new ItemSpec { Id = "funkenfokus", Name = "Funkenfokus", Cost = 200, Text = "+15 % Angriffstempo", AttackSpeed = 0.15 }, + new ItemSpec { Id = "quellamulett", Name = "Quellamulett", Cost = 220, Text = "Regeneriert 1,5 % der Lebenspunkte pro Sekunde", Regen = 0.015 }, + new ItemSpec { Id = "kristallsplitter", Name = "Kristallsplitter", Cost = 260, Text = "Jeder Treffer: 25 % an bis zu 2 Gegner in 1,5 m · ab Stufe 3", Splash = 0.25, MinLevel = 3 } + ); + + public static readonly OrderedMap Champions = Ordered( + new ChampionSpec { Id = "ch_schutz", Name = "Rostschieber", RoleText = "Schutz", Model = "s02", Cost = 150, Base = "s02", Text = "Schildträger: startet mit Schild, gibt alle 6 s bis zu 4 Verbündeten in 4 m einen Schild von 120.", ViewScale = 1.25 }, + new ChampionSpec { Id = "ch_druck", Name = "Dunstsänger", RoleText = "Druck auf Unterstützer", Model = "s03", Cost = 150, Base = "s03", Text = "Sucht Unterstützer und Fernkämpfer und verlangsamt deren Angriffe.", ViewScale = 1.25, Priority = "support" }, + new ChampionSpec { Id = "ch_belagerung", Name = "Keilbrecher", RoleText = "Belagerung", Model = "s04", Cost = 180, Base = "s04", Text = "Greift bevorzugt Gebäude an und verursacht dort ×1,8 Schaden.", ViewScale = 1.3, Priority = "building", SiegeFactor = 1.8 } + ); + + /// Base troop id to role; iteration order matters for RoleOf (first match). + public static readonly OrderedMap MatchRoles = Pairs("g01", "melee", "g03", "front", "g05", "ranged", "g07", "splash", "g09", "support", "w01", "melee", "w03", "front", "w05", "ranged", "w07", "splash", "w09", "support"); + public static readonly OrderedMap HeroRoles = Pairs("held_ringborke", "front", "held_quellgeflecht", "support", "held_funkenlanze", "ranged"); + public static readonly string[] RowOrder = { "front", "melee", "splash", "ranged", "support" }; + public static readonly string[] BotNames = { "Eichrufer", "Aschenzunge", "Quellwächter", "Glutfaust", "Moosauge", "Basaltherz", "Rindenkrone", "Funkenschritt" }; + public static readonly string[] WavesMelee = { "e01", "e02", "e05" }; + public static readonly string[] ArmorNames = { "Leicht", "Schwer", "Ätherisch" }; + public static readonly string[] DamageNames = { "Klinge", "Durchschlag", "Impuls" }; + public static readonly OrderedMap FactionNames = Pairs("glutpakt", "Glutpakt", "wurzelbund", "Wurzelbund"); + + /// Bot profiles in the reference order (the seed rotation depends on it). + public static readonly OrderedMap BotProfiles = Ordered( + new BotProfile { Name = "ausgewogen", Front = 0.3, Melee = 0.25, Ranged = 0.25, Splash = 0.1, Support = 0.1, UpgradeFrom = 6, SupportLane = 0.0, Hero = "held_ringborke", HeroRound = 4, Items = new[] { "basaltschild", "glutklinge", "rankenmantel" }, TalentChoices = new[] { 0, 1 }, Champion = "" }, + new BotProfile { Name = "verteidigung", Front = 0.35, Melee = 0.2, Ranged = 0.25, Splash = 0.1, Support = 0.1, UpgradeFrom = 7, SupportLane = 0.15, Hero = "held_ringborke", HeroRound = 3, Items = new[] { "basaltschild", "rankenmantel", "glutklinge" }, TalentChoices = new[] { 1, 1 }, Champion = "ch_schutz" }, + new BotProfile { Name = "druck", Front = 0.2, Melee = 0.35, Ranged = 0.25, Splash = 0.15, Support = 0.05, UpgradeFrom = 8, SupportLane = 0.0, Hero = "held_funkenlanze", HeroRound = 3, Items = new[] { "glutklinge", "funkenfokus", "kristallsplitter" }, TalentChoices = new[] { 1, 1 }, Champion = "ch_belagerung" }, + new BotProfile { Name = "fernkampf", Front = 0.25, Melee = 0.1, Ranged = 0.4, Splash = 0.15, Support = 0.1, UpgradeFrom = 6, SupportLane = 0.0, Hero = "held_funkenlanze", HeroRound = 4, Items = new[] { "funkenfokus", "glutklinge", "kristallsplitter" }, TalentChoices = new[] { 0, 0 }, Champion = "ch_druck" }, + new BotProfile { Name = "teamhilfe", Front = 0.3, Melee = 0.2, Ranged = 0.25, Splash = 0.1, Support = 0.15, UpgradeFrom = 6, SupportLane = 0.22, Hero = "held_quellgeflecht", HeroRound = 4, Items = new[] { "quellamulett", "rankenmantel", "basaltschild" }, TalentChoices = new[] { 1, 0 }, Champion = "ch_schutz" }, + new BotProfile { Name = "bossjagd", Front = 0.35, Melee = 0.25, Ranged = 0.2, Splash = 0.1, Support = 0.1, UpgradeFrom = 6, SupportLane = 0.1, Hero = "held_ringborke", HeroRound = 3, Items = new[] { "glutklinge", "basaltschild", "rankenmantel" }, TalentChoices = new[] { 1, 1 }, Champion = "ch_belagerung", BossFrom = 5, BossTroops = 5 } + ); + } +} diff --git a/Assets/Luneraria/Core/Content/DataCatalog.cs b/Assets/Luneraria/Core/Content/DataCatalog.cs new file mode 100644 index 0000000..e85fc13 --- /dev/null +++ b/Assets/Luneraria/Core/Content/DataCatalog.cs @@ -0,0 +1,47 @@ +using System.Collections.Generic; + +namespace Luneraria.Core +{ + /// Lookups into the unit tables; every call returns an independent copy. + public static class DataCatalog + { + public static readonly string[] Factions = { "glutpakt", "wurzelbund" }; + + /// Troop definition (copy) or null for unknown ids. + public static UnitDef GetUnit(string id) + { + UnitDef entry; + return id != null && ContentData.Units.TryGetValue(id, out entry) ? entry.Clone() : null; + } + + public static UnitDef GetEnemy(string id) + { + return ContentData.Enemies[id].Clone(); + } + + public static UnitDef GetSend(string id) + { + return ContentData.Sends[id].Clone(); + } + + /// Upgrade target of a troop type, "" when fully upgraded or unknown. + public static string UpgradeOf(string id) + { + UnitDef entry; + return id != null && ContentData.Units.TryGetValue(id, out entry) ? entry.UpgradeId : ""; + } + + public static int CostOf(string id) + { + UnitDef entry; + return id != null && ContentData.Units.TryGetValue(id, out entry) ? entry.Cost : 0; + } + + /// The five base troops of a Bund, in shop order. + public static List FactionIds(string faction) + { + string prefix = faction == "wurzelbund" ? "w" : "g"; + return new List { prefix + "01", prefix + "03", prefix + "05", prefix + "07", prefix + "09" }; + } + } +} diff --git a/Assets/Luneraria/Core/Content/Definitions.cs b/Assets/Luneraria/Core/Content/Definitions.cs new file mode 100644 index 0000000..c983862 --- /dev/null +++ b/Assets/Luneraria/Core/Content/Definitions.cs @@ -0,0 +1,200 @@ +using System.Collections.Generic; + +namespace Luneraria.Core +{ + /// + /// Combat definition of a unit type: troop, monster, send, hero, champion, boss or building. + /// One type for all, as in the reference, where definitions were dictionaries; the defaults + /// are the fallbacks the rules used for missing keys (e.g. SiegeFactor 1, HpFactor 1). + /// + public sealed class UnitDef + { + public string Id = ""; + public string DisplayName = ""; + public int Cost; + public string UpgradeId = ""; + public double MaxHp = 1.0; + public double Damage; + /// 0 Klinge, 1 Durchschlag, 2 Impuls. + public int AttackType; + /// 0 Leicht, 1 Schwer, 2 Ätherisch. + public int ArmorType; + public double AttackRange = 1.0; + public double Speed = 2.0; + public string Ability = ""; + public int LeakValue; + public int Bounty; + public string AbilityDescription = ""; + public bool IsBoss; + public int IncomeGain; + // Set by the match for army units and heroes. + public string Role = ""; + public string HeroId = ""; + public int Level = 1; + public double ViewScale = 1.0; + public double Regen; + public double ItemSplash; + public List Talents = new List(); + public double DamageBonus; + public double ReductionBonus; + public double AttackSpeedBonus; + // Attack champions. + public string ChampionId = ""; + public string Priority = ""; + public double SiegeFactor = 1.0; + // Monsters: wave strength factor (heals of e06 scale with it). + public double HpFactor = 1.0; + // Buildings: outer, inner, base or core. + public string Tier = ""; + + public UnitDef Clone() + { + var copy = (UnitDef)MemberwiseClone(); + copy.Talents = new List(Talents); + return copy; + } + } + + public sealed class HeroSpec + { + public string Id = ""; + public string Name = ""; + public string Title = ""; + public string Model = ""; + public int Cost; + public string RoleText = ""; + public bool Provisional; + public string Summary = ""; + /// Level-1 values without items and talents. + public UnitDef Base = new UnitDef(); + } + + public sealed class TalentOption + { + public readonly string Id; + public readonly string Name; + public readonly string Text; + + public TalentOption(string id, string name, string text) + { + Id = id; + Name = name; + Text = text; + } + } + + public sealed class ItemSpec + { + public string Id = ""; + public string Name = ""; + public int Cost; + public string Text = ""; + public double HpFlat; + public double Damage; + public double Reduction; + public double AttackSpeed; + public double Regen; + public double Splash; + public int MinLevel = 1; + } + + public sealed class ChampionSpec + { + public string Id = ""; + public string Name = ""; + public string RoleText = ""; + public string Model = ""; + public int Cost; + /// Send type whose base values the champion scales (s02, s03, s04). + public string Base = ""; + public string Text = ""; + public string Priority = ""; + public double SiegeFactor = 1.0; + public double ViewScale = 1.0; + } + + public sealed class BotProfile + { + public string Name = ""; + public double Front; + public double Melee; + public double Ranged; + public double Splash; + public double Support; + public int UpgradeFrom; + public double SupportLane; + public string Hero = ""; + public int HeroRound; + public string[] Items = new string[0]; + public int[] TalentChoices = new int[0]; + public string Champion = ""; + /// Boss hunters only; 0 = never goes to the grotto. + public int BossFrom; + public int BossTroops; + + public bool HuntsBoss { get { return BossFrom > 0; } } + + public double Share(string role) + { + switch (role) + { + case "front": return Front; + case "melee": return Melee; + case "ranged": return Ranged; + case "splash": return Splash; + default: return Support; + } + } + } + + public static partial class ContentData + { + static OrderedMap Map(params UnitDef[] entries) + { + var map = new OrderedMap(); + foreach (UnitDef entry in entries) + map[entry.Id] = entry; + return map; + } + + static OrderedMap Ordered(params HeroSpec[] entries) + { + var map = new OrderedMap(); + foreach (HeroSpec entry in entries) + map[entry.Id] = entry; + return map; + } + + static OrderedMap Ordered(params ItemSpec[] entries) + { + var map = new OrderedMap(); + foreach (ItemSpec entry in entries) + map[entry.Id] = entry; + return map; + } + + static OrderedMap Ordered(params ChampionSpec[] entries) + { + var map = new OrderedMap(); + foreach (ChampionSpec entry in entries) + map[entry.Id] = entry; + return map; + } + + static OrderedMap Ordered(params BotProfile[] entries) + { + var map = new OrderedMap(); + foreach (BotProfile entry in entries) + map[entry.Name] = entry; + return map; + } + + static OrderedMap Pairs(params string[] keysAndValues) + { + var map = new OrderedMap(); + for (int i = 0; i + 1 < keysAndValues.Length; i += 2) + map[keysAndValues[i]] = keysAndValues[i + 1]; + return map; + } + } +} diff --git a/Assets/Luneraria/Core/Content/LuneBalance.cs b/Assets/Luneraria/Core/Content/LuneBalance.cs new file mode 100644 index 0000000..7cb73d6 --- /dev/null +++ b/Assets/Luneraria/Core/Content/LuneBalance.cs @@ -0,0 +1,70 @@ +namespace Luneraria.Core +{ + /// + /// Every tunable number of Champions of Luneraria (reference: lune_balance.gd with + /// data/luneraria/balance_default.tres). Tests may use variants; bots never get extras. + /// + public sealed class LuneBalance + { + // Simulation + /// Fixed combat step in seconds (20 steps per second of combat time). + public double SimStep = 0.05; + /// Ends only the current combat phase, never the match. + public double CombatTimeLimit = 180.0; + public double MarchSpeedFactor = 1.6; + public double AggroRadius = 7.0; + /// Targets further away than this are dropped and re-acquired. + public double LeashRadius = 10.0; + public double LaneHalfWidth = 2.6; + + // Economy + public int StartGold = 220; + public int BaseIncome = 70; + public int IncomePerRound = 4; + public int IncomeGrowthCap = 80; + public int SupplyCap = 12; + public double SellRefund = 0.75; + /// Share of lane kill gold for the lane player; the rest splits evenly in the team. + public double LaneShare = 0.5; + + // Waves + public int WaveBaseCount = 3; + /// One more monster per lane every N rounds, up to WaveMaxCount. + public int WaveCountEvery = 3; + public int WaveMaxCount = 7; + public double WaveHpGrowth = 0.11; + public double WaveDamageGrowth = 0.07; + public double WaveGrowthQuadratic = 0.0015; + public double MonsterBountyScale = 2.0; + public double BountyGrowth = 0.04; + /// Monster types in rotation order; later indices unlock later. + public string[] MonsterPool = { "e01", "e02", "e04", "e03", "e06", "e05" }; + + // Buildings + public double TowerOuterHp = 6000.0; + public double TowerInnerHp = 7500.0; + public double BaseTowerHp = 9000.0; + public double CoreHp = 12000.0; + public double TowerDamage = 90.0; + public double BaseTowerDamage = 120.0; + /// Must exceed the longest unit reach (6.5 m + building radius). + public double TowerRange = 8.6; + public double TowerAttackInterval = 1.0; + public double BuildingRadius = 1.3; + public int BountyOuterTower = 150; + public int BountyInnerTower = 210; + public int BountyBaseTower = 270; + + // Map + public double InnerTowerFraction = 0.17; + public double OuterTowerFraction = 0.35; + public double TowerSideOffset = 3.4; + + public static LuneBalance Default() { return new LuneBalance(); } + + public int RoundIncome(int roundNumber) + { + return BaseIncome + GdMath.Min(IncomeGrowthCap, IncomePerRound * GdMath.Max(0, roundNumber - 1)); + } + } +} diff --git a/Assets/Luneraria/Core/Content/LuneContent.cs b/Assets/Luneraria/Core/Content/LuneContent.cs new file mode 100644 index 0000000..72dbc1b --- /dev/null +++ b/Assets/Luneraria/Core/Content/LuneContent.cs @@ -0,0 +1,194 @@ +using System; +using System.Collections.Generic; + +namespace Luneraria.Core +{ + /// + /// Heroes, talents, items, attack champions and the boss (reference: lune_content.gd). + /// Hero and champion roles are provisional assignments of existing models. + /// + public static class LuneContent + { + public const double HpPerLevel = 0.09; + public const double DamagePerLevel = 0.07; + public const int XpParticipation = 40; + public const int XpPerRound = 6; + public const double XpRadius = 12.0; + public const int ItemSlots = 3; + public const double ItemRefund = 0.5; + public const double ChampionHp = 2.2; + public const double ChampionDamage = 1.6; + public const int ChampionBounty = 70; + public const int ChampionBountyPerRound = 6; + public const int MaxBookings = 2; + public const string BossModel = "e10"; + public const double BossGrottoHp = 3600.0; + public const double BossGrottoDamage = 55.0; + public const double BossDeployHp = 6800.0; + public const double BossDeployDamage = 88.0; + public const int BossBounty = 520; + public const int BossBountyPerRound = 60; + /// Victory in round n: deployment in n+1, locked in n+1..n+3, open again from n+4. + public const int BossLockRounds = 3; + public const int BossXp = 220; + public const int BuildingXp = 60; + + public static OrderedMap Heroes { get { return ContentData.Heroes; } } + public static OrderedMap Items { get { return ContentData.Items; } } + public static OrderedMap Champions { get { return ContentData.Champions; } } + public static int[] LevelXp { get { return ContentData.LevelXp; } } + public static int[] TalentLevels { get { return ContentData.TalentLevels; } } + + public static TalentOption[][] TalentsOf(string heroId) + { + return ContentData.Talents[heroId]; + } + + public static int LevelFor(int xp) + { + int level = 1; + for (int i = 0; i < ContentData.LevelXp.Length; i++) + { + if (xp >= ContentData.LevelXp[i]) + level = i + 1; + } + return level; + } + + /// Combat definition of a hero with its level, items and talents. + public static UnitDef HeroDefinition(HeroState hero) + { + HeroSpec spec = ContentData.Heroes[hero.HeroId]; + UnitDef definition = spec.Base.Clone(); + int level = LevelFor(hero.Xp); + definition.Id = spec.Model; + definition.HeroId = hero.HeroId; + definition.DisplayName = spec.Name; + definition.MaxHp = definition.MaxHp * (1.0 + HpPerLevel * (double)(level - 1)); + definition.Damage = definition.Damage * (1.0 + DamagePerLevel * (double)(level - 1)); + definition.Level = level; + definition.ViewScale = 1.25; + double damageBonus = 0.0; + double reduction = 0.0; + double attackSpeed = 0.0; + foreach (string itemId in hero.Items) + { + ItemSpec item = ContentData.Items[itemId]; + definition.MaxHp = definition.MaxHp + item.HpFlat; + damageBonus += item.Damage; + reduction += item.Reduction; + attackSpeed += item.AttackSpeed; + definition.Regen = definition.Regen + item.Regen; + definition.ItemSplash = definition.ItemSplash + item.Splash; + } + if (hero.Talents.Contains("borkenhaut")) + reduction += 0.15; + if (hero.Talents.Contains("fernsicht")) + definition.AttackRange = definition.AttackRange + 1.5; + if (hero.Talents.Contains("glutsalve")) + attackSpeed += 0.20; + definition.Talents = new List(hero.Talents); + definition.DamageBonus = damageBonus; + definition.ReductionBonus = reduction; + definition.AttackSpeedBonus = GdMath.Min(0.5, attackSpeed); + return definition; + } + + /// Attack champion of a round: a send type scaled like the waves of that round. + public static UnitDef ChampionDefinition(string championId, int roundNumber, LuneBalance balance) + { + ChampionSpec spec = ContentData.Champions[championId]; + UnitDef definition = DataCatalog.GetSend(spec.Base); + definition.Id = spec.Model; + definition.ChampionId = championId; + definition.DisplayName = spec.Name; + definition.MaxHp = definition.MaxHp * ChampionHp * LuneWaves.Strength(balance, roundNumber, balance.WaveHpGrowth); + definition.Damage = definition.Damage * ChampionDamage * LuneWaves.Strength(balance, roundNumber, balance.WaveDamageGrowth); + definition.Bounty = ChampionBounty + ChampionBountyPerRound * roundNumber; + definition.Priority = spec.Priority; + definition.SiegeFactor = spec.SiegeFactor; + definition.ViewScale = spec.ViewScale; + if (championId == "ch_schutz") + definition.Ability = "ch_schutz"; + return definition; + } + + /// The Schlundkrone: resting in the grotto, or deployed on a lane (with bounty). + public static UnitDef BossDefinition(int roundNumber, LuneBalance balance, bool deployed) + { + UnitDef definition = DataCatalog.GetEnemy(BossModel); + definition.DisplayName = "Schlundkrone"; + definition.MaxHp = (deployed ? BossDeployHp : BossGrottoHp) * LuneWaves.Strength(balance, roundNumber, balance.WaveHpGrowth); + definition.Damage = (deployed ? BossDeployDamage : BossGrottoDamage) * LuneWaves.Strength(balance, roundNumber, balance.WaveDamageGrowth); + definition.Bounty = deployed ? BossBounty + BossBountyPerRound * roundNumber : 0; + definition.IsBoss = true; + definition.ViewScale = 1.7; + definition.Speed = 1.6; + return definition; + } + + public static int BossBountyFor(int roundNumber) + { + return BossBounty + BossBountyPerRound * roundNumber; + } + } + + /// + /// Endless monster waves (reference: lune_waves.gd). Both teams get the identical composition + /// per lane. The count is capped; strength grows through stats and later monster types. + /// + public static class LuneWaves + { + public static double Strength(LuneBalance balance, int roundNumber, double growth) + { + double r = (double)(GdMath.Max(1, roundNumber) - 1); + return 1.0 + growth * r + balance.WaveGrowthQuadratic * r * r; + } + + public static int MonsterCount(LuneBalance balance, int roundNumber) + { + int extra = (GdMath.Max(1, roundNumber) - 1) / GdMath.Max(1, balance.WaveCountEvery); + return GdMath.Min(balance.WaveMaxCount, balance.WaveBaseCount + extra); + } + + public static List UnlockedTypes(LuneBalance balance, int roundNumber) + { + string[] pool = balance.MonsterPool; + int available = GdMath.Clamp(1 + (GdMath.Max(1, roundNumber) - 1) / 2, 1, pool.Length); + var result = new List(); + for (int i = 0; i < available; i++) + result.Add(pool[i]); + return result; + } + + /// Monster definitions for one lane of one team, melee first so they lead. + public static List Build(LuneBalance balance, int roundNumber) + { + List types = UnlockedTypes(balance, roundNumber); + double hpFactor = Strength(balance, roundNumber, balance.WaveHpGrowth); + double damageFactor = Strength(balance, roundNumber, balance.WaveDamageGrowth); + double bountyFactor = balance.MonsterBountyScale * (1.0 + balance.BountyGrowth * (double)(GdMath.Max(1, roundNumber) - 1)); + var melee = new List(); + var ranged = new List(); + int count = MonsterCount(balance, roundNumber); + for (int index = 0; index < count; index++) + { + string typeId = types[(index + roundNumber) % types.Count]; + UnitDef source = ContentData.Enemies[typeId]; + UnitDef monster = source.Clone(); + monster.MaxHp = source.MaxHp * hpFactor; + monster.Damage = source.Damage * damageFactor; + monster.HpFactor = hpFactor; + double bounty = GdMath.Clamp(GdMath.Round((double)source.Bounty * bountyFactor), 1.0, 1.0e12); + // The reference stores a 64-bit int; bounties stay far below int range in any real match. + monster.Bounty = bounty >= int.MaxValue ? int.MaxValue : (int)bounty; + if (Array.IndexOf(ContentData.WavesMelee, typeId) >= 0) + melee.Add(monster); + else + ranged.Add(monster); + } + melee.AddRange(ranged); + return melee; + } + } +} diff --git a/Assets/Luneraria/Core/Content/PlannedHeroes.cs b/Assets/Luneraria/Core/Content/PlannedHeroes.cs new file mode 100644 index 0000000..a280b43 --- /dev/null +++ b/Assets/Luneraria/Core/Content/PlannedHeroes.cs @@ -0,0 +1,104 @@ +using System.Collections.Generic; + +namespace Luneraria.Core +{ + /// How a hero power is triggered. + public enum PowerTrigger + { + /// Automatic in combat (like the existing abilities). + Automatic, + /// Released by the player through the command menu during combat. + Command, + } + + /// + /// Description of an ability or ultimate. Numbers are balance parameters; null means "not + /// decided yet". Nothing here is simulated until a hero is activated in a hero phase. + /// + public sealed class HeroPower + { + public string Id = ""; + public string Name = ""; + public string Text = ""; + public PowerTrigger Trigger = PowerTrigger.Automatic; + /// Effect family in the rules vocabulary (slow, splash, damage buff, dot, ...). + public string Effect = ""; + public double? Radius; + public double? Duration; + public double? Amount; + public int? MaxTargets; + public double? Cooldown; + /// Stun length for powers that stun (a new rule, see docs/port/U1-RULES.md). + public double? Stun; + /// Open design questions of this power. + public string Note = ""; + } + + /// A planned hero from the owner's hero concept (docs/luneraria/HELDEN-KONZEPT.md in the reference). + public sealed class PlannedHero + { + public string Id = ""; + public string Name = ""; + public string People = ""; + public string Role = ""; + /// Row in the formation, as for troops: front, melee, ranged, splash or support. + public string FormationRole = ""; + public string Weapon = ""; + public string Look = ""; + public HeroPower Ability = new HeroPower(); + public HeroPower Ultimate = new HeroPower(); + public string Goal = ""; + /// False until a hero phase implements and balances the kit; not purchasable before. + public bool Active; + } + + /// + /// The four heroes the owner defined for Champions of Luneraria (Lucy, Ghaliga, Siegfried, + /// Feena). Part of the data model so HUD and command menu can be designed against them; + /// the match still offers only the three reference heroes (ContentData.Heroes), so the port + /// keeps behavioural parity. Ultimates are released through the command menu; the rest of + /// the combat stays automatic. + /// + public static class PlannedHeroes + { + public static readonly IReadOnlyList All = new List + { + new PlannedHero + { + Id = "lucy", Name = "Lucy", People = "Dunkelelfe", Role = "Kontrolle / Fernkampf", FormationRole = "ranged", Weapon = "Bogen", + Look = "Lange weiße Haare, grüne Augen, dunkle Haut, dunkle Lederrüstung mit dunkelblauen Akzenten, frostige Nachtästhetik.", + Ability = new HeroPower { Id = "frostpfeile", Name = "Frostpfeile", Text = "Treffer verlangsamen Gegner.", Effect = "movement_slow" }, + Ultimate = new HeroPower { Id = "multischuss", Name = "Multischuss", Text = "Mehrere Pfeile auf mehrere Ziele; Kontrolle und Flächendruck statt rohem Burst.", + Trigger = PowerTrigger.Command, Effect = "multi_target_volley" }, + Goal = "Gefährliche Gegnerwellen verlangsamen und Formationen stören.", + }, + new PlannedHero + { + Id = "ghaliga", Name = "Ghaliga", People = "Zwerg", Role = "Frontkämpfer / Bruiser", FormationRole = "front", Weapon = "Axt", + Look = "Rote Haare, langer Bart, blaue Augen, goldene Zwergenrüstung, schwere robuste Silhouette.", + Ability = new HeroPower { Id = "wirbelhieb", Name = "Wirbelhieb", Text = "Flächenangriff um ihn herum.", Effect = "splash_around_self" }, + Ultimate = new HeroPower { Id = "versteinerung", Name = "Versteinerung", Text = "Absorbiert massiv Schaden und wird extrem zäh.", + Trigger = PowerTrigger.Command, Effect = "shield_and_reduction", Note = "Bindungs-/Aggroeffekt optional: wäre eine neue Zielwahlregel." }, + Goal = "Front halten, Gegner binden, Wellen abfangen.", + }, + new PlannedHero + { + Id = "siegfried", Name = "Siegfried", People = "Mensch", Role = "Anführer / Frontkämpfer / Support", FormationRole = "front", Weapon = "Schwert (gold-blau)", + Look = "Kurze blonde Haare, blaue Augen, goldene Paladinrüstung.", + Ability = new HeroPower { Id = "schlachtruf", Name = "Schlachtruf", Text = "Stärkt nahe Verbündete.", Effect = "damage" }, + Ultimate = new HeroPower { Id = "excalibur", Name = "Excalibur", Text = "Großer kritischer Flächenangriff mit kurzer Betäubung; trifft nicht die ganze Karte.", + Trigger = PowerTrigger.Command, Effect = "area_strike_stun", Note = "Wirkbereich (Radius) und Betäubungsdauer sind Balanceparameter; Betäubung ist eine neue Regel." }, + Goal = "Verbündete stärken und kritische Kämpfe drehen.", + }, + new PlannedHero + { + Id = "feena", Name = "Feena", People = "Waldelfe", Role = "Fernkampf-DPS / Boss- und Elitejägerin", FormationRole = "ranged", Weapon = "Bogen", + Look = "Lange rote Haare, grüne Augen, grün-braune Lederrüstung, flinke naturverbundene Schützin.", + Ability = new HeroPower { Id = "giftpfeile", Name = "Giftpfeile", Text = "Schaden über Zeit.", Effect = "dot" }, + Ultimate = new HeroPower { Id = "turbopfeile", Name = "Turbopfeile", Text = "Stark erhöhtes Angriffstempo für kurze Zeit.", + Trigger = PowerTrigger.Command, Effect = "attack_speed", Note = "Das Angriffstempo ist heute auf +50 % gedeckelt; das Ultimate braucht eine Ausnahme oder einen höheren Deckel." }, + Goal = "Hoher anhaltender Fernkampfschaden, besonders gegen starke Einzelziele.", + }, + }; + } +} diff --git a/Assets/Luneraria/Core/Luneraria.Core.asmdef b/Assets/Luneraria/Core/Luneraria.Core.asmdef new file mode 100644 index 0000000..d7cf9f9 --- /dev/null +++ b/Assets/Luneraria/Core/Luneraria.Core.asmdef @@ -0,0 +1,14 @@ +{ + "name": "Luneraria.Core", + "rootNamespace": "Luneraria.Core", + "references": [], + "includePlatforms": [], + "excludePlatforms": [], + "allowUnsafeCode": false, + "overrideReferences": false, + "precompiledReferences": [], + "autoReferenced": true, + "defineConstraints": [], + "versionDefines": [], + "noEngineReferences": true +} diff --git a/Assets/Luneraria/Core/Model/GdMath.cs b/Assets/Luneraria/Core/Model/GdMath.cs new file mode 100644 index 0000000..21f8713 --- /dev/null +++ b/Assets/Luneraria/Core/Model/GdMath.cs @@ -0,0 +1,83 @@ +using System; +using System.Collections.Generic; + +namespace Luneraria.Core +{ + /// + /// Scalar helpers with the exact semantics of the GDScript built-ins the rules used + /// (clampf, maxf, minf, roundf, floori, ceili, is_equal_approx). Doubles throughout. + /// + public static class GdMath + { + public const double CmpEpsilon = 0.00001; + + public static double Clamp(double value, double low, double high) + { + return value < low ? low : (value > high ? high : value); + } + + public static int Clamp(int value, int low, int high) + { + return value < low ? low : (value > high ? high : value); + } + + /// Godot's MAX macro: (a > b) ? a : b. + public static double Max(double a, double b) + { + return a > b ? a : b; + } + + /// Godot's MIN macro: (a < b) ? a : b. + public static double Min(double a, double b) + { + return a < b ? a : b; + } + + public static int Max(int a, int b) { return a > b ? a : b; } + + public static int Min(int a, int b) { return a < b ? a : b; } + + public static int FloorI(double value) { return (int)Math.Floor(value); } + + public static int CeilI(double value) { return (int)Math.Ceiling(value); } + + /// roundf: half away from zero (C round), not banker's rounding. + public static double Round(double value) + { + return Math.Round(value, MidpointRounding.AwayFromZero); + } + + public static bool IsEqualApprox(double a, double b) + { + if (a == b) + return true; + double tolerance = CmpEpsilon * Math.Abs(a); + if (tolerance < CmpEpsilon) + tolerance = CmpEpsilon; + return Math.Abs(a - b) < tolerance; + } + + /// GDScript atan2(y, x) on doubles. + public static double Atan2(double y, double x) { return Math.Atan2(y, x); } + + /// + /// Stable insertion sort with a "less than" predicate. Every comparator of the rules is + /// a strict order on distinct unit ids or sequence numbers, so the result is unique; + /// stability keeps it deterministic even for near ties. + /// + public static void SortStable(List list, Func less) + { + for (int i = 1; i < list.Count; i++) + { + T item = list[i]; + int j = i - 1; + while (j >= 0 && less(item, list[j])) + { + list[j + 1] = list[j]; + j--; + } + list[j + 1] = item; + } + } + } +} diff --git a/Assets/Luneraria/Core/Model/OrderedMap.cs b/Assets/Luneraria/Core/Model/OrderedMap.cs new file mode 100644 index 0000000..4348b46 --- /dev/null +++ b/Assets/Luneraria/Core/Model/OrderedMap.cs @@ -0,0 +1,97 @@ +using System; +using System.Collections; +using System.Collections.Generic; + +namespace Luneraria.Core +{ + /// + /// Map with a defined iteration order: insertion order; removing a key keeps the order of + /// the others and a key added again goes to the end. The rules iterate buildings, effects + /// and damage-over-time entries; with this map that order never depends on hashing or on + /// the history of a Dictionary (docs/port/U1-RULES.md, determinism). + /// + public sealed class OrderedMap : IEnumerable> + { + readonly Dictionary _index = new Dictionary(); + readonly List _keys = new List(); + readonly List _values = new List(); + + public int Count { get { return _keys.Count; } } + public IReadOnlyList Keys { get { return _keys; } } + public IReadOnlyList Values { get { return _values; } } + + public bool ContainsKey(TKey key) { return _index.ContainsKey(key); } + + public TValue this[TKey key] + { + get { return _values[_index[key]]; } + set + { + int at; + if (_index.TryGetValue(key, out at)) + { + _values[at] = value; + return; + } + _index[key] = _keys.Count; + _keys.Add(key); + _values.Add(value); + } + } + + public bool TryGetValue(TKey key, out TValue value) + { + int at; + if (_index.TryGetValue(key, out at)) + { + value = _values[at]; + return true; + } + value = default(TValue); + return false; + } + + public TValue GetValueOrDefault(TKey key, TValue fallback) + { + int at; + return _index.TryGetValue(key, out at) ? _values[at] : fallback; + } + + public bool Remove(TKey key) + { + int at; + if (!_index.TryGetValue(key, out at)) + return false; + _keys.RemoveAt(at); + _values.RemoveAt(at); + _index.Remove(key); + for (int i = at; i < _keys.Count; i++) + _index[_keys[i]] = i; + return true; + } + + public void Clear() + { + _index.Clear(); + _keys.Clear(); + _values.Clear(); + } + + /// Copy in the same order; values are copied with the given function. + public OrderedMap Clone(Func copy = null) + { + var result = new OrderedMap(); + for (int i = 0; i < _keys.Count; i++) + result[_keys[i]] = copy != null ? copy(_values[i]) : _values[i]; + return result; + } + + public IEnumerator> GetEnumerator() + { + for (int i = 0; i < _keys.Count; i++) + yield return new KeyValuePair(_keys[i], _values[i]); + } + + IEnumerator IEnumerable.GetEnumerator() { return GetEnumerator(); } + } +} diff --git a/Assets/Luneraria/Core/Model/Vec2.cs b/Assets/Luneraria/Core/Model/Vec2.cs new file mode 100644 index 0000000..56faf4b --- /dev/null +++ b/Assets/Luneraria/Core/Model/Vec2.cs @@ -0,0 +1,143 @@ +using System; + +namespace Luneraria.Core +{ + /// + /// Ground vector (x, z) with 32-bit components and plain single-precision arithmetic, like + /// Godot's Vector2 (tools/godot-golden/float_probe.gd: 4000 of 4000 samples identical). + /// Scalars of the rules are doubles; they are rounded to float where they meet a vector. + /// Matching Godot's arithmetic keeps the golden comparisons tight; the product requirement + /// is determinism on one machine, not identical bits across platforms (docs/port/U1-RULES.md). + /// + [Serializable] + public struct Vec2 : IEquatable + { + public float X; + public float Y; + + public static readonly Vec2 Zero = new Vec2(0f, 0f); + public static readonly Vec2 Right = new Vec2(1f, 0f); + public static readonly Vec2 Left = new Vec2(-1f, 0f); + + public Vec2(float x, float y) + { + X = x; + Y = y; + } + + /// From doubles: each component rounded to float. + public Vec2(double x, double y) + { + X = (float)x; + Y = (float)y; + } + + public static Vec2 operator +(Vec2 a, Vec2 b) { return new Vec2(a.X + b.X, a.Y + b.Y); } + public static Vec2 operator -(Vec2 a, Vec2 b) { return new Vec2(a.X - b.X, a.Y - b.Y); } + public static Vec2 operator -(Vec2 a) { return new Vec2(-a.X, -a.Y); } + + public static Vec2 operator *(Vec2 a, double s) + { + float f = (float)s; + return new Vec2(a.X * f, a.Y * f); + } + + public static Vec2 operator *(double s, Vec2 a) + { + float f = (float)s; + return new Vec2(f * a.X, f * a.Y); + } + + public static Vec2 operator /(Vec2 a, double s) + { + float f = (float)s; + return new Vec2(a.X / f, a.Y / f); + } + + public static bool operator ==(Vec2 a, Vec2 b) { return a.X == b.X && a.Y == b.Y; } + public static bool operator !=(Vec2 a, Vec2 b) { return !(a == b); } + + public float Length() { return MathF.Sqrt(X * X + Y * Y); } + + public float LengthSquared() { return X * X + Y * Y; } + + public float DistanceTo(Vec2 p) + { + float dx = X - p.X; + float dy = Y - p.Y; + return MathF.Sqrt(dx * dx + dy * dy); + } + + public float DistanceSquaredTo(Vec2 p) + { + float dx = X - p.X; + float dy = Y - p.Y; + return dx * dx + dy * dy; + } + + public float Dot(Vec2 p) { return X * p.X + Y * p.Y; } + + public Vec2 Normalized() + { + float l = X * X + Y * Y; + if (l != 0f) + { + l = MathF.Sqrt(l); + return new Vec2(X / l, Y / l); + } + return this; + } + + /// from + (to - from) * weight per component, weight rounded to float. + public Vec2 Lerp(Vec2 to, double weight) + { + float w = (float)weight; + return new Vec2(X + (to.X - X) * w, Y + (to.Y - Y) * w); + } + + public Vec2 LimitLength(double length) + { + float limit = (float)length; + float l = Length(); + Vec2 v = this; + if (l > 0f && limit < l) + { + v.X /= l; + v.Y /= l; + v.X *= limit; + v.Y *= limit; + } + return v; + } + + public Vec2 Rotated(double angle) + { + float a = (float)angle; + float sine = MathF.Sin(a); + float cosi = MathF.Cos(a); + return new Vec2(X * cosi - Y * sine, X * sine + Y * cosi); + } + + public bool Equals(Vec2 other) { return X.Equals(other.X) && Y.Equals(other.Y); } + public override bool Equals(object obj) { return obj is Vec2 other && Equals(other); } + public override int GetHashCode() { return (X.GetHashCode() * 397) ^ Y.GetHashCode(); } + public override string ToString() { return "(" + X.ToString("R", System.Globalization.CultureInfo.InvariantCulture) + ", " + Y.ToString("R", System.Globalization.CultureInfo.InvariantCulture) + ")"; } + } + + /// Integer grid cell for the spatial buckets of a combat step. + public struct Vec2I : IEquatable + { + public int X; + public int Y; + + public Vec2I(int x, int y) + { + X = x; + Y = y; + } + + public bool Equals(Vec2I other) { return X == other.X && Y == other.Y; } + public override bool Equals(object obj) { return obj is Vec2I other && Equals(other); } + public override int GetHashCode() { return (X * 73856093) ^ (Y * 19349663); } + } +} diff --git a/Assets/Luneraria/Core/Simulation/LuneBot.cs b/Assets/Luneraria/Core/Simulation/LuneBot.cs new file mode 100644 index 0000000..44d9c9f --- /dev/null +++ b/Assets/Luneraria/Core/Simulation/LuneBot.cs @@ -0,0 +1,267 @@ +using System.Collections.Generic; + +namespace Luneraria.Core +{ + /// + /// Bot planner (reference: lune_bot.gd). Plans through LuneMatch.Submit exactly like a + /// human: same costs, caps and phase. Reads only public state (committed buildings, round, + /// boss state, announcements) and its own draft, never other players' drafts. No randomness. + /// + public static class LuneBot + { + /// Boss hunters attack from this Lanchester ratio on; each failed own attempt multiplies it. + public const double BossBar = 1.35; + public const double BossBarStep = 1.25; + + public static string ProfileFor(LuneMatch match, int slot) + { + // A match may fix the profile per slot (balance runs); otherwise a seed-based rotation. + if (match.BotProfiles.Count == 6) + return match.BotProfiles[slot]; + IReadOnlyList names = ContentData.BotProfiles.Keys; + return names[(slot * 7 + match.SeedValue) % names.Count]; + } + + public static void Plan(LuneMatch match, int slot, string profileName = "") + { + string name = string.IsNullOrEmpty(profileName) ? ProfileFor(match, slot) : profileName; + BotProfile profile = ContentData.BotProfiles[name]; + Player player = match.Players[slot]; + List ids = match.BaseIds(player.Bund); + var roles = new Dictionary(); + foreach (string id in ids) + roles[match.RoleOf(id)] = id; + PlanHero(match, slot, profile); + // Items and champions are planned before the army so the roster cannot drain the reserve. + PlanItems(match, slot, profile, 110); + PlanChampion(match, slot, profile); + for (int guard = 0; guard < 40; guard++) + { + List roster = player.Draft.Roster; + bool acted = false; + if (roster.Count >= profile.UpgradeFrom || roster.Count >= match.Balance.SupplyCap) + acted = TryUpgrade(match, slot, roster); + if (!acted && roster.Count < match.Balance.SupplyCap) + { + string role = NeededRole(match, roster, profile); + string lane = player.Lane; + // Deterministic help cadence (lane offset, not shared randomness) keeps mirror matches fair. + if (profile.SupportLane > 0.0) + { + int every = GdMath.Max(2, (int)GdMath.Round(1.0 / GdMath.Max(0.1, profile.SupportLane))); + int laneIndex = LuneMap.LaneIndex(player.Lane); + if ((match.RoundNumber + laneIndex) % every == 0) + lane = WeakestLane(match, player.Team); + } + acted = match.Submit(slot, Command.Buy(roles[role], lane)).Ok; + } + if (!acted && roster.Count < profile.UpgradeFrom) + acted = TryUpgrade(match, slot, roster); + if (!acted) + break; + } + PlanBoss(match, slot, profile); + match.SetReady(slot); + } + + static void PlanHero(LuneMatch match, int slot, BotProfile profile) + { + Player player = match.Players[slot]; + HeroState hero = player.Draft.Hero; + if (hero == null) + { + if (match.RoundNumber >= profile.HeroRound) + match.Submit(slot, Command.HeroBuy(profile.Hero)); + return; + } + int level = LuneContent.LevelFor(hero.Xp); + for (int tier = 0; tier < LuneContent.TalentLevels.Length; tier++) + { + if (hero.Talents.Count == tier && level >= LuneContent.TalentLevels[tier]) + match.Submit(slot, Command.Talent(tier, profile.TalentChoices[tier])); + } + } + + static void PlanItems(LuneMatch match, int slot, BotProfile profile, int reserve) + { + HeroState hero = match.Players[slot].Draft.Hero; + if (hero == null || hero.Items.Count >= LuneContent.ItemSlots) + return; + foreach (string itemId in profile.Items) + { + if (hero.Items.Contains(itemId)) + continue; + // Keep a reserve so the army still grows; one purchase per planning. + if (match.Players[slot].Draft.Gold >= ContentData.Items[itemId].Cost + reserve) + { + if (match.Submit(slot, Command.ItemBuy(itemId)).Ok) + return; + } + } + } + + static void PlanChampion(LuneMatch match, int slot, BotProfile profile) + { + string champion = profile.Champion; + if (string.IsNullOrEmpty(champion) || match.RoundNumber < 3) + return; + Player player = match.Players[slot]; + // At most one booked champion still on its way; bookings last exactly one round. + foreach (Booking booking in player.Bookings) + { + if (booking.DeployRound > match.RoundNumber) + return; + } + BotMemory memory; + if (!match.BotMemory.TryGetValue(slot, out memory)) + memory = new BotMemory(); + if ((memory.HasChampionRound ? memory.ChampionRound : 0) + 2 >= match.RoundNumber) + return; + if (player.Draft.Gold < ContentData.Champions[champion].Cost + 40) + return; + if (match.Submit(slot, Command.ChampionBook(champion, player.Lane)).Ok) + { + memory.HasChampionRound = true; + memory.ChampionRound = match.RoundNumber; + match.BotMemory[slot] = memory; + } + } + + /// + /// Only boss-hunting bots go to the grotto, and only with a strong own army; the boss + /// state and lock are public information. + /// + static void PlanBoss(LuneMatch match, int slot, BotProfile profile) + { + Player player = match.Players[slot]; + BossClaim claim = match.Boss.Claim; + if (claim != null && claim.ChooserSlot == slot && claim.DeployRound == match.RoundNumber) + { + string lane = WeakestLane(match, 1 - player.Team); + match.Submit(slot, Command.BossLaneChoice(lane)); + } + if (!profile.HuntsBoss || match.RoundNumber < profile.BossFrom || !match.GrottoAvailable()) + return; + List roster = player.Draft.Roster; + if (roster.Count < profile.BossTroops) + return; + var picks = new List(roster); + GdMath.SortStable(picks, (a, b) => a.Invested == b.Invested ? a.Seq < b.Seq : a.Invested > b.Invested); + int keep = GdMath.Min(profile.BossTroops - 1, picks.Count); + picks.RemoveRange(keep, picks.Count - keep); + HeroState hero = player.Draft.Hero; + // The boss formula is public. Lanchester estimate: total HP x total damage of the + // expedition against the boss. A failed own attempt (public outcome) raises the bar. + double totalHp = 0.0; + double totalDamage = 0.0; + foreach (RosterEntry entry in picks) + { + UnitDef definition = DataCatalog.GetUnit(entry.TypeId); + totalHp += definition.MaxHp; + totalDamage += definition.Damage; + } + if (hero != null) + { + UnitDef heroDef = LuneContent.HeroDefinition(hero); + totalHp += heroDef.MaxHp; + totalDamage += heroDef.Damage * (1.0 + heroDef.DamageBonus); + } + UnitDef bossDef = LuneContent.BossDefinition(match.RoundNumber, match.Balance, false); + double ratio = totalHp * totalDamage / (bossDef.MaxHp * bossDef.Damage); + BotMemory memory; + if (match.BotMemory.TryGetValue(slot, out memory)) + { + // Reference behaviour (docs/port/U1-RULES.md, R1): a bot whose memory only holds a + // champion booking fails to read the boss fields and stops planning the grotto here. + if (!memory.HasBossFields) + return; + } + else + { + memory = new BotMemory { HasBossFields = true, Bar = BossBar, Sent = 0 }; + } + foreach (BossLogEntry ev in match.BossLog) + { + if (ev.Round == memory.Sent && ev.Event == "failed") + { + memory.Bar = memory.Bar * BossBarStep; + memory.Sent = 0; + } + } + match.BotMemory[slot] = memory; + if (ratio < memory.Bar) + return; + memory.Sent = match.RoundNumber; + foreach (RosterEntry entry in picks) + match.Submit(slot, Command.Assign(entry.Uid, LuneMatch.Grotto)); + if (hero != null) + match.Submit(slot, Command.Assign(hero.Uid, LuneMatch.Grotto)); + } + + static string NeededRole(LuneMatch match, List roster, BotProfile profile) + { + var counts = new Dictionary(); + foreach (RosterEntry entry in roster) + { + string role = match.RoleOf(entry.TypeId); + int current; + counts.TryGetValue(role, out current); + counts[role] = current + 1; + } + string best = "front"; + double bestGap = double.NegativeInfinity; + foreach (string role in ContentData.RowOrder) + { + int have; + counts.TryGetValue(role, out have); + double gap = profile.Share(role) * (double)(roster.Count + 1) - (double)have; + if (gap > bestGap + 0.0001) + { + best = role; + bestGap = gap; + } + } + return best; + } + + static bool TryUpgrade(LuneMatch match, int slot, List roster) + { + string bestUid = ""; + int bestSeq = 1 << 30; + int bestCost = 1 << 30; + foreach (RosterEntry entry in roster) + { + string upgrade = DataCatalog.UpgradeOf(entry.TypeId); + if (upgrade.Length == 0) + continue; + int cost = DataCatalog.CostOf(upgrade); + if (cost < bestCost || (cost == bestCost && entry.Seq < bestSeq)) + { + bestCost = cost; + bestSeq = entry.Seq; + bestUid = entry.Uid; + } + } + if (bestUid.Length == 0) + return false; + return match.Submit(slot, Command.Upgrade(bestUid)).Ok; + } + + /// First lane (top, mid, bot) with the fewest standing lane towers of a team. + public static string WeakestLane(LuneMatch match, int team) + { + string weakest = "mid"; + int fewest = 99; + foreach (string lane in LuneMap.Lanes) + { + int towers = match.TowersAlive(team, lane); + if (towers < fewest) + { + fewest = towers; + weakest = lane; + } + } + return weakest; + } + } +} diff --git a/Assets/Luneraria/Core/Simulation/LuneCombat.cs b/Assets/Luneraria/Core/Simulation/LuneCombat.cs new file mode 100644 index 0000000..de20588 --- /dev/null +++ b/Assets/Luneraria/Core/Simulation/LuneCombat.cs @@ -0,0 +1,973 @@ +using System; +using System.Collections.Generic; + +namespace Luneraria.Core +{ + /// A death recorded during combat; the settlement pays bounties and XP from it. + public sealed class CombatEvent + { + public int Serial; + public int Step; + public double Time; + public int Team; + public string Lane = ""; + public string Zone = "lane"; + /// Kind of the unit that died. + public string Kind = ""; + public int UnitId; + public string DefId = ""; + public int Bounty; + public int OwnerSlot = -1; + public string PersistentUid = ""; + public string BuildingId = ""; + public int Xp; + public List XpHeroes = new List(); + } + + /// + /// One automatic combat phase on all three lanes (reference: lune_combat.gd). Every step + /// first gathers targets, movement, hits, heals and effects from the state at the start of + /// the step, then applies them together, so processing order never decides who strikes + /// first. Deaths of a step resolve together; two Ancients falling in one step is a draw. + /// Iteration happens only over lists in spawn order and over insertion-ordered maps. + /// + public sealed class LuneCombat + { + public const int Neutral = 2; + /// Units without a target look for one every RETARGET steps, staggered by TeamIndex. + public const int Retarget = 4; + const double Cell = 4.0; + + public readonly LuneMap Map; + public readonly LuneBalance Balance; + public readonly int RoundNumber; + public readonly List Units = new List(); + public readonly OrderedMap Buildings = new OrderedMap(); + public double Elapsed; + public int Steps; + public bool Finished; + /// cleared, timeout or core. + public string EndReason = ""; + public readonly List DestroyedCores = new List(); + public readonly List Events = new List(); + public LuneUnit GrottoBoss; + public bool GrottoResolved = true; + public int GrottoClaimTeam = -1; + public int GrottoActiveTeam = -1; + /// none, success or failed. + public string GrottoOutcome = "none"; + + int _nextId = 1; + readonly int[] _teamCount = new int[3]; + int _eventSerial; + readonly Dictionary _pendingDamage = new Dictionary(); + readonly Dictionary _pendingHeal = new Dictionary(); + readonly List _pendingEffects = new List(); + readonly List _pendingDots = new List(); + readonly List _pendingShields = new List(); + // Per-step caches: building gates, march limits, spatial buckets of mobile units. + readonly Dictionary _attackable = new Dictionary(); + readonly Dictionary _limits = new Dictionary(); + readonly Dictionary>[] _grid = { new Dictionary>(), new Dictionary>(), new Dictionary>() }; + + struct PendingEffect + { + public LuneUnit Unit; + public string Family; + public string Kind; + public double Amount; + public double Duration; + } + + struct PendingDot + { + public LuneUnit Unit; + public string Family; + public double Damage; + public double Duration; + public int AttackType; + } + + struct PendingShield + { + public LuneUnit Unit; + public double Amount; + public double Duration; + } + + public LuneCombat(LuneMap map, LuneBalance balance, int roundNumber) + { + Map = map; + Balance = balance; + RoundNumber = roundNumber; + } + + // ---------------------------------------------------------------- setup + public LuneUnit AddBuilding(BuildingDef definition, double hp) + { + var unit = new LuneUnit(); + unit.Id = _nextId++; + unit.Kind = definition.Tier == "core" ? "core" : "tower"; + unit.Team = definition.Team; + unit.Lane = definition.Lane; + unit.BuildingId = definition.Id; + unit.TeamIndex = _teamCount[unit.Team]++; + unit.Def = new UnitDef { Id = definition.Id, DisplayName = definition.Id, MaxHp = definition.MaxHp, Damage = definition.Damage, + AttackRange = definition.Range, AttackType = 1, ArmorType = 1, Speed = 0.0, Ability = "", Bounty = definition.Bounty, Tier = definition.Tier }; + unit.Position = definition.Position; + unit.PreviousPosition = unit.Position; + unit.MaxHp = definition.MaxHp; + unit.Hp = GdMath.Clamp(hp, 0.0, unit.MaxHp); + unit.Alive = unit.Hp > 0.0; + Units.Add(unit); + Buildings[unit.BuildingId] = unit; + return unit; + } + + public LuneUnit Spawn(string kind, int team, string lane, UnitDef definition, double progress, double lateral, int slot = -1, string uid = "") + { + var unit = new LuneUnit(); + unit.Id = _nextId++; + unit.Kind = kind; + unit.Team = team; + unit.Lane = lane; + unit.Def = definition; + unit.OwnerSlot = slot; + unit.PersistentUid = uid ?? ""; + unit.TeamIndex = _teamCount[team]++; + unit.Progress = progress; + unit.Lateral = lateral; + unit.Position = Map.LanePoint(team, lane, progress, lateral); + unit.PreviousPosition = unit.Position; + Vec2 forward = Map.LaneForward(team, lane, progress); + unit.Facing = GdMath.Atan2(forward.X, forward.Y); + unit.MaxHp = definition.MaxHp; + unit.Hp = unit.MaxHp; + StartAbility(unit); + Units.Add(unit); + return unit; + } + + public LuneUnit SpawnAt(string kind, int team, string zone, UnitDef definition, Vec2 at, int slot = -1, string uid = "") + { + LuneUnit unit = Spawn(kind, team, "mid", definition, 0.0, 0.0, slot, uid); + unit.Zone = zone; + unit.Lane = zone; + unit.Position = at; + unit.PreviousPosition = at; + return unit; + } + + public LuneUnit AddGrottoBoss(UnitDef definition) + { + GrottoBoss = SpawnAt("boss", Neutral, LuneMap.GrottoZone, definition, Map.GrottoBossPoint()); + GrottoBoss.Dormant = true; + GrottoResolved = false; + return GrottoBoss; + } + + public Dictionary AliveMap() + { + var result = new Dictionary(); + IReadOnlyList values = Buildings.Values; + for (int i = 0; i < values.Count; i++) + result[values[i].BuildingId] = values[i].Alive; + return result; + } + + public bool BuildingAttackable(LuneUnit unit, Dictionary gates) + { + if (!unit.Alive) + return false; + bool cached; + if (_attackable.TryGetValue(unit.BuildingId, out cached)) + return cached; + return LuneMap.IsAttackable(Map.BuildingDef(unit.BuildingId), gates); + } + + void PrepareCaches(List living, Dictionary gates) + { + _attackable.Clear(); + IReadOnlyList buildings = Buildings.Values; + for (int i = 0; i < buildings.Count; i++) + _attackable[buildings[i].BuildingId] = LuneMap.IsAttackable(Map.BuildingDef(buildings[i].BuildingId), gates); + _limits.Clear(); + for (int team = 0; team < 2; team++) + { + foreach (string lane in LuneMap.Lanes) + { + LanePath path = Map.LanePaths[lane]; + double limit = path.Length; + for (int i = 0; i < buildings.Count; i++) + { + LuneUnit building = buildings[i]; + if (building.Alive && building.Kind == "tower" && building.Team != team && building.Lane == lane) + limit = GdMath.Min(limit, path.Length - Map.BuildingDef(building.BuildingId).Progress - 1.5); + } + _limits[team * 3 + LuneMap.LaneIndex(lane)] = limit; + } + } + for (int side = 0; side < 3; side++) + _grid[side].Clear(); + foreach (LuneUnit unit in living) + { + if (!unit.IsMobile()) + continue; + var key = new Vec2I(GdMath.FloorI(unit.Position.X / Cell), GdMath.FloorI(unit.Position.Y / Cell)); + List bucket; + if (!_grid[unit.Team].TryGetValue(key, out bucket)) + { + bucket = new List(); + _grid[unit.Team][key] = bucket; + } + bucket.Add(unit); + } + } + + public static int[] HostileTeams(int team) + { + return team == Neutral ? new[] { 0, 1 } : new[] { 1 - team, Neutral }; + } + + /// Mobile units of the given teams in the cells around a point; the caller checks distance. + List NearMobile(Vec2 center, double radius, int[] teams) + { + var result = new List(); + int reach = GdMath.CeilI(radius / Cell); + int cx = GdMath.FloorI(center.X / Cell); + int cy = GdMath.FloorI(center.Y / Cell); + foreach (int side in teams) + { + Dictionary> cells = _grid[side]; + if (cells.Count == 0) + continue; + for (int dx = -reach; dx <= reach; dx++) + { + for (int dy = -reach; dy <= reach; dy++) + { + List bucket; + if (cells.TryGetValue(new Vec2I(cx + dx, cy + dy), out bucket)) + result.AddRange(bucket); + } + } + } + return result; + } + + // ---------------------------------------------------------------- step + public void Step() + { + if (Finished) + return; + double dt = Balance.SimStep; + Elapsed += dt; + Steps += 1; + _pendingDamage.Clear(); + _pendingHeal.Clear(); + _pendingEffects.Clear(); + _pendingDots.Clear(); + _pendingShields.Clear(); + Dictionary gates = AliveMap(); + var living = new List(); + foreach (LuneUnit unit in Units) + { + if (unit.Alive) + { + living.Add(unit); + unit.PreviousPosition = unit.Position; + } + } + PrepareCaches(living, gates); + foreach (LuneUnit unit in living) + { + double dot = unit.AdvanceStatus(dt); + if (dot > 0.0) + QueueDamage(unit, dot, gates); + } + foreach (LuneUnit unit in living) + { + if (unit.IsMobile()) + AbilityStep(unit, living); + } + foreach (LuneUnit unit in living) + { + if (unit.IsMobile() || unit.Kind == "tower") + { + bool keep = unit.Target != null && unit.Target.Alive; + if (keep || (Steps + unit.TeamIndex) % Retarget == 0) + unit.Target = ChooseTarget(unit, living, gates); + } + } + var moves = new Dictionary>(); + foreach (LuneUnit unit in living) + { + if (unit.IsMobile()) + moves[unit.Id] = PlanMove(unit, living, dt); + } + foreach (LuneUnit unit in living) + { + KeyValuePair plan; + if (!moves.TryGetValue(unit.Id, out plan)) + continue; + Vec2 next = plan.Key; + Vec2 heading = next - unit.Position; + unit.Position = next; + if (heading.LengthSquared() > 0.000001) + unit.Facing = GdMath.Atan2(heading.X, heading.Y); + if (unit.Zone == "lane") + UpdateProgress(unit, plan.Value); + } + foreach (LuneUnit unit in living) + Attack(unit, living, gates, dt); + foreach (LuneUnit unit in living) + { + double heal; + if (_pendingHeal.TryGetValue(unit.Id, out heal)) + unit.Heal(heal); + } + foreach (PendingShield entry in _pendingShields) + entry.Unit.GrantShield(entry.Amount, entry.Duration); + foreach (PendingEffect entry in _pendingEffects) + entry.Unit.ApplyEffect(entry.Family, entry.Kind, entry.Amount, entry.Duration); + foreach (PendingDot entry in _pendingDots) + entry.Unit.ApplyDot(entry.Family, entry.Damage, entry.Duration, entry.AttackType); + foreach (LuneUnit unit in living) + { + double damage; + if (_pendingDamage.TryGetValue(unit.Id, out damage)) + unit.Take(damage); + } + foreach (LuneUnit unit in living) + { + if (unit.Hp <= 0.0 && unit.Alive) + { + unit.Alive = false; + unit.DeathTime = Elapsed; + unit.Target = null; + RecordDeath(unit); + } + } + UpdateGrotto(); + CheckEnd(); + } + + /// Expeditions fight each other first; the boss wakes when at most one team remains. + void UpdateGrotto() + { + if (GrottoResolved || GrottoBoss == null) + return; + var teamsAlive = new List(); + foreach (LuneUnit unit in Units) + { + if (unit.Alive && unit.Zone == LuneMap.GrottoZone && unit.Team != Neutral && !teamsAlive.Contains(unit.Team)) + teamsAlive.Add(unit.Team); + } + if (GrottoBoss.Dormant && teamsAlive.Count <= 1) + { + GrottoBoss.Dormant = false; + GrottoActiveTeam = teamsAlive.Count == 1 ? teamsAlive[0] : -1; + } + if (!GrottoBoss.Alive) + { + GrottoResolved = true; + GrottoClaimTeam = GrottoActiveTeam; + GrottoOutcome = GrottoClaimTeam >= 0 ? "success" : "failed"; + } + else if (teamsAlive.Count == 0) + { + GrottoResolved = true; + GrottoOutcome = "failed"; + } + } + + void CheckEnd() + { + if (DestroyedCores.Count > 0) + { + Finished = true; + EndReason = "core"; + return; + } + bool mobileAlive = !GrottoResolved; + foreach (LuneUnit unit in Units) + { + if (unit.Alive && unit.IsMobile() && unit.Zone == "lane") + { + mobileAlive = true; + break; + } + } + if (!mobileAlive) + { + Finished = true; + EndReason = "cleared"; + } + else if (Elapsed >= Balance.CombatTimeLimit - 0.000001) + { + Finished = true; + EndReason = "timeout"; + } + } + + void RecordDeath(LuneUnit unit) + { + _eventSerial += 1; + var ev = new CombatEvent { Serial = _eventSerial, Step = Steps, Time = Elapsed, Team = unit.Team, Lane = unit.Lane, Zone = unit.Zone, + Kind = unit.Kind, UnitId = unit.Id, DefId = unit.Def.Id, Bounty = 0, OwnerSlot = unit.OwnerSlot, PersistentUid = unit.PersistentUid }; + if (unit.Kind == "monster" || unit.Kind == "champion" || unit.Kind == "boss") + { + ev.Bounty = unit.Def.Bounty; + } + else if (unit.IsBuilding()) + { + ev.Bounty = unit.Def.Bounty; + ev.BuildingId = unit.BuildingId; + if (unit.Kind == "core" && !DestroyedCores.Contains(unit.Team)) + DestroyedCores.Add(unit.Team); + } + // Participation XP: every opposing hero near the death shares it, whoever landed the hit. + int xp = 0; + switch (unit.Kind) + { + case "monster": xp = 12 + RoundNumber; break; + case "champion": xp = 30 + 2 * RoundNumber; break; + case "boss": xp = LuneContent.BossXp; break; + case "troop": + case "hero": xp = 15; break; + case "tower": + case "core": xp = LuneContent.BuildingXp; break; + } + double radius = LuneContent.XpRadius + (unit.IsBuilding() ? 2.0 : 0.0); + foreach (LuneUnit other in Units) + { + if (other.Kind == "hero" && other.Alive && other.Zone == unit.Zone && other.Team != unit.Team && other.Position.DistanceTo(unit.Position) <= radius) + ev.XpHeroes.Add(other.PersistentUid); + } + ev.Xp = xp; + Events.Add(ev); + } + + // ---------------------------------------------------------------- targeting and movement + static bool Hostile(LuneUnit unit, LuneUnit other) + { + return other.Alive && other.Team != unit.Team && other.Zone == unit.Zone && !other.Dormant && !unit.Dormant; + } + + LuneUnit ChooseTarget(LuneUnit unit, List living, Dictionary gates) + { + LuneUnit current = unit.Target; + if (current != null && Hostile(unit, current) && unit.Position.DistanceTo(current.Position) <= Balance.LeashRadius) + { + if (!current.IsBuilding() || BuildingAttackable(current, gates)) + { + if (unit.Kind != "tower" || unit.Position.DistanceTo(current.Position) <= unit.AttackRange()) + return current; + } + } + double radius = unit.Kind == "tower" ? unit.AttackRange() : Balance.AggroRadius; + LuneUnit best = null; + double bestDistance = double.PositiveInfinity; + string priority = unit.Def.Priority; + IReadOnlyList buildings = Buildings.Values; + if (priority == "building") + { + // Siege champions go for the nearest attackable building before anything else. + for (int i = 0; i < buildings.Count; i++) + { + LuneUnit building = buildings[i]; + if (Hostile(unit, building) && BuildingAttackable(building, gates)) + { + double reachDistance = unit.Position.DistanceTo(building.Position) - Balance.BuildingRadius; + if (reachDistance <= Balance.AggroRadius && reachDistance < bestDistance) + { + best = building; + bestDistance = reachDistance; + } + } + } + if (best != null) + return best; + } + foreach (LuneUnit other in NearMobile(unit.Position, radius, HostileTeams(unit.Team))) + { + if (!Hostile(unit, other)) + continue; + double d = unit.Position.DistanceTo(other.Position); + // Pressure champions treat support and ranged enemies as 6 m closer. + if (priority == "support" && (other.Role() == "support" || other.Role() == "ranged")) + d -= 6.0; + if (d <= radius && (d < bestDistance - 0.0001 || (Math.Abs(d - bestDistance) <= 0.0001 && other.Id < best.Id))) + { + best = other; + bestDistance = d; + } + } + if (best != null || unit.Kind == "tower") + return best; + // Buildings: nearby attackable ones; at the end of a lane the whole base is in reach. + for (int i = 0; i < buildings.Count; i++) + { + LuneUnit other = buildings[i]; + if (!Hostile(unit, other) || !BuildingAttackable(other, gates)) + continue; + double d = unit.Position.DistanceTo(other.Position) - Balance.BuildingRadius; + if ((d <= radius || unit.ReachedBase) && d < bestDistance) + { + best = other; + bestDistance = d; + } + } + return best; + } + + double MarchLimit(LuneUnit unit) + { + double cached; + if (_limits.TryGetValue(unit.Team * 3 + LuneMap.LaneIndex(unit.Lane), out cached)) + return cached; + LanePath path = Map.LanePaths[unit.Lane]; + double limit = path.Length; + IReadOnlyList buildings = Buildings.Values; + for (int i = 0; i < buildings.Count; i++) + { + LuneUnit building = buildings[i]; + if (building.Alive && building.Kind == "tower" && building.Team != unit.Team && building.Lane == unit.Lane) + limit = GdMath.Min(limit, path.Length - Map.BuildingDef(building.BuildingId).Progress - 1.5); + } + return limit; + } + + /// + /// Returns the next position and the marching progress. Marching advances the lane + /// parameter directly, so formation offsets cannot stall a unit on the inside of a bend. + /// + KeyValuePair PlanMove(LuneUnit unit, List living, double dt) + { + double stepLength = unit.Speed() * Balance.MarchSpeedFactor * unit.MovementFactor() * dt; + Vec2 goal = unit.Position; + double travel = 0.0; + double marched = unit.Progress; + if (unit.Target != null) + { + double reach = unit.AttackRange() + (unit.Target.IsBuilding() ? Balance.BuildingRadius : 0.0); + double gap = unit.Position.DistanceTo(unit.Target.Position) - reach; + if (gap > 0.0) + { + goal = unit.Target.Position; + travel = GdMath.Min(stepLength, gap + 0.02); + } + } + else if (unit.Zone == LuneMap.GrottoZone) + { + if (unit.Kind != "boss" && GrottoBoss != null && GrottoBoss.Alive) + { + double gapBoss = unit.Position.DistanceTo(GrottoBoss.Position) - unit.AttackRange(); + if (gapBoss > 0.0) + { + goal = GrottoBoss.Position; + travel = GdMath.Min(stepLength, gapBoss + 0.02); + } + } + } + else if (unit.Zone == "lane") + { + double limit = MarchLimit(unit); + Vec2 anchor = Map.LanePoint(unit.Team, unit.Lane, unit.Progress, unit.Lateral); + double off = unit.Position.DistanceTo(anchor); + if (off > 1.2) + { + // Rejoin the formation line after a chase before advancing again. + goal = anchor; + travel = GdMath.Min(stepLength, unit.Position.DistanceTo(anchor)); + } + else if (unit.Progress < limit - 0.01) + { + marched = GdMath.Min(unit.Progress + stepLength, limit); + goal = Map.LanePoint(unit.Team, unit.Lane, marched, unit.Lateral); + travel = unit.Position.DistanceTo(goal); + } + else if (off > 0.05) + { + goal = anchor; + travel = GdMath.Min(stepLength, unit.Position.DistanceTo(anchor)); + } + } + Vec2 next = unit.Position; + if (travel > 0.0 && goal.DistanceSquaredTo(unit.Position) > 0.000001) + next += (goal - unit.Position).Normalized() * GdMath.Min(travel, unit.Position.DistanceTo(goal)); + // Separation from allies so bodies do not stack; opponents may still close to melee range. + Vec2 push = Vec2.Zero; + foreach (LuneUnit other in NearMobile(unit.Position, 1.1, new[] { unit.Team })) + { + if (other == unit || other.Zone != unit.Zone) + continue; + Vec2 offset = unit.Position - other.Position; + double distance = offset.Length(); + if (distance < 1.1) + { + if (distance < 0.0001) + { + // Mirrored teams sidestep in mirrored directions. + offset = unit.Id < other.Id ? Vec2.Right : Vec2.Left; + if (unit.Team == 1) + offset = LuneMap.Mirror(offset); + distance = 0.001; + } + push += offset.Normalized() * (1.1 - distance) * 2.0; + } + } + next += push.LimitLength(0.9) * dt; + next.X = (float)GdMath.Clamp(next.X, -LuneMap.HalfExtent, LuneMap.HalfExtent); + next.Y = (float)GdMath.Clamp(next.Y, -LuneMap.HalfExtent, LuneMap.HalfExtent); + return new KeyValuePair(next, marched); + } + + void UpdateProgress(LuneUnit unit, double marched) + { + LanePath path = Map.LanePaths[unit.Lane]; + double limit = MarchLimit(unit); + if (unit.Target != null) + { + // After a chase the unit continues from where it now stands, never further back. + Vec2 blue = unit.Team == 0 ? unit.Position : LuneMap.Mirror(unit.Position); + marched = GdMath.Max(marched, GdMath.Min(path.Project(blue), limit)); + } + unit.Progress = GdMath.Max(unit.Progress, GdMath.Min(marched, GdMath.Max(limit, unit.Progress))); + if (unit.Progress >= path.Length - 0.6) + unit.ReachedBase = true; + } + + // ---------------------------------------------------------------- attacks + void Attack(LuneUnit unit, List living, Dictionary gates, double dt) + { + unit.InRange = false; + LuneUnit target = unit.Target; + if (target == null || !target.Alive || unit.Kind == "core") + { + unit.AttackProgress = 0.0; + return; + } + double reach = unit.AttackRange() + (target.IsBuilding() ? Balance.BuildingRadius : 0.0) + 0.035; + if (unit.Position.DistanceTo(target.Position) > reach) + { + unit.AttackProgress = 0.0; + return; + } + if (target.IsBuilding() && !BuildingAttackable(target, gates)) + { + unit.AttackProgress = 0.0; + return; + } + unit.InRange = true; + double interval = unit.Kind == "tower" ? Balance.TowerAttackInterval : 1.0; + unit.AttackProgress += dt * unit.AttackSpeedFactor() / interval; + while (unit.AttackProgress >= 1.0 - 0.000001) + { + unit.AttackProgress = GdMath.Max(0.0, unit.AttackProgress - 1.0); + unit.HitCount += 1; + unit.AttackSerial += 1; + double damage = unit.Def.Damage * (1.0 + unit.DamageBonus()); + if (unit.HitCount % 4 == 0) + { + if (unit.Ability() == "g05") + damage *= unit.HasTalent("durchschlag") ? 2.1 : 1.5; + else if (unit.Ability() == "g06") + damage *= 1.75; + } + if (unit.HitCount % 3 == 0 && unit.HasTalent("stammschlag")) + damage *= 1.6; + if (target.IsBuilding()) + damage *= unit.Def.SiegeFactor; + QueueDamage(target, target.Mitigated(damage, unit.Def.AttackType), gates); + OnHit(unit, target, living, gates); + // Item effects come last and never trigger further on-hit effects. + double itemSplash = unit.Def.ItemSplash; + if (itemSplash > 0.0) + Splash(unit, target, living, gates, itemSplash, 1.5, 2); + } + } + + public void QueueDamage(LuneUnit target, double amount, Dictionary gates) + { + if (amount <= 0.0 || !target.Alive) + return; + // The building gate applies to every source: ranged, splash, DoT and abilities. + if (target.IsBuilding() && !BuildingAttackable(target, gates)) + return; + double current; + _pendingDamage.TryGetValue(target.Id, out current); + _pendingDamage[target.Id] = current + amount; + } + + /// Damage queued for a unit in the current step (tests). + public bool HasPendingDamage(LuneUnit unit) { return _pendingDamage.ContainsKey(unit.Id); } + + void QueueHeal(LuneUnit target, double amount) + { + double current; + _pendingHeal.TryGetValue(target.Id, out current); + _pendingHeal[target.Id] = current + amount; + } + + // ---------------------------------------------------------------- abilities + void StartAbility(LuneUnit unit) + { + unit.AbilityReady = 6.0; + switch (unit.Ability()) + { + case "w03": + case "w04": + unit.AbilityReady = 5.0; + break; + case "w09": + case "w10": + unit.AbilityReady = 4.0; + break; + case "s02": + case "ch_schutz": + unit.GrantShield(unit.MaxHp * 0.15); + break; + case "e08": + unit.GrantShield(unit.MaxHp * 0.20); + break; + } + } + + List Nearby(LuneUnit unit, bool allied, Vec2 center, double radius, int maximum, LuneUnit excluded = null, bool healthPriority = false) + { + var result = new List(); + // Buildings can be splash victims; they are few, so check them directly. + List pool = NearMobile(center, radius, allied ? new[] { unit.Team } : HostileTeams(unit.Team)); + if (!allied) + { + IReadOnlyList buildings = Buildings.Values; + for (int i = 0; i < buildings.Count; i++) + pool.Add(buildings[i]); + } + foreach (LuneUnit other in pool) + { + if (!other.Alive || other == excluded || other.Zone != unit.Zone) + continue; + if ((other.Team == unit.Team) != allied || other.Dormant) + continue; + if (allied && other.IsBuilding()) + continue; + if (other.Position.DistanceTo(center) <= radius + 0.000001) + result.Add(other); + } + GdMath.SortStable(result, (a, b) => + { + if (healthPriority && !GdMath.IsEqualApprox(a.Hp / a.MaxHp, b.Hp / b.MaxHp)) + return a.Hp / a.MaxHp < b.Hp / b.MaxHp; + double ad = a.Position.DistanceTo(center); + double bd = b.Position.DistanceTo(center); + return GdMath.IsEqualApprox(ad, bd) ? a.Id < b.Id : ad < bd; + }); + if (result.Count > maximum) + result.RemoveRange(maximum, result.Count - maximum); + return result; + } + + void AddEffect(LuneUnit target, string family, string kind, double amount, double duration) + { + _pendingEffects.Add(new PendingEffect { Unit = target, Family = family, Kind = kind, Amount = amount, Duration = duration }); + } + + void AddDot(LuneUnit target, string family, double damage, double duration, int attackType) + { + _pendingDots.Add(new PendingDot { Unit = target, Family = family, Damage = damage, Duration = duration, AttackType = attackType }); + } + + void AbilityStep(LuneUnit unit, List living) + { + double regen = unit.Def.Regen; + if (regen > 0.0 && unit.Hp < unit.MaxHp) + QueueHeal(unit, unit.MaxHp * regen * Balance.SimStep); + if (unit.HasTalent("schutzwurzeln") && unit.CombatTime + 0.000001 >= unit.AuraReady) + { + foreach (LuneUnit ally in Nearby(unit, true, unit.Position, 4.0, 4)) + AddEffect(ally, "bark_guard", "reduction", 0.10, 4.5); + unit.AuraReady = unit.CombatTime + 4.0; + } + if (unit.CombatTime + 0.000001 < unit.AbilityReady) + return; + string ability = unit.Ability(); + bool success = false; + switch (ability) + { + case "w03": + case "w04": + if (unit.Hp < unit.MaxHp) + { + QueueHeal(unit, ability == "w04" ? 100.0 : 35.0); + success = true; + } + break; + case "w09": + case "w10": + { + bool upgraded = ability == "w10"; + double radius = upgraded ? 4.5 : 4.0; + int count = upgraded ? 3 : 1; + double amount = upgraded ? 80.0 : 65.0; + if (unit.HasTalent("tiefe_quelle")) + { + count = 1; + amount = 190.0; + } + else if (unit.HasTalent("weite_quelle")) + { + radius = 5.5; + count = 5; + amount = 65.0; + } + foreach (LuneUnit ally in Nearby(unit, true, unit.Position, radius, count, null, true)) + { + if (ally.Hp < ally.MaxHp) + { + QueueHeal(ally, amount); + if (unit.HasTalent("quellschild")) + _pendingShields.Add(new PendingShield { Unit = ally, Amount = 70.0, Duration = 4.0 }); + success = true; + } + } + break; + } + case "ch_schutz": + { + List allies = Nearby(unit, true, unit.Position, 4.0, 4); + foreach (LuneUnit ally in allies) + _pendingShields.Add(new PendingShield { Unit = ally, Amount = 120.0, Duration = 6.0 }); + success = allies.Count > 0; + break; + } + case "g09": + case "g10": + { + bool upgraded = ability == "g10"; + List allies = Nearby(unit, true, unit.Position, upgraded ? 4.0 : 3.0, upgraded ? 4 : 3, null, true); + foreach (LuneUnit ally in allies) + { + AddEffect(ally, "hearth_warmth", "damage", upgraded ? 0.15 : 0.10, 4.0); + if (upgraded) + QueueHeal(ally, 45.0); + } + success = allies.Count > 0; + break; + } + case "e06": + foreach (LuneUnit ally in Nearby(unit, true, unit.Position, 4.0, 100, null, true)) + { + if (ally.Hp < ally.MaxHp) + { + QueueHeal(ally, 30.0 * unit.Def.HpFactor); + success = true; + break; + } + } + break; + case "s03": + case "e09": + { + List victims = Nearby(unit, false, unit.Position, ability == "e09" ? 6.0 : 3.0, ability == "e09" ? 3 : 4); + foreach (LuneUnit victim in victims) + AddEffect(victim, "dissonance", "attack_slow", 0.15, 3.0); + success = victims.Count > 0; + break; + } + case "s05": + { + List victims = Nearby(unit, false, unit.Position, 5.0, 1); + foreach (LuneUnit victim in victims) + AddEffect(victim, "rift_wound", "healing_reduction", 0.30, 4.0); + success = victims.Count > 0; + break; + } + } + if (success) + { + unit.AbilityReady = unit.CombatTime + (ability == "w03" || ability == "w04" ? 5.0 : (ability == "w09" || ability == "w10" ? 4.0 : 6.0)); + unit.AbilitySerial += 1; + } + } + + void OnHit(LuneUnit unit, LuneUnit primary, List living, Dictionary gates) + { + string ability = unit.Ability(); + int hits = unit.HitCount; + if (unit.HasTalent("wurzelbeben") && hits % 3 == 0) + Splash(unit, primary, living, gates, 0.50, 2.0, 3); + if (unit.HasTalent("splitterschuss") && hits % 4 == 0) + Splash(unit, primary, living, gates, 0.45, 2.0, 3); + if (unit.HasTalent("keimsaat") && hits % 2 == 0) + AddDot(primary, "seed_burn", 9.0, 4.0, unit.Def.AttackType); + switch (ability) + { + case "w01": + case "w02": + if (hits % 3 == 0) + { + AddEffect(primary, "root_grasp", "movement_slow", ability == "w02" ? 0.30 : 0.20, ability == "w02" ? 3.0 : 2.0); + if (ability == "w02") + AddEffect(primary, "root_grasp_attack", "attack_slow", 0.10, 3.0); + } + break; + case "w05": + case "w06": + if (hits % 4 == 0) + AddDot(primary, "seed_burn", ability == "w06" ? 10.0 : 3.0, 4.0, unit.Def.AttackType); + break; + case "w07": + case "w08": + if (hits % 3 == 0) + Splash(unit, primary, living, gates, ability == "w08" ? 0.80 : 0.60, ability == "w08" ? 2.5 : 2.0, ability == "w08" ? 4 : 3); + break; + case "g01": + case "g02": + if (hits % 3 == 0) + AddDot(primary, "burn", ability == "g02" ? 12.0 : 4.0, 3.0, unit.Def.AttackType); + break; + case "g07": + Splash(unit, primary, living, gates, 0.30, 1.5, 3); + break; + case "g08": + Splash(unit, primary, living, gates, 0.40, 2.0, 4); + break; + case "e05": + if (hits % 4 == 0) + Splash(unit, primary, living, gates, 0.40, 1.5, 2); + break; + case "e07": + if (hits % 4 == 0) + Splash(unit, primary, living, gates, 0.60, 2.0, 3); + break; + case "e10": + if (hits % 4 == 0) + Splash(unit, primary, living, gates, 0.60, 2.5, 4); + break; + case "s04": + if (hits % 4 == 0) + Splash(unit, primary, living, gates, 0.50, 2.0, 3); + break; + } + } + + void Splash(LuneUnit unit, LuneUnit primary, List living, Dictionary gates, double factor, double radius, int maximum) + { + foreach (LuneUnit victim in Nearby(unit, false, primary.Position, radius, maximum, primary)) + QueueDamage(victim, victim.Mitigated(unit.Def.Damage * factor, unit.Def.AttackType), gates); + } + + // ---------------------------------------------------------------- queries for views and tests + public int MobileCount(int team = -1) + { + int count = 0; + foreach (LuneUnit unit in Units) + { + if (unit.Alive && unit.IsMobile() && (team < 0 || unit.Team == team)) + count++; + } + return count; + } + } +} diff --git a/Assets/Luneraria/Core/Simulation/LuneMap.cs b/Assets/Luneraria/Core/Simulation/LuneMap.cs new file mode 100644 index 0000000..68df6a1 --- /dev/null +++ b/Assets/Luneraria/Core/Simulation/LuneMap.cs @@ -0,0 +1,345 @@ +using System.Collections.Generic; + +namespace Luneraria.Core +{ + /// Static data of one building (18 per match). + public sealed class BuildingDef + { + public string Id = ""; + public int Team; + /// top, mid, bot, or base for base towers and Ancients. + public string Lane = ""; + /// outer (Grenzwacht), inner (Bastion), base (Kernwacht) or core (Ancient). + public string Tier = ""; + /// Lane progress from the own base; -1 for base buildings. + public double Progress; + public Vec2 Position; + public double MaxHp; + public double Damage; + public double Range; + public int Bounty; + } + + /// + /// Lane polyline with cumulative lengths. Points are float vectors; the cumulative table is + /// stored as float and the total length as double, as in the reference. + /// + public sealed class LanePath + { + public readonly Vec2[] Points; + public readonly float[] Cumulative; + public readonly double Length; + + public LanePath(List source) + { + Points = source.ToArray(); + Cumulative = new float[Points.Length]; + Cumulative[0] = 0f; + double length = 0.0; + for (int i = 1; i < Points.Length; i++) + { + length += Points[i].DistanceTo(Points[i - 1]); + Cumulative[i] = (float)length; + } + Length = length; + } + + /// Index i of the segment [i - 1, i] that contains lane coordinate d. + int Segment(double d) + { + int low = 1; + int high = Points.Length - 1; + while (low < high) + { + int middle = (low + high) >> 1; + if (d <= Cumulative[middle]) + high = middle; + else + low = middle + 1; + } + return low; + } + + public Vec2 PointAt(double s) + { + double d = GdMath.Clamp(s, 0.0, Length); + int i = Segment(d); + double span = GdMath.Max(0.0001, (double)Cumulative[i] - (double)Cumulative[i - 1]); + return Points[i - 1].Lerp(Points[i], GdMath.Clamp((d - Cumulative[i - 1]) / span, 0.0, 1.0)); + } + + public Vec2 TangentAt(double s) + { + int i = Segment(GdMath.Clamp(s, 0.0, Length)); + return (Points[i] - Points[i - 1]).Normalized(); + } + + /// Point and unnormalised tangent (b - a) / span at s in one pass. + public void Sample(double s, out Vec2 point, out Vec2 tangent) + { + double d = GdMath.Clamp(s, 0.0, Length); + int i = Segment(d); + Vec2 a = Points[i - 1]; + Vec2 b = Points[i]; + double span = GdMath.Max(0.0001, (double)Cumulative[i] - (double)Cumulative[i - 1]); + point = a.Lerp(b, GdMath.Clamp((d - Cumulative[i - 1]) / span, 0.0, 1.0)); + tangent = (b - a) / span; + } + + /// Lane coordinate of the closest point on the polyline. + public double Project(Vec2 position) + { + double best = double.PositiveInfinity; + double bestS = 0.0; + for (int i = 1; i < Points.Length; i++) + { + Vec2 a = Points[i - 1]; + Vec2 b = Points[i]; + Vec2 ab = b - a; + double t = GdMath.Clamp((double)(position - a).Dot(ab) / GdMath.Max(0.0001, (double)ab.LengthSquared()), 0.0, 1.0); + double d = position.DistanceSquaredTo(a + ab * t); + if (d < best) + { + best = d; + bestS = (double)Cumulative[i - 1] + (double)ab.Length() * t; + } + } + return bestS; + } + } + + /// + /// Map in ground coordinates (x, z): Blau (team 0) in the south-west, Rot (team 1) in the + /// north-east, Rot the mirror image of Blau across x = z. Every lane is built from its Blau + /// half and that half mirrored, so lanes, towers and spawns are equal by construction + /// (reference: lune_map.gd, G1 layout). Top and Bottom have exactly the same length. + /// + public sealed class LuneMap + { + public static readonly string[] Lanes = { "top", "mid", "bot" }; + public static readonly Dictionary LaneNames = new Dictionary { { "top", "Top" }, { "mid", "Mid" }, { "bot", "Bottom" } }; + /// Catmull-Rom control points of each Blau half, base to symmetry axis. + public static readonly Vec2[] TopControl = { new Vec2(-27.4, 21.0), new Vec2(-26.4, 13.0), new Vec2(-28.4, 4.0), new Vec2(-26.2, -5.0), + new Vec2(-28.6, -13.5), new Vec2(-28.4, -21.2), new Vec2(-25.0, -25.0) }; + public static readonly Vec2[] MidControl = { new Vec2(-21.6, 21.6), new Vec2(-16.4, 17.2), new Vec2(-10.9, 11.5), new Vec2(-5.6, 5.9), new Vec2(0.0, 0.0) }; + public static readonly Vec2 CoreBlue = new Vec2(-30.0, 30.0); + /// Two base towers per Ancient, 6 m out and 40° either side of the Mid direction. + public static readonly Vec2[] BaseTowersBlue = { new Vec2(-29.477, 24.023), new Vec2(-24.023, 29.477) }; + /// Neutral boss grotto on the symmetry axis between Top and Mid. + public static readonly Vec2 Grotto = new Vec2(-13.5, -13.5); + public const double HalfExtent = 36.0; + public static readonly Vec2 Axis = new Vec2(0.70710678, 0.70710678); + public static readonly Vec2 BlueSide = new Vec2(-0.70710678, 0.70710678); + public const double SampleSpacing = 2.0; + public const string GrottoZone = "grotto"; + + public readonly LuneBalance Balance; + public readonly Dictionary LanePaths = new Dictionary(); + public readonly List Buildings = new List(); + readonly Dictionary _index = new Dictionary(); + + public LuneMap(LuneBalance balance = null) + { + Balance = balance ?? LuneBalance.Default(); + LanePaths["top"] = new LanePath(FullLane(SampleHalf(TopControl))); + LanePaths["mid"] = new LanePath(FullLane(SampleHalf(MidControl))); + LanePaths["bot"] = new LanePath(SolveBottom(LanePaths["top"].Length)); + BuildBuildings(); + } + + public static int LaneIndex(string lane) + { + return System.Array.IndexOf(Lanes, lane); + } + + public static Vec2 Mirror(Vec2 v) { return new Vec2(v.Y, v.X); } + + public static Vec2 MirrorMid(Vec2 v) { return new Vec2(-v.Y, -v.X); } + + public static List FullLane(List half) + { + var result = new List(half); + for (int i = half.Count - 2; i >= 0; i--) + result.Add(Mirror(half[i])); + return result; + } + + /// + /// Samples the Catmull-Rom curve through the control points of a Blau half. The phantom + /// point after the axis point mirrors the one before it, so the joined lane has no kink. + /// + public static List SampleHalf(IList control) + { + var ext = new List { control[0] * 2.0 - control[1] }; + ext.AddRange(control); + ext.Add(Mirror(control[control.Count - 2])); + var result = new List(); + for (int i = 1; i < ext.Count - 2; i++) + { + Vec2 p0 = ext[i - 1]; + Vec2 p1 = ext[i]; + Vec2 p2 = ext[i + 1]; + Vec2 p3 = ext[i + 2]; + int steps = GdMath.Max(2, GdMath.CeilI(p1.DistanceTo(p2) / SampleSpacing)); + for (int k = 0; k < steps; k++) + { + double t = (double)k / steps; + double t2 = t * t; + double t3 = t2 * t; + result.Add(0.5 * (2.0 * p1 + (p2 - p0) * t + (2.0 * p0 - 5.0 * p1 + 4.0 * p2 - p3) * t2 + (3.0 * p1 - p0 - 3.0 * p2 + p3) * t3)); + } + } + result.Add(control[control.Count - 1]); + return result; + } + + /// Bottom half through the south-eastern lowland; bend pulls the meander inwards. + public static Vec2[] BottomControl(double bend) + { + return new[] { new Vec2(-21.0, 27.4), new Vec2(-12.5, 27.0), new Vec2(-4.0, 27.6), new Vec2(4.0, 27.0 - bend), + new Vec2(12.0, 27.4 - 0.6 * bend), new Vec2(19.5, 27.0), new Vec2(22.2, 27.8), new Vec2(25.0, 25.0) }; + } + + /// Bisection on the meander so Bottom is exactly as long as Top. + public static List SolveBottom(double targetLength) + { + double low = 0.0; + double high = 8.0; + for (int i = 0; i < 60; i++) + { + double bend = (low + high) * 0.5; + if (new LanePath(FullLane(SampleHalf(BottomControl(bend)))).Length < targetLength) + low = bend; + else + high = bend; + } + return FullLane(SampleHalf(BottomControl((low + high) * 0.5))); + } + + /// Lane coordinate s for a team's own marching progress (0 at its own base). + public double SFor(int team, string lane, double progress) + { + return team == 0 ? progress : LanePaths[lane].Length - progress; + } + + public double ProgressFor(int team, string lane, double s) + { + return team == 0 ? s : LanePaths[lane].Length - s; + } + + /// Blau frame point, mirrored for Rot so both sides are exact images. + public Vec2 LanePoint(int team, string lane, double progress, double lateral = 0.0) + { + Vec2 point; + Vec2 tangent; + LanePaths[lane].Sample(progress, out point, out tangent); + Vec2 blue = point + new Vec2(-tangent.Y, tangent.X) * lateral; + return team == 0 ? blue : new Vec2(blue.Y, blue.X); + } + + public Vec2 LaneForward(int team, string lane, double progress) + { + LanePath path = LanePaths[lane]; + Vec2 tangent = path.TangentAt(GdMath.Clamp(progress, 0.0, path.Length)); + return team == 0 ? tangent : Mirror(tangent); + } + + /// Grotto entrance of a team (mirrored); the boss rests slightly inside. + public Vec2 GrottoEntry(int team) + { + Vec2 blue = Grotto + new Vec2(1.2, 4.6); + return team == 0 ? blue : Mirror(blue); + } + + public Vec2 GrottoBossPoint() { return Grotto + new Vec2(-1.5, -1.5); } + + public Vec2 GrottoCenter() { return Grotto; } + + /// Army formation area on a lane: progress from/to and lateral half width. + public static void DeploymentSpan(out double from, out double to, out double halfWidth) + { + from = 0.4; + to = 7.2; + halfWidth = 2.4; + } + + public Vec2 CorePosition(int team) { return team == 0 ? CoreBlue : Mirror(CoreBlue); } + + void BuildBuildings() + { + Buildings.Clear(); + _index.Clear(); + for (int team = 0; team < 2; team++) + { + string prefix = team == 0 ? "blau" : "rot"; + foreach (string lane in Lanes) + { + LanePath path = LanePaths[lane]; + foreach (string tier in new[] { "inner", "outer" }) + { + double fraction = tier == "inner" ? Balance.InnerTowerFraction : Balance.OuterTowerFraction; + double progress = path.Length * fraction; + Add(new BuildingDef { Id = prefix + "_" + lane + "_" + tier, Team = team, Lane = lane, Tier = tier, Progress = progress, + Position = LanePoint(team, lane, progress, Balance.TowerSideOffset), + MaxHp = tier == "inner" ? Balance.TowerInnerHp : Balance.TowerOuterHp, Damage = Balance.TowerDamage, Range = Balance.TowerRange, + Bounty = tier == "inner" ? Balance.BountyInnerTower : Balance.BountyOuterTower }); + } + } + for (int index = 0; index < 2; index++) + { + Vec2 point = BaseTowersBlue[index]; + Add(new BuildingDef { Id = prefix + "_base_" + (index + 1), Team = team, Lane = "base", Tier = "base", Progress = -1.0, + Position = team == 0 ? point : Mirror(point), MaxHp = Balance.BaseTowerHp, Damage = Balance.BaseTowerDamage, + Range = Balance.TowerRange, Bounty = Balance.BountyBaseTower }); + } + Add(new BuildingDef { Id = prefix + "_ancient", Team = team, Lane = "base", Tier = "core", Progress = -1.0, + Position = CorePosition(team), MaxHp = Balance.CoreHp, Damage = 0.0, Range = 0.0, Bounty = 0 }); + } + } + + void Add(BuildingDef definition) + { + Buildings.Add(definition); + _index[definition.Id] = definition; + } + + public BuildingDef BuildingDef(string id) + { + BuildingDef definition; + return _index.TryGetValue(id, out definition) ? definition : null; + } + + /// + /// Gate rule shared by every damage source: outer first, inner after its outer, base + /// towers once any lane is fully open, the Ancient after both base towers. + /// alive maps building id to alive; missing ids count as destroyed. + /// + public static bool IsAttackable(BuildingDef definition, IDictionary alive) + { + string prefix = definition.Team == 0 ? "blau" : "rot"; + switch (definition.Tier) + { + case "outer": + return true; + case "inner": + return !Get(alive, prefix + "_" + definition.Lane + "_outer"); + case "base": + foreach (string lane in Lanes) + { + if (!Get(alive, prefix + "_" + lane + "_outer") && !Get(alive, prefix + "_" + lane + "_inner")) + return true; + } + return false; + case "core": + return !Get(alive, prefix + "_base_1") && !Get(alive, prefix + "_base_2"); + } + return false; + } + + static bool Get(IDictionary alive, string id) + { + bool value; + return alive.TryGetValue(id, out value) && value; + } + } +} diff --git a/Assets/Luneraria/Core/Simulation/LuneMatch.cs b/Assets/Luneraria/Core/Simulation/LuneMatch.cs new file mode 100644 index 0000000..0c72298 --- /dev/null +++ b/Assets/Luneraria/Core/Simulation/LuneMatch.cs @@ -0,0 +1,858 @@ +using System; +using System.Collections.Generic; + +namespace Luneraria.Core +{ + /// + /// Authoritative match (reference: lune_match.gd): six seats in two teams, persistent + /// ownership, planning drafts that are validated and committed atomically, combat, + /// settlement and victory. A match ends only when an Ancient falls: no round limit and no + /// decision by HP. Clients never run this; the authority applies their commands. + /// + public sealed class LuneMatch + { + public const int Ongoing = -2; + public const int Draw = -1; + public const string Grotto = "grotto"; + + public readonly LuneBalance Balance; + public readonly LuneMap Map; + public int SeedValue; + public int RoundNumber = 1; + public Phase Phase = Phase.Planning; + public int Winner = Ongoing; + public string EndNote = ""; + public readonly List Players = new List(); + /// Building HP between combats, in map order. + public readonly OrderedMap BuildingHp = new OrderedMap(); + public LuneCombat Combat; + /// Result of the last combat; null before the first settlement. + public Settlement LastSettlement; + public readonly List History = new List(); + public readonly BossState Boss = new BossState(); + public readonly List BossLog = new List(); + public List BotProfiles = new List(); + public readonly Dictionary BotMemory = new Dictionary(); + /// Remainder rotation per team so both teams follow the same distribution. + readonly int[] _rewardRotation = new int[2]; + + public LuneMatch(LuneBalance config = null) + { + Balance = config ?? LuneBalance.Default(); + Map = new LuneMap(Balance); + } + + public void Setup(MatchOptions options) + { + options = options ?? new MatchOptions(); + SeedValue = options.Seed; + RoundNumber = 1; + Phase = Phase.Planning; + Winner = Ongoing; + EndNote = ""; + History.Clear(); + LastSettlement = null; + _rewardRotation[0] = 0; + _rewardRotation[1] = 0; + Boss.NextAvailableRound = 1; + Boss.Claim = null; + Boss.SettledRound = 0; + BossLog.Clear(); + Players.Clear(); + BotProfiles = new List(options.Profiles ?? new List()); + BotMemory.Clear(); + int human = options.HumanSlot; + List bunds = options.Bunds ?? new List(); + for (int slot = 0; slot < 6; slot++) + { + string bund = slot < bunds.Count ? bunds[slot] : ((slot + SeedValue) % 2 == 0 ? "glutpakt" : "wurzelbund"); + var player = new Player + { + Slot = slot, Team = slot / 3, Lane = LuneMap.Lanes[slot % 3], IsHuman = slot == human, + Name = slot == human ? "Du" : ContentData.BotNames[(slot + SeedValue) % ContentData.BotNames.Length], + Bund = bund, Gold = Balance.StartGold, Ready = slot != human, NextSeq = 1, + }; + player.Draft = Snapshot(player); + Players.Add(player); + } + BuildingHp.Clear(); + foreach (BuildingDef definition in Map.Buildings) + BuildingHp[definition.Id] = definition.MaxHp; + } + + public Draft Snapshot(Player player) + { + var draft = new Draft { Gold = player.Gold, NextSeq = player.NextSeq, Hero = player.Hero != null ? player.Hero.Clone() : null, BossLane = "" }; + foreach (RosterEntry entry in player.Roster) + draft.Roster.Add(entry.Clone()); + return draft; + } + + public int SlotOf(int team, string lane) { return team * 3 + LuneMap.LaneIndex(lane); } + + public List BaseIds(string bund) { return DataCatalog.FactionIds(bund); } + + public bool GrottoAvailable() { return RoundNumber >= Boss.NextAvailableRound; } + + // ---------------------------------------------------------------- planning commands + public CommandResult Submit(int slot, Command command) + { + if (Phase != Phase.Planning) + return Result(false, "Befehle sind nur in der Planung möglich."); + if (slot < 0 || slot >= Players.Count) + return Result(false, "Unbekannter Spieler."); + Player player = Players[slot]; + Draft before = player.Draft.Clone(); + CommandResult result = Apply(player, player.Draft, command ?? new Command()); + if (result.Ok) + player.Undo.Add(before); + return result; + } + + public CommandResult Undo(int slot) + { + Player player = Players[slot]; + if (Phase != Phase.Planning || player.Undo.Count == 0) + return Result(false, "Nichts rückgängig zu machen."); + player.Draft = player.Undo[player.Undo.Count - 1]; + player.Undo.RemoveAt(player.Undo.Count - 1); + return Result(true, "Letzte Planung zurückgenommen."); + } + + static int Find(List roster, string uid) + { + for (int index = 0; index < roster.Count; index++) + { + if (roster[index].Uid == uid) + return index; + } + return -1; + } + + static int NextSeq(Draft draft) + { + int seq = draft.NextSeq; + draft.NextSeq = seq + 1; + return seq; + } + + bool ValidDestination(string lane) + { + return LuneMap.LaneIndex(lane) >= 0 || (lane == Grotto && GrottoAvailable()); + } + + CommandResult Apply(Player player, Draft draft, Command command) + { + List roster = draft.Roster; + HeroState hero = draft.Hero; + switch (command.Type ?? "") + { + case "buy": + { + string typeId = command.TypeId ?? ""; + if (!BaseIds(player.Bund).Contains(typeId)) + return Result(false, "Diese Truppe gehört nicht zu deinem Bund."); + if (roster.Count >= Balance.SupplyCap) + return Result(false, string.Format("Versorgungsgrenze erreicht ({0} Truppen).", Balance.SupplyCap)); + UnitDef data = DataCatalog.GetUnit(typeId); + int cost = data.Cost; + if (draft.Gold < cost) + return Result(false, string.Format("Es fehlen {0} Gold.", cost - draft.Gold)); + string lane = command.Lane ?? player.Lane; + if (LuneMap.LaneIndex(lane) < 0) + return Result(false, "Unbekannte Lane."); + draft.Gold -= cost; + // Per-player numbering keeps both teams' ids in the same order. + int seq = NextSeq(draft); + roster.Add(new RosterEntry { Uid = "p" + player.Slot + "-" + seq, Seq = seq, TypeId = typeId, Lane = lane, Invested = cost, Fresh = true }); + return Result(true, data.DisplayName + " gekauft."); + } + case "upgrade": + { + int index = Find(roster, command.Uid ?? ""); + if (index < 0) + return Result(false, "Diese Truppe gehört dir nicht."); + RosterEntry entry = roster[index]; + string upgradeId = DataCatalog.UpgradeOf(entry.TypeId); + if (upgradeId.Length == 0) + return Result(false, "Bereits vollständig aufgewertet."); + UnitDef next = DataCatalog.GetUnit(upgradeId); + if (draft.Gold < next.Cost) + return Result(false, string.Format("Es fehlen {0} Gold.", next.Cost - draft.Gold)); + draft.Gold -= next.Cost; + entry.TypeId = upgradeId; + entry.Invested += next.Cost; + return Result(true, "Zu " + next.DisplayName + " aufgewertet."); + } + case "sell": + { + int index = Find(roster, command.Uid ?? ""); + if (index < 0) + return Result(false, "Diese Truppe gehört dir nicht."); + RosterEntry entry = roster[index]; + // A purchase from this planning is cancelled at full price; committed troops sell at the refund rate. + int refund = entry.Fresh ? entry.Invested : GdMath.FloorI(entry.Invested * Balance.SellRefund); + draft.Gold += refund; + roster.RemoveAt(index); + return Result(true, string.Format("Für {0} Gold zurückgegeben.", refund)); + } + case "assign": + { + string uid = command.Uid ?? ""; + string lane = command.Lane ?? ""; + if (!ValidDestination(lane)) + return Result(false, lane == Grotto ? string.Format("Die Grotte ist bis Runde {0} gesperrt.", Boss.NextAvailableRound) : "Ungültige Zuweisung."); + if (hero != null && hero.Uid == uid) + { + hero.Lane = lane; + } + else + { + int index = Find(roster, uid); + if (index < 0) + return Result(false, "Ungültige Zuweisung."); + roster[index].Lane = lane; + } + return Result(true, lane == Grotto ? "In die Bossgrotte entsandt." : "Auf " + LuneMap.LaneNames[lane] + " eingeteilt."); + } + case "hero_buy": + { + string heroId = command.HeroId ?? ""; + HeroSpec spec; + if (!ContentData.Heroes.TryGetValue(heroId, out spec)) + return Result(false, "Unbekannter Held."); + if (hero != null) + return Result(false, "Pro Spieler ist ein aktiver Held erlaubt."); + if (draft.Gold < spec.Cost) + return Result(false, string.Format("Es fehlen {0} Gold.", spec.Cost - draft.Gold)); + draft.Gold -= spec.Cost; + int seq = NextSeq(draft); + draft.Hero = new HeroState { Uid = "h" + player.Slot + "-" + seq, Seq = seq, HeroId = heroId, Lane = player.Lane, Xp = 0, Invested = spec.Cost, Fresh = true }; + return Result(true, spec.Name + " angeworben."); + } + case "hero_cancel": + { + if (hero == null || !hero.Fresh) + return Result(false, "Nur ein Held aus dieser Planung lässt sich zurückgeben."); + int refund = hero.Invested; + foreach (string itemId in hero.Items) + refund += ContentData.Items[itemId].Cost; + draft.Gold += refund; + draft.Hero = null; + return Result(true, string.Format("Held zurückgegeben ({0} Gold).", refund)); + } + case "item_buy": + { + string itemId = command.ItemId ?? ""; + if (command.Uid != null && (hero == null || command.Uid != hero.Uid)) + return Result(false, "Normale Truppen tragen keine Items."); + if (hero == null) + return Result(false, "Items benötigen einen Helden."); + ItemSpec item; + if (!ContentData.Items.TryGetValue(itemId, out item)) + return Result(false, "Unbekanntes Item."); + if (hero.Items.Contains(itemId)) + return Result(false, item.Name + " trägt dein Held bereits; Items sind einzigartig."); + if (hero.Items.Count >= LuneContent.ItemSlots) + return Result(false, string.Format("Alle {0} Itemplätze sind belegt.", LuneContent.ItemSlots)); + if (LuneContent.LevelFor(hero.Xp) < item.MinLevel) + return Result(false, string.Format("{0} erfordert Stufe {1}.", item.Name, item.MinLevel)); + if (draft.Gold < item.Cost) + return Result(false, string.Format("Es fehlen {0} Gold.", item.Cost - draft.Gold)); + draft.Gold -= item.Cost; + hero.Items.Add(itemId); + hero.FreshItems.Add(itemId); + return Result(true, item.Name + " ausgerüstet."); + } + case "item_sell": + { + string itemId = command.ItemId ?? ""; + if (hero == null || !hero.Items.Contains(itemId)) + return Result(false, "Dein Held trägt dieses Item nicht."); + int cost = ContentData.Items[itemId].Cost; + bool fresh = hero.FreshItems.Contains(itemId); + int refund = fresh ? cost : GdMath.FloorI(cost * LuneContent.ItemRefund); + hero.Items.Remove(itemId); + hero.FreshItems.Remove(itemId); + draft.Gold += refund; + return Result(true, string.Format("Item für {0} Gold verkauft.", refund)); + } + case "talent": + { + if (hero == null) + return Result(false, "Talente benötigen einen Helden."); + int tier = command.Tier ?? -1; + int choice = command.Choice ?? -1; + if (tier != hero.Talents.Count || tier < 0 || tier >= LuneContent.TalentLevels.Length || choice < 0 || choice > 1) + return Result(false, "Dieses Talent ist jetzt nicht wählbar."); + if (LuneContent.LevelFor(hero.Xp) < LuneContent.TalentLevels[tier]) + return Result(false, string.Format("Talentstufe {0} erfordert Heldenstufe {1}.", tier + 1, LuneContent.TalentLevels[tier])); + TalentOption option = LuneContent.TalentsOf(hero.HeroId)[tier][choice]; + hero.Talents.Add(option.Id); + return Result(true, "Talent " + option.Name + " gewählt."); + } + case "champion_book": + { + string championId = command.ChampionId ?? ""; + string lane = command.Lane ?? player.Lane; + ChampionSpec spec; + if (!ContentData.Champions.TryGetValue(championId, out spec) || LuneMap.LaneIndex(lane) < 0) + return Result(false, "Ungültige Buchung."); + if (draft.NewBookings.Count >= LuneContent.MaxBookings) + return Result(false, string.Format("Höchstens {0} Angriffschampions pro Runde.", LuneContent.MaxBookings)); + if (draft.Gold < spec.Cost) + return Result(false, string.Format("Es fehlen {0} Gold.", spec.Cost - draft.Gold)); + draft.Gold -= spec.Cost; + int seq = NextSeq(draft); + draft.NewBookings.Add(new Booking { Uid = "c" + player.Slot + "-" + seq, Seq = seq, ChampionId = championId, Lane = lane, Cost = spec.Cost }); + return Result(true, spec.Name + " für die nächste Runde auf " + LuneMap.LaneNames[lane] + " gebucht."); + } + case "champion_cancel": + { + string uid = command.Uid ?? ""; + List bookings = draft.NewBookings; + for (int index = 0; index < bookings.Count; index++) + { + if (bookings[index].Uid == uid) + { + draft.Gold += bookings[index].Cost; + bookings.RemoveAt(index); + return Result(true, "Buchung zurückgenommen."); + } + } + return Result(false, "Nur Buchungen aus dieser Planung lassen sich zurücknehmen."); + } + case "boss_lane": + { + BossClaim claim = Boss.Claim; + string lane = command.Lane ?? ""; + if (claim == null || claim.DeployRound != RoundNumber || claim.ChooserSlot != player.Slot) + return Result(false, "Du bestimmst die Boss-Lane nicht."); + if (LuneMap.LaneIndex(lane) < 0) + return Result(false, "Unbekannte Lane."); + draft.BossLane = lane; + return Result(true, "Der Boss greift über " + LuneMap.LaneNames[lane] + " an."); + } + } + return Result(false, "Unbekannter Befehl."); + } + + static CommandResult Result(bool ok, string message) { return new CommandResult(ok, message); } + + public void SetReady(int slot, bool value = true) + { + if (Phase == Phase.Planning) + Players[slot].Ready = value; + } + + public bool AllReady() + { + foreach (Player player in Players) + { + if (!player.Ready) + return false; + } + return true; + } + + /// Public for everyone: the champion bookings and boss deployment of this round. + public List Announcements() + { + var result = new List(); + foreach (Player player in Players) + { + foreach (Booking booking in player.Bookings) + { + if (booking.DeployRound == RoundNumber) + result.Add(new Announcement { Kind = "champion", Team = player.Team, Slot = player.Slot, Lane = booking.Lane, ChampionId = booking.ChampionId }); + } + } + BossClaim claim = Boss.Claim; + if (claim != null && claim.DeployRound == RoundNumber) + result.Add(new Announcement { Kind = "boss", Team = claim.Team, Slot = claim.ChooserSlot, Lane = claim.Lane, Bounty = LuneContent.BossBountyFor(RoundNumber) }); + return result; + } + + // ---------------------------------------------------------------- phase changes + /// Validates every draft again and commits all of them at once, then starts combat. + public bool BeginCombat() + { + if (Phase != Phase.Planning) + return false; + foreach (Player player in Players) + { + if (!DraftValid(player)) + player.Draft = Snapshot(player); + } + foreach (Player player in Players) + { + Draft draft = player.Draft; + player.Spent += GdMath.Max(0, player.Gold - draft.Gold); + player.Gold = draft.Gold; + player.NextSeq = draft.NextSeq; + player.Roster = new List(); + foreach (RosterEntry entry in draft.Roster) + { + RosterEntry committed = entry.Clone(); + committed.Fresh = false; + player.Roster.Add(committed); + } + player.Hero = draft.Hero != null ? draft.Hero.Clone() : null; + if (player.Hero != null) + { + player.Hero.Fresh = false; + player.Hero.FreshItems = new List(); + } + foreach (Booking booking in draft.NewBookings) + { + Booking committed = booking.Clone(); + committed.DeployRound = RoundNumber + 1; + player.Bookings.Add(committed); + } + BossClaim claim = Boss.Claim; + if (claim != null && claim.ChooserSlot == player.Slot && draft.BossLane.Length > 0) + claim.Lane = draft.BossLane; + player.Undo.Clear(); + } + Combat = new LuneCombat(Map, Balance, RoundNumber); + foreach (BuildingDef definition in Map.Buildings) + { + if (BuildingHp[definition.Id] > 0.0) + Combat.AddBuilding(definition, BuildingHp[definition.Id]); + } + SpawnWaves(); + SpawnChampions(); + SpawnDeployedBoss(); + SpawnArmies(); + Phase = Phase.Combat; + return true; + } + + bool DraftValid(Player player) + { + Draft draft = player.Draft; + if (draft.Gold < 0 || draft.Roster.Count > Balance.SupplyCap) + return false; + List allowed = BaseIds(player.Bund); + foreach (RosterEntry entry in draft.Roster) + { + string id = entry.TypeId; + string baseId = id; + foreach (string candidate in allowed) + { + if (DataCatalog.UpgradeOf(candidate) == id) + baseId = candidate; + } + if (!allowed.Contains(baseId) || !ValidDestination(entry.Lane)) + return false; + } + HeroState hero = draft.Hero; + if (hero != null) + { + List items = hero.Items; + if (items.Count > LuneContent.ItemSlots || !ValidDestination(hero.Lane)) + return false; + for (int index = 0; index < items.Count; index++) + { + if (items.IndexOf(items[index]) != index || !ContentData.Items.ContainsKey(items[index])) + return false; + } + if (hero.Talents.Count > LuneContent.TalentLevels.Length) + return false; + } + return draft.NewBookings.Count <= LuneContent.MaxBookings; + } + + void SpawnWaves() + { + List wave = LuneWaves.Build(Balance, RoundNumber); + for (int team = 0; team < 2; team++) + { + foreach (string lane in LuneMap.Lanes) + { + for (int index = 0; index < wave.Count; index++) + { + int row = index / 3; + double lateral = ((double)(index % 3) - 1.0) * 1.3; + Combat.Spawn("monster", team, lane, wave[index].Clone(), 11.0 - (double)row * 1.4, lateral); + } + } + } + } + + void SpawnChampions() + { + for (int team = 0; team < 2; team++) + { + foreach (string lane in LuneMap.Lanes) + { + int index = 0; + for (int slot = team * 3; slot < team * 3 + 3; slot++) + { + foreach (Booking booking in Players[slot].Bookings) + { + if (booking.DeployRound == RoundNumber && booking.Lane == lane) + { + UnitDef definition = LuneContent.ChampionDefinition(booking.ChampionId, RoundNumber, Balance); + Combat.Spawn("champion", team, lane, definition, 13.0, ((double)(index % 3) - 1.0) * 1.4, slot, booking.Uid); + index += 1; + } + } + } + } + } + } + + void SpawnDeployedBoss() + { + BossClaim claim = Boss.Claim; + if (claim == null || claim.DeployRound != RoundNumber) + return; + UnitDef definition = LuneContent.BossDefinition(RoundNumber, Balance, true); + Combat.Spawn("boss", claim.Team, claim.Lane, definition, 14.0, 0.0, claim.ChooserSlot, "boss-" + RoundNumber); + BossLog.Add(new BossLogEntry { Round = RoundNumber, Event = "deployed", Team = claim.Team, Lane = claim.Lane }); + } + + /// One unit a player fields this combat: a troop or the hero. + public sealed class ArmyEntry + { + public int Slot; + public string Uid = ""; + public int Seq; + public string Lane = ""; + public string Role = ""; + public int Invested; + public UnitDef Definition; + public string Kind = "troop"; + } + + public List ArmyEntries(int slot) + { + Player player = Players[slot]; + var entries = new List(); + foreach (RosterEntry entry in player.Roster) + { + entries.Add(new ArmyEntry { Slot = slot, Uid = entry.Uid, Seq = entry.Seq, Lane = entry.Lane, Role = RoleOf(entry.TypeId), + Invested = entry.Invested, Definition = TroopDefinition(entry.TypeId), Kind = "troop" }); + } + HeroState hero = player.Hero; + if (hero != null) + { + int invested = hero.Invested; + foreach (string itemId in hero.Items) + invested += ContentData.Items[itemId].Cost; + UnitDef definition = LuneContent.HeroDefinition(hero); + definition.Role = ContentData.HeroRoles[hero.HeroId]; + entries.Add(new ArmyEntry { Slot = slot, Uid = hero.Uid, Seq = hero.Seq, Lane = hero.Lane, Role = definition.Role, + Invested = invested, Definition = definition, Kind = "hero" }); + } + return entries; + } + + UnitDef TroopDefinition(string typeId) + { + UnitDef definition = DataCatalog.GetUnit(typeId); + definition.Role = RoleOf(typeId); + return definition; + } + + /// Front rows first (front, melee, splash, ranged, support), then purchase order. + static List Sorted(List entries) + { + GdMath.SortStable(entries, (a, b) => + { + int ra = Array.IndexOf(ContentData.RowOrder, a.Role); + int rb = Array.IndexOf(ContentData.RowOrder, b.Role); + return ra == rb ? a.Seq < b.Seq : ra < rb; + }); + return entries; + } + + static List OnLane(List entries, string lane) + { + return entries.FindAll(e => e.Lane == lane); + } + + void SpawnArmies() + { + for (int team = 0; team < 2; team++) + { + foreach (string lane in LuneMap.Lanes) + { + // The lane owner's troops form the first rows; supporting players follow behind. + int owner = SlotOf(team, lane); + var order = new List { owner }; + for (int slot = team * 3; slot < team * 3 + 3; slot++) + { + if (slot != owner) + order.Add(slot); + } + var ordered = new List(); + foreach (int slot in order) + ordered.AddRange(Sorted(OnLane(ArmyEntries(slot), lane))); + for (int index = 0; index < ordered.Count; index++) + { + ArmyEntry entry = ordered[index]; + int row = index / 4; + double lateral = ((double)(index % 4) - 1.5) * 1.2; + Combat.Spawn(entry.Kind, team, lane, entry.Definition, GdMath.Max(0.4, 7.2 - (double)row * 1.5), lateral, entry.Slot, entry.Uid); + } + } + } + // Grotto expeditions leave their lanes for the whole combat phase. + bool expedition = false; + for (int team = 0; team < 2; team++) + { + var ordered = new List(); + for (int slot = team * 3; slot < team * 3 + 3; slot++) + ordered.AddRange(Sorted(OnLane(ArmyEntries(slot), Grotto))); + Vec2 entryPoint = Map.GrottoEntry(team); + Vec2 inward = (Map.GrottoBossPoint() - entryPoint).Normalized(); + Vec2 across = new Vec2(-inward.Y, inward.X) * (team == 0 ? 1.0 : -1.0); + for (int index = 0; index < ordered.Count; index++) + { + ArmyEntry entry = ordered[index]; + Vec2 at = entryPoint - inward * (double)(index / 3) * 1.2 + across * ((double)(index % 3) - 1.0) * 1.1; + Combat.SpawnAt(entry.Kind, team, Grotto, entry.Definition, at, entry.Slot, entry.Uid); + expedition = true; + } + } + if (expedition) + Combat.AddGrottoBoss(LuneContent.BossDefinition(RoundNumber, Balance, false)); + } + + /// Role of a troop type (base or upgrade): front, melee, ranged, splash or support. + public string RoleOf(string typeId) + { + foreach (KeyValuePair pair in ContentData.MatchRoles) + { + if (pair.Key == typeId || DataCatalog.UpgradeOf(pair.Key) == typeId) + return pair.Value; + } + return "melee"; + } + + public void StepCombat() + { + if (Phase != Phase.Combat || Combat == null) + return; + Combat.Step(); + if (Combat.Finished) + Settle(); + } + + /// Runs the current combat phase to its end (tests, bot simulations). + public void FinishCombat() + { + while (Phase == Phase.Combat) + StepCombat(); + } + + /// Pays bounties, XP and income once; the match ends only by an Ancient. + public void Settle() + { + var gains = new int[6]; + var laneKills = new OrderedMap(); + var buildingsLost = new List(); + var xpGain = new OrderedMap(); + foreach (CombatEvent ev in Combat.Events) + { + int dying = ev.Team; + int killer = dying < 2 ? 1 - dying : -1; + int bounty = ev.Bounty; + if (ev.Kind == "boss" && ev.Zone == "lane" && bounty > 0 && killer >= 0) + { + // The defenders of a deployed boss share its bounty evenly. + Split(gains, killer, bounty); + } + else if ((ev.Kind == "monster" || ev.Kind == "champion") && bounty > 0 && ev.Zone == "lane" && killer >= 0) + { + int owner = SlotOf(killer, ev.Lane); + int lanePart = (int)Math.Floor(bounty * Balance.LaneShare); + gains[owner] += lanePart; + Split(gains, killer, bounty - lanePart); + laneKills[ev.Lane] = laneKills.GetValueOrDefault(ev.Lane, 0) + 1; + } + else if (ev.Kind == "tower" || ev.Kind == "core") + { + buildingsLost.Add(ev.BuildingId); + Split(gains, killer, bounty); + } + if (ev.XpHeroes.Count > 0) + { + int share = GdMath.Max(1, ev.Xp / ev.XpHeroes.Count); + foreach (string uid in ev.XpHeroes) + xpGain[uid] = xpGain.GetValueOrDefault(uid, 0) + share; + } + } + foreach (LuneUnit unit in Combat.Units) + { + if (unit.IsBuilding()) + BuildingHp[unit.BuildingId] = unit.Alive ? unit.Hp : 0.0; + else if (unit.Kind == "hero") + xpGain[unit.PersistentUid] = xpGain.GetValueOrDefault(unit.PersistentUid, 0) + LuneContent.XpParticipation + LuneContent.XpPerRound * RoundNumber; + } + foreach (Player player in Players) + { + int gained; + if (player.Hero != null && xpGain.TryGetValue(player.Hero.Uid, out gained)) + player.Hero.Xp += gained; + } + int income = Balance.RoundIncome(RoundNumber); + foreach (Player player in Players) + { + int total = gains[player.Slot] + (Combat.DestroyedCores.Count > 0 ? 0 : income); + player.Gold += total; + player.Earned += total; + // Deployed bookings are consumed; they never return as property. + player.Bookings = player.Bookings.FindAll(b => b.DeployRound > RoundNumber); + } + // The claim is decided from this round's expedition before its units go home. + string bossResult = SettleBoss(); + foreach (Player player in Players) + { + // An expedition is an order for one round: units return to their owner's lane. + foreach (RosterEntry entry in player.Roster) + { + if (entry.Lane == Grotto) + entry.Lane = player.Lane; + } + if (player.Hero != null && player.Hero.Lane == Grotto) + player.Hero.Lane = player.Lane; + } + LastSettlement = new Settlement { Round = RoundNumber, Gains = gains, Income = income, BuildingsLost = buildingsLost, EndReason = Combat.EndReason, + CombatTime = Combat.Elapsed, LaneKills = laneKills, Xp = xpGain, Boss = bossResult }; + var entryHistory = new HistoryEntry { Round = RoundNumber, EndReason = Combat.EndReason, CombatTime = Combat.Elapsed, Buildings = AliveCount(), + Lost = new List(buildingsLost), Boss = bossResult }; + for (int slot = 0; slot < 6; slot++) + { + entryHistory.Gold[slot] = Players[slot].Gold; + entryHistory.HeroLevels[slot] = Players[slot].Hero == null ? 0 : LuneContent.LevelFor(Players[slot].Hero.Xp); + } + History.Add(entryHistory); + if (Combat.DestroyedCores.Count > 0) + { + Winner = Combat.DestroyedCores.Count >= 2 ? Draw : 1 - Combat.DestroyedCores[0]; + EndNote = Winner == Draw ? "Beide Ancients fielen im selben Schritt." : "Ancient von " + (Combat.DestroyedCores[0] == 0 ? "Blau" : "Rot") + " zerstört."; + Phase = Phase.Over; + return; + } + RoundNumber += 1; + Phase = Phase.Planning; + foreach (Player player in Players) + { + player.Draft = Snapshot(player); + player.Undo.Clear(); + player.Ready = !player.IsHuman; + } + } + + /// + /// Boss bookkeeping at settlement; returns a short outcome label. Idempotent: a repeated + /// settlement signal for the same combat changes nothing ("repeat"). + /// + public string SettleBoss() + { + int fought = Combat.RoundNumber; + if (Boss.SettledRound == fought) + return "repeat"; + Boss.SettledRound = fought; + string result = "none"; + BossClaim claim = Boss.Claim; + if (claim != null && claim.DeployRound == fought) + { + // The deployment happens exactly once; afterwards the claim is gone. + Boss.Claim = null; + result = "deployed"; + } + if (Combat.GrottoOutcome == "success" && Boss.Claim == null && fought >= Boss.NextAvailableRound) + { + int team = Combat.GrottoClaimTeam; + int chooser = BossChooser(team); + Boss.Claim = new BossClaim { Team = team, WonRound = fought, DeployRound = fought + 1, ChooserSlot = chooser, Lane = Players[chooser].Lane }; + Boss.NextAvailableRound = fought + 1 + LuneContent.BossLockRounds; + BossLog.Add(new BossLogEntry { Round = fought, Event = "won", Team = team, Chooser = chooser }); + result = "won"; + } + else if (Combat.GrottoOutcome == "failed") + { + BossLog.Add(new BossLogEntry { Round = fought, Event = "failed" }); + result = result == "none" ? "failed" : result; + } + return result; + } + + /// The team's player with the highest army value in the grotto; ties go to the lower slot. + int BossChooser(int team) + { + int best = team * 3; + int bestValue = -1; + for (int slot = team * 3; slot < team * 3 + 3; slot++) + { + int value = 0; + foreach (ArmyEntry entry in ArmyEntries(slot)) + { + if (entry.Lane == Grotto) + value += entry.Invested; + } + if (value > bestValue) + { + best = slot; + bestValue = value; + } + } + return best; + } + + /// Distributes an amount evenly over a team; the remainder rotates so no slot is favoured. + void Split(int[] gains, int team, int amount) + { + if (amount <= 0 || team < 0) + return; + int share = amount / 3; + int rest = amount % 3; + for (int offset = 0; offset < 3; offset++) + gains[team * 3 + offset] += share; + for (int index = 0; index < rest; index++) + gains[team * 3 + (_rewardRotation[team] + index) % 3] += 1; + _rewardRotation[team] = (_rewardRotation[team] + rest) % 3; + } + + int[] AliveCount() + { + var counts = new int[2]; + foreach (KeyValuePair pair in BuildingHp) + { + if (pair.Value > 0.0) + counts[pair.Key.StartsWith("blau", StringComparison.Ordinal) ? 0 : 1] += 1; + } + return counts; + } + + public bool BuildingAlive(string id) + { + double hp; + return BuildingHp.TryGetValue(id, out hp) && hp > 0.0; + } + + /// Live state for displays: during combat the combat instance is authoritative. + public bool BuildingAliveNow(string id) + { + LuneUnit unit; + if (Phase == Phase.Combat && Combat != null && Combat.Buildings.TryGetValue(id, out unit)) + return unit.Alive; + return BuildingAlive(id); + } + + public int TowersAlive(int team, string lane, bool live = false) + { + string prefix = team == 0 ? "blau" : "rot"; + Func probe = live ? (Func)BuildingAliveNow : BuildingAlive; + return (probe(prefix + "_" + lane + "_outer") ? 1 : 0) + (probe(prefix + "_" + lane + "_inner") ? 1 : 0); + } + + public double CoreHp(int team) { return BuildingHp[team == 0 ? "blau_ancient" : "rot_ancient"]; } + + public int GoldOf(int slot) { return Phase == Phase.Planning ? Players[slot].Draft.Gold : Players[slot].Gold; } + } +} diff --git a/Assets/Luneraria/Core/Simulation/LuneUnit.cs b/Assets/Luneraria/Core/Simulation/LuneUnit.cs new file mode 100644 index 0000000..c998c10 --- /dev/null +++ b/Assets/Luneraria/Core/Simulation/LuneUnit.cs @@ -0,0 +1,253 @@ +using System; +using System.Collections.Generic; + +namespace Luneraria.Core +{ + /// Timed effect of one family (e.g. "root_grasp"): kind, strength, time left. + public sealed class Effect + { + /// movement_slow, attack_slow, attack_speed, damage, reduction, healing_reduction. + public string Kind = ""; + public double Amount; + public double Remaining; + } + + /// Damage over time of one family (e.g. "burn"): ticks once per second. + public sealed class DamageOverTime + { + public double Damage; + public double Remaining; + public double NextTick = 1.0; + public int AttackType; + } + + /// + /// One combat instance (reference: lune_unit.gd). Persistent ownership stays in LuneMatch; + /// this object lives for one combat phase. Damage, heals and effects are queued and applied + /// together by LuneCombat, so processing order never decides who strikes first. + /// + public sealed class LuneUnit + { + /// Attack type (row) against armour type (column): Klinge, Durchschlag, Impuls. + public static readonly double[,] DamageMatrix = { { 1.30, 0.75, 1.00 }, { 1.00, 1.30, 0.75 }, { 0.75, 1.00, 1.30 } }; + public static readonly string[] MobileKinds = { "troop", "hero", "monster", "champion", "boss" }; + + /// Sequential per combat, assigned in spawn order (deterministic). + public int Id; + /// Spawn index within the own team; mirrored units share it (fair staggering). + public int TeamIndex; + /// troop, hero, monster, champion, boss, tower or core. + public string Kind = "troop"; + public int Team; + public int OwnerSlot = -1; + public string PersistentUid = ""; + public string Lane = "mid"; + /// lane or grotto. + public string Zone = "lane"; + public UnitDef Def = new UnitDef(); + public string BuildingId = ""; + public Vec2 Position; + public Vec2 PreviousPosition; + public double Facing; + public double Hp = 1.0; + public double MaxHp = 1.0; + public bool Alive = true; + public LuneUnit Target; + public double Progress; + public double Lateral; + public double AttackProgress; + public int HitCount; + public double CombatTime; + public double Shield; + public double ShieldRemaining = double.PositiveInfinity; + public readonly OrderedMap Effects = new OrderedMap(); + public readonly OrderedMap Dots = new OrderedMap(); + public double AbilityReady = 6.0; + public bool ReachedBase; + /// The grotto boss waits while two expeditions still fight each other. + public bool Dormant; + public double AuraReady = 4.0; + // Presentation-only counters; never read by the rules. + public int AttackSerial; + public int AbilitySerial; + public double HitFlash; + public bool InRange; + public double DeathTime = -1.0; + + public bool IsBuilding() { return Kind == "tower" || Kind == "core"; } + + public bool IsMobile() { return Array.IndexOf(MobileKinds, Kind) >= 0; } + + public double AttackRange() { return Def.AttackRange; } + + public double Speed() { return Def.Speed; } + + public int ArmorType() { return GdMath.Clamp(Def.ArmorType, 0, 2); } + + public string Ability() { return Def.Ability; } + + public bool IsBoss() { return Kind == "boss" || Def.IsBoss; } + + public double Mitigated(double raw, int attackType) + { + double value = GdMath.Max(0.0, raw) * DamageMatrix[GdMath.Clamp(attackType, 0, 2), ArmorType()]; + return value * (1.0 - DamageReduction()); + } + + /// Applies an already mitigated amount through the shield. + public void Take(double amount) + { + if (!Alive || amount <= 0.0) + return; + double absorbed = GdMath.Min(Shield, amount); + Shield -= absorbed; + Hp = GdMath.Max(0.0, Hp - (amount - absorbed)); + HitFlash = 0.18; + } + + public void Heal(double amount) + { + if (Alive && !IsBuilding()) + Hp = GdMath.Min(MaxHp, Hp + GdMath.Max(0.0, amount) * (1.0 - StrongestEffect("healing_reduction"))); + } + + public void GrantShield(double amount, double duration = double.PositiveInfinity) + { + if (Alive && amount > Shield) + { + Shield = amount; + ShieldRemaining = duration; + } + } + + /// Buildings ignore crowd control and buffs; an existing family keeps the stronger values. + public void ApplyEffect(string family, string kind, double amount, double duration) + { + if (!Alive || IsBuilding()) + return; + Effect effect; + if (Effects.TryGetValue(family, out effect)) + { + effect.Amount = GdMath.Max(effect.Amount, amount); + effect.Remaining = GdMath.Max(effect.Remaining, duration); + } + else + { + Effects[family] = new Effect { Kind = kind, Amount = amount, Remaining = duration }; + } + } + + public void ApplyDot(string family, double damage, double duration, int attackType) + { + if (!Alive || IsBuilding()) + return; + DamageOverTime dot; + if (Dots.TryGetValue(family, out dot)) + { + if (damage > dot.Damage) + { + dot.Damage = damage; + dot.AttackType = attackType; + } + dot.Remaining = GdMath.Max(dot.Remaining, duration); + } + else + { + Dots[family] = new DamageOverTime { Damage = damage, Remaining = duration, NextTick = 1.0, AttackType = attackType }; + } + } + + public double StrongestEffect(string kind) + { + double amount = 0.0; + IReadOnlyList values = Effects.Values; + for (int i = 0; i < values.Count; i++) + { + if (values[i].Kind == kind) + amount = GdMath.Max(amount, values[i].Amount); + } + return amount; + } + + public double DamageBonus() + { + double result = 0.0; + IReadOnlyList values = Effects.Values; + for (int i = 0; i < values.Count; i++) + { + if (values[i].Kind == "damage") + result += values[i].Amount; + } + return GdMath.Min(0.30, result) + Def.DamageBonus; + } + + public double DamageReduction() + { + double result = StrongestEffect("reduction"); + switch (Ability()) + { + case "g03": + if (CombatTime < 8.0 - 0.000001) + result = GdMath.Max(result, 0.15); + break; + case "g04": + result = GdMath.Max(result, CombatTime < 10.0 - 0.000001 ? 0.25 : 0.10); + break; + } + return GdMath.Min(0.35, result + Def.ReductionBonus); + } + + public double AttackSpeedFactor() + { + double slowing = StrongestEffect("attack_slow") * (IsBoss() ? 0.5 : 1.0); + double bonus = Def.AttackSpeedBonus; + return 1.0 + GdMath.Clamp(StrongestEffect("attack_speed") - slowing + bonus, -0.25, 0.5); + } + + public bool HasTalent(string id) { return Def.Talents.Contains(id); } + + public string Role() { return Def.Role; } + + public double MovementFactor() + { + return 1.0 - GdMath.Min(0.35, StrongestEffect("movement_slow") * (IsBoss() ? 0.5 : 1.0)); + } + + /// Advances effect and shield timers; returns the DoT damage due this step. + public double AdvanceStatus(double delta) + { + CombatTime += delta; + HitFlash = GdMath.Max(0.0, HitFlash - delta); + var families = new List(Effects.Keys); + foreach (string family in families) + { + Effect effect = Effects[family]; + effect.Remaining -= delta; + if (effect.Remaining <= 0.000001) + Effects.Remove(family); + } + if (!double.IsPositiveInfinity(ShieldRemaining)) + { + ShieldRemaining -= delta; + if (ShieldRemaining <= 0.000001) + Shield = 0.0; + } + double dotDamage = 0.0; + var dotFamilies = new List(Dots.Keys); + foreach (string family in dotFamilies) + { + DamageOverTime dot = Dots[family]; + dot.NextTick -= GdMath.Min(delta, GdMath.Max(0.0, dot.Remaining)); + while (dot.NextTick <= 0.000001) + { + dotDamage += Mitigated(dot.Damage, dot.AttackType); + dot.NextTick += 1.0; + } + dot.Remaining -= delta; + if (dot.Remaining <= 0.000001) + Dots.Remove(family); + } + return dotDamage; + } + } +} diff --git a/Assets/Luneraria/Core/Simulation/MatchModel.cs b/Assets/Luneraria/Core/Simulation/MatchModel.cs new file mode 100644 index 0000000..b00025e --- /dev/null +++ b/Assets/Luneraria/Core/Simulation/MatchModel.cs @@ -0,0 +1,236 @@ +using System.Collections.Generic; + +namespace Luneraria.Core +{ + public enum Phase { Planning, Combat, Over } + + /// One persistent troop of a player (committed roster or planning draft). + public sealed class RosterEntry + { + /// "p{slot}-{seq}": unique per match; ownership is the slot in the uid. + public string Uid = ""; + public int Seq; + public string TypeId = ""; + /// top, mid, bot or grotto (one round). + public string Lane = ""; + public int Invested; + /// Bought in the current planning (full refund on sale). + public bool Fresh; + + public RosterEntry Clone() { return (RosterEntry)MemberwiseClone(); } + } + + /// The single hero of a player. + public sealed class HeroState + { + public string Uid = ""; + public int Seq; + public string HeroId = ""; + public string Lane = ""; + public int Xp; + public List Items = new List(); + public List Talents = new List(); + public int Invested; + public bool Fresh; + /// Items bought in the current planning (full refund on sale). + public List FreshItems = new List(); + + public HeroState Clone() + { + var copy = (HeroState)MemberwiseClone(); + copy.Items = new List(Items); + copy.Talents = new List(Talents); + copy.FreshItems = new List(FreshItems); + return copy; + } + } + + /// An attack champion booking: bought in round n, fights once in round n + 1. + public sealed class Booking + { + public string Uid = ""; + public int Seq; + public string ChampionId = ""; + public string Lane = ""; + public int Cost; + /// 0 while uncommitted (draft); the round it fights in once committed. + public int DeployRound; + + public Booking Clone() { return (Booking)MemberwiseClone(); } + } + + /// Private planning of one player; validated and committed atomically at combat start. + public sealed class Draft + { + public int Gold; + public List Roster = new List(); + public int NextSeq; + public HeroState Hero; + public List NewBookings = new List(); + /// Lane chosen by the boss chooser in this planning, "" if unchanged. + public string BossLane = ""; + + public Draft Clone() + { + var copy = new Draft { Gold = Gold, NextSeq = NextSeq, BossLane = BossLane, Hero = Hero != null ? Hero.Clone() : null }; + foreach (RosterEntry entry in Roster) + copy.Roster.Add(entry.Clone()); + foreach (Booking booking in NewBookings) + copy.NewBookings.Add(booking.Clone()); + return copy; + } + } + + /// One of six seats. Team = slot / 3, lane = slot % 3 (top, mid, bot). + public sealed class Player + { + public int Slot; + public int Team; + public string Lane = ""; + public bool IsHuman; + public string Name = ""; + public string Bund = ""; + public int Gold; + public List Roster = new List(); + public HeroState Hero; + public List Bookings = new List(); + public bool Ready; + public int Earned; + public int Spent; + public int NextSeq; + public Draft Draft; + public List Undo = new List(); + } + + public sealed class BossClaim + { + public int Team; + public int WonRound; + public int DeployRound; + public int ChooserSlot; + public string Lane = ""; + + public BossClaim Clone() { return (BossClaim)MemberwiseClone(); } + } + + /// Public boss state: the grotto opens from NextAvailableRound; Claim is null or the conquest. + public sealed class BossState + { + public int NextAvailableRound = 1; + public BossClaim Claim; + /// Round whose settlement was already applied (idempotence), 0 = none. + public int SettledRound; + } + + public sealed class BossLogEntry + { + public int Round; + /// deployed, won or failed. + public string Event = ""; + public int Team = -1; + public string Lane = ""; + public int Chooser = -1; + } + + /// Public announcement of the current round: a champion or the deployed boss. + public sealed class Announcement + { + /// champion or boss. + public string Kind = ""; + public int Team; + public int Slot; + public string Lane = ""; + public string ChampionId = ""; + public int Bounty; + } + + public sealed class Settlement + { + public int Round; + public int[] Gains = new int[6]; + public int Income; + public List BuildingsLost = new List(); + public string EndReason = ""; + public double CombatTime; + public OrderedMap LaneKills = new OrderedMap(); + public OrderedMap Xp = new OrderedMap(); + /// none, won, failed, deployed or repeat. + public string Boss = "none"; + } + + public sealed class HistoryEntry + { + public int Round; + public string EndReason = ""; + public double CombatTime; + public int[] Buildings = new int[2]; + public int[] Gold = new int[6]; + public List Lost = new List(); + public string Boss = ""; + public int[] HeroLevels = new int[6]; + } + + public sealed class MatchOptions + { + public int Seed = 1; + /// -1 for six bots. + public int HumanSlot = 1; + /// Six Bünde; missing entries follow the seed. + public List Bunds = new List(); + /// Optional fixed bot profile per slot (balance runs). + public List Profiles = new List(); + } + + /// Bot-private notes per slot, derived only from its own actions and public outcomes. + public sealed class BotMemory + { + public bool HasChampionRound; + public int ChampionRound; + public bool HasBossFields; + public double Bar; + public int Sent; + } + + public struct CommandResult + { + public bool Ok; + public string Message; + + public CommandResult(bool ok, string message) + { + Ok = ok; + Message = message; + } + } + + /// + /// A player's intent during planning. Clients only ever send these; the authority applies + /// them through LuneMatch.Submit. Null fields mean "not given" (e.g. buy without lane uses + /// the player's own lane). + /// + public sealed class Command + { + public string Type = ""; + public string TypeId; + public string Lane; + public string Uid; + public string HeroId; + public string ItemId; + public string ChampionId; + public int? Tier; + public int? Choice; + + public static Command Buy(string typeId, string lane = null) { return new Command { Type = "buy", TypeId = typeId, Lane = lane }; } + public static Command Upgrade(string uid) { return new Command { Type = "upgrade", Uid = uid }; } + public static Command Sell(string uid) { return new Command { Type = "sell", Uid = uid }; } + public static Command Assign(string uid, string lane) { return new Command { Type = "assign", Uid = uid, Lane = lane }; } + public static Command HeroBuy(string heroId) { return new Command { Type = "hero_buy", HeroId = heroId }; } + public static Command HeroCancel() { return new Command { Type = "hero_cancel" }; } + public static Command ItemBuy(string itemId, string uid = null) { return new Command { Type = "item_buy", ItemId = itemId, Uid = uid }; } + public static Command ItemSell(string itemId) { return new Command { Type = "item_sell", ItemId = itemId }; } + public static Command Talent(int tier, int choice) { return new Command { Type = "talent", Tier = tier, Choice = choice }; } + public static Command ChampionBook(string championId, string lane = null) { return new Command { Type = "champion_book", ChampionId = championId, Lane = lane }; } + public static Command ChampionCancel(string uid) { return new Command { Type = "champion_cancel", Uid = uid }; } + public static Command BossLaneChoice(string lane) { return new Command { Type = "boss_lane", Lane = lane }; } + } +} diff --git a/Assets/Luneraria/Tests/Core/CheckSuite.cs b/Assets/Luneraria/Tests/Core/CheckSuite.cs new file mode 100644 index 0000000..4de8e99 --- /dev/null +++ b/Assets/Luneraria/Tests/Core/CheckSuite.cs @@ -0,0 +1,56 @@ +using System; +using System.Collections.Generic; + +namespace Luneraria.Core.Tests +{ + /// + /// A test suite in the style of the Godot reference tests: named checks, counted, failures + /// collected with their label. The same suites run in the .NET harness (tools/dotnet) and in + /// Unity's Test Runner (Unity/CoreSuiteTests.cs); check counts stay comparable with Godot. + /// + public abstract class CheckSuite + { + public int Checks { get; private set; } + public readonly List Failures = new List(); + public readonly List Notes = new List(); + /// Folder with the golden files (Assets/Luneraria/Tests/Core/Golden). + public string GoldenDirectory = ""; + + public abstract string Name { get; } + + protected abstract void RunChecks(); + + public bool Run() + { + Checks = 0; + Failures.Clear(); + Notes.Clear(); + try + { + RunChecks(); + } + catch (Exception error) + { + Failures.Add("EXCEPTION " + error.GetType().Name + ": " + error.Message + "\n" + error.StackTrace); + } + return Failures.Count == 0; + } + + protected void Check(bool ok, string label) + { + Checks += 1; + if (!ok) + Failures.Add(label); + } + + protected void Note(string text) + { + Notes.Add(text); + } + + public static IList All() + { + return new List { new ContentSuite(), new CoreRulesSuite(), new M2RulesSuite(), new GoldenSuite(), new DeterminismSuite() }; + } + } +} diff --git a/Assets/Luneraria/Tests/Core/ContentSuite.cs b/Assets/Luneraria/Tests/Core/ContentSuite.cs new file mode 100644 index 0000000..68cf590 --- /dev/null +++ b/Assets/Luneraria/Tests/Core/ContentSuite.cs @@ -0,0 +1,308 @@ +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; + +namespace Luneraria.Core.Tests +{ + /// + /// Compares every rule table and the computed map of the C# core with the export of the + /// Godot reference (Golden/content.json, tools/godot-golden/content_export.gd): units, + /// monsters, sends, heroes, talents, items, champions, bot profiles (order), balance + /// defaults, lane polylines and building positions. Tables must match exactly; the lane + /// geometry is computed and must match within 1e-5 m (the largest deviation is noted). + /// + public sealed class ContentSuite : CheckSuite + { + public override string Name { get { return "content"; } } + + const double GeometryTolerance = 0.00001; + + protected override void RunChecks() + { + var data = MiniJson.Obj(MiniJson.Parse(File.ReadAllText(Path.Combine(GoldenDirectory, "content.json")))); + CompareUnits("units", MiniJson.Obj(data["units"]), ContentData.Units); + CompareUnits("enemies", MiniJson.Obj(data["enemies"]), ContentData.Enemies); + CompareUnits("sends", MiniJson.Obj(data["sends"]), ContentData.Sends); + CompareHeroes(MiniJson.Obj(data["heroes"])); + CompareItems(MiniJson.Obj(data["items"])); + CompareChampions(MiniJson.Obj(data["champions"])); + CompareTalents(MiniJson.Obj(data["talents"])); + CompareConstants(data); + CompareProfiles(MiniJson.Obj(data["bot_profiles"])); + CompareBalance(MiniJson.Obj(data["balance"])); + CompareMap(MiniJson.Obj(data["lanes"]), MiniJson.Arr(data["buildings"])); + } + + void CompareUnits(string label, OrderedMap expected, OrderedMap actual) + { + Check(expected.Keys.SequenceEqual(actual.Keys), label + ": same ids in the same order"); + foreach (KeyValuePair pair in expected) + { + var entry = MiniJson.Obj(pair.Value); + UnitDef unit; + if (!actual.TryGetValue(pair.Key, out unit)) + { + Check(false, label + ": missing " + pair.Key); + continue; + } + var problems = new List(); + Compare(problems, entry, "id", unit.Id); + Compare(problems, entry, "display_name", unit.DisplayName); + Compare(problems, entry, "cost", unit.Cost); + Compare(problems, entry, "upgrade_id", unit.UpgradeId); + Compare(problems, entry, "max_hp", unit.MaxHp); + Compare(problems, entry, "damage", unit.Damage); + Compare(problems, entry, "attack_type", unit.AttackType); + Compare(problems, entry, "armor_type", unit.ArmorType); + Compare(problems, entry, "attack_range", unit.AttackRange); + Compare(problems, entry, "speed", unit.Speed); + Compare(problems, entry, "ability", unit.Ability); + Compare(problems, entry, "leak_value", unit.LeakValue); + Compare(problems, entry, "bounty", unit.Bounty); + Compare(problems, entry, "ability_description", unit.AbilityDescription); + Compare(problems, entry, "is_boss", unit.IsBoss); + Compare(problems, entry, "income_gain", unit.IncomeGain); + Check(problems.Count == 0, label + " " + pair.Key + " matches the reference " + string.Join(", ", problems)); + } + } + + static void Compare(List problems, OrderedMap entry, string key, object actual) + { + object expected; + if (!entry.TryGetValue(key, out expected)) + return; + bool same; + if (actual is double d) + same = MiniJson.Num(expected) == d; + else if (actual is int i) + same = MiniJson.Int(expected) == i; + else if (actual is bool b) + same = expected is bool eb && eb == b; + else + same = MiniJson.Str(expected) == MiniJson.Str(actual); + if (!same) + problems.Add(key + ": " + MiniJson.Str(expected) + " != " + MiniJson.Str(actual)); + } + + void CompareHeroes(OrderedMap expected) + { + Check(expected.Keys.SequenceEqual(ContentData.Heroes.Keys), "heroes: same ids in the same order"); + foreach (KeyValuePair pair in expected) + { + var entry = MiniJson.Obj(pair.Value); + HeroSpec hero = ContentData.Heroes[pair.Key]; + var problems = new List(); + Compare(problems, entry, "name", hero.Name); + Compare(problems, entry, "title", hero.Title); + Compare(problems, entry, "model", hero.Model); + Compare(problems, entry, "cost", hero.Cost); + Compare(problems, entry, "role", hero.RoleText); + Compare(problems, entry, "summary", hero.Summary); + var baseDef = MiniJson.Obj(entry["def"]); + Compare(problems, baseDef, "max_hp", hero.Base.MaxHp); + Compare(problems, baseDef, "damage", hero.Base.Damage); + Compare(problems, baseDef, "attack_type", hero.Base.AttackType); + Compare(problems, baseDef, "armor_type", hero.Base.ArmorType); + Compare(problems, baseDef, "attack_range", hero.Base.AttackRange); + Compare(problems, baseDef, "speed", hero.Base.Speed); + Compare(problems, baseDef, "ability", hero.Base.Ability); + Check(problems.Count == 0, "hero " + pair.Key + " matches " + string.Join(", ", problems)); + } + } + + void CompareItems(OrderedMap expected) + { + Check(expected.Keys.SequenceEqual(ContentData.Items.Keys), "items: same ids in the same order"); + foreach (KeyValuePair pair in expected) + { + var entry = MiniJson.Obj(pair.Value); + ItemSpec item = ContentData.Items[pair.Key]; + var problems = new List(); + Compare(problems, entry, "name", item.Name); + Compare(problems, entry, "cost", item.Cost); + Compare(problems, entry, "text", item.Text); + Compare(problems, entry, "hp_flat", item.HpFlat); + Compare(problems, entry, "damage", item.Damage); + Compare(problems, entry, "reduction", item.Reduction); + Compare(problems, entry, "attack_speed", item.AttackSpeed); + Compare(problems, entry, "regen", item.Regen); + Compare(problems, entry, "splash", item.Splash); + Compare(problems, entry, "min_level", item.MinLevel); + Check(problems.Count == 0, "item " + pair.Key + " matches " + string.Join(", ", problems)); + } + } + + void CompareChampions(OrderedMap expected) + { + Check(expected.Keys.SequenceEqual(ContentData.Champions.Keys), "champions: same ids in the same order"); + foreach (KeyValuePair pair in expected) + { + var entry = MiniJson.Obj(pair.Value); + ChampionSpec spec = ContentData.Champions[pair.Key]; + var problems = new List(); + Compare(problems, entry, "name", spec.Name); + Compare(problems, entry, "role", spec.RoleText); + Compare(problems, entry, "model", spec.Model); + Compare(problems, entry, "cost", spec.Cost); + Compare(problems, entry, "base", spec.Base); + Compare(problems, entry, "text", spec.Text); + Compare(problems, entry, "priority", spec.Priority); + Compare(problems, entry, "siege_factor", spec.SiegeFactor); + Compare(problems, entry, "view_scale", spec.ViewScale); + Check(problems.Count == 0, "champion " + pair.Key + " matches " + string.Join(", ", problems)); + } + } + + void CompareTalents(OrderedMap expected) + { + bool same = expected.Count == ContentData.Talents.Count; + foreach (KeyValuePair pair in expected) + { + TalentOption[][] tiers; + if (!ContentData.Talents.TryGetValue(pair.Key, out tiers)) + { + same = false; + continue; + } + List expectedTiers = MiniJson.Arr(pair.Value); + same = same && expectedTiers.Count == tiers.Length; + for (int tier = 0; tier < Math.Min(expectedTiers.Count, tiers.Length); tier++) + { + List options = MiniJson.Arr(expectedTiers[tier]); + same = same && options.Count == tiers[tier].Length; + for (int choice = 0; choice < Math.Min(options.Count, tiers[tier].Length); choice++) + { + var option = MiniJson.Obj(options[choice]); + same = same && MiniJson.Str(option["id"]) == tiers[tier][choice].Id && MiniJson.Str(option["name"]) == tiers[tier][choice].Name + && MiniJson.Str(option["text"]) == tiers[tier][choice].Text; + } + } + } + Check(same, "talents: every tier and choice matches"); + } + + void CompareConstants(OrderedMap data) + { + List levels = MiniJson.Arr(data["level_xp"]); + Check(levels.Select(MiniJson.Int).SequenceEqual(ContentData.LevelXp), "level XP table"); + Check(MiniJson.Arr(data["talent_levels"]).Select(MiniJson.Int).SequenceEqual(ContentData.TalentLevels), "talent levels"); + var constants = MiniJson.Obj(data["content_constants"]); + var expected = new Dictionary + { + { "HP_PER_LEVEL", LuneContent.HpPerLevel }, { "DAMAGE_PER_LEVEL", LuneContent.DamagePerLevel }, { "XP_PARTICIPATION", LuneContent.XpParticipation }, + { "XP_PER_ROUND", LuneContent.XpPerRound }, { "XP_RADIUS", LuneContent.XpRadius }, { "ITEM_SLOTS", LuneContent.ItemSlots }, + { "ITEM_REFUND", LuneContent.ItemRefund }, { "CHAMPION_HP", LuneContent.ChampionHp }, { "CHAMPION_DAMAGE", LuneContent.ChampionDamage }, + { "CHAMPION_BOUNTY", LuneContent.ChampionBounty }, { "CHAMPION_BOUNTY_PER_ROUND", LuneContent.ChampionBountyPerRound }, + { "MAX_BOOKINGS", LuneContent.MaxBookings }, { "BOSS_GROTTO_HP", LuneContent.BossGrottoHp }, { "BOSS_GROTTO_DAMAGE", LuneContent.BossGrottoDamage }, + { "BOSS_DEPLOY_HP", LuneContent.BossDeployHp }, { "BOSS_DEPLOY_DAMAGE", LuneContent.BossDeployDamage }, { "BOSS_BOUNTY", LuneContent.BossBounty }, + { "BOSS_BOUNTY_PER_ROUND", LuneContent.BossBountyPerRound }, { "BOSS_LOCK_ROUNDS", LuneContent.BossLockRounds }, { "BOSS_XP", LuneContent.BossXp }, + { "BUILDING_XP", LuneContent.BuildingXp }, + }; + var wrong = expected.Where(p => MiniJson.Num(constants[p.Key]) != p.Value).Select(p => p.Key).ToList(); + Check(wrong.Count == 0 && MiniJson.Str(constants["BOSS_MODEL"]) == LuneContent.BossModel, "content constants " + string.Join(", ", wrong)); + Check(MiniJson.Obj(data["match_roles"]).Keys.SequenceEqual(ContentData.MatchRoles.Keys) + && MiniJson.Obj(data["match_roles"]).All(p => ContentData.MatchRoles[p.Key] == MiniJson.Str(p.Value)), "troop roles in reference order"); + Check(MiniJson.Obj(data["hero_roles"]).All(p => ContentData.HeroRoles[p.Key] == MiniJson.Str(p.Value)), "hero roles"); + Check(MiniJson.Arr(data["row_order"]).Select(MiniJson.Str).SequenceEqual(ContentData.RowOrder), "formation row order"); + Check(MiniJson.Arr(data["bot_names"]).Select(MiniJson.Str).SequenceEqual(ContentData.BotNames), "bot names"); + Check(MiniJson.Arr(data["waves_melee"]).Select(MiniJson.Str).SequenceEqual(ContentData.WavesMelee), "melee monster types"); + var bot = MiniJson.Obj(data["bot_constants"]); + Check(MiniJson.Num(bot["BOSS_BAR"]) == LuneBot.BossBar && MiniJson.Num(bot["BOSS_BAR_STEP"]) == LuneBot.BossBarStep, "bot boss thresholds"); + } + + void CompareProfiles(OrderedMap expected) + { + Check(expected.Keys.SequenceEqual(ContentData.BotProfiles.Keys), "bot profiles in reference order (seed rotation)"); + foreach (KeyValuePair pair in expected) + { + var entry = MiniJson.Obj(pair.Value); + BotProfile profile = ContentData.BotProfiles[pair.Key]; + bool same = MiniJson.Num(entry["front"]) == profile.Front && MiniJson.Num(entry["melee"]) == profile.Melee && MiniJson.Num(entry["ranged"]) == profile.Ranged + && MiniJson.Num(entry["splash"]) == profile.Splash && MiniJson.Num(entry["support"]) == profile.Support + && MiniJson.Int(entry["upgrade_from"]) == profile.UpgradeFrom && MiniJson.Num(entry["support_lane"]) == profile.SupportLane + && MiniJson.Str(entry["hero"]) == profile.Hero && MiniJson.Int(entry["hero_round"]) == profile.HeroRound + && MiniJson.Arr(entry["items"]).Select(MiniJson.Str).SequenceEqual(profile.Items) + && MiniJson.Arr(entry["talents"]).Select(MiniJson.Int).SequenceEqual(profile.TalentChoices) + && MiniJson.Str(entry["champion"]) == profile.Champion + && (entry.ContainsKey("boss_from") ? MiniJson.Int(entry["boss_from"]) == profile.BossFrom && MiniJson.Int(entry["boss_troops"]) == profile.BossTroops : !profile.HuntsBoss); + Check(same, "bot profile " + pair.Key); + } + } + + void CompareBalance(OrderedMap expected) + { + LuneBalance balance = LuneBalance.Default(); + var actual = new Dictionary + { + { "sim_step", balance.SimStep }, { "combat_time_limit", balance.CombatTimeLimit }, { "march_speed_factor", balance.MarchSpeedFactor }, + { "aggro_radius", balance.AggroRadius }, { "leash_radius", balance.LeashRadius }, { "lane_half_width", balance.LaneHalfWidth }, + { "start_gold", balance.StartGold }, { "base_income", balance.BaseIncome }, { "income_per_round", balance.IncomePerRound }, + { "income_growth_cap", balance.IncomeGrowthCap }, { "supply_cap", balance.SupplyCap }, { "sell_refund", balance.SellRefund }, + { "lane_share", balance.LaneShare }, { "wave_base_count", balance.WaveBaseCount }, { "wave_count_every", balance.WaveCountEvery }, + { "wave_max_count", balance.WaveMaxCount }, { "wave_hp_growth", balance.WaveHpGrowth }, { "wave_damage_growth", balance.WaveDamageGrowth }, + { "wave_growth_quadratic", balance.WaveGrowthQuadratic }, { "monster_bounty_scale", balance.MonsterBountyScale }, + { "bounty_growth", balance.BountyGrowth }, { "tower_outer_hp", balance.TowerOuterHp }, { "tower_inner_hp", balance.TowerInnerHp }, + { "base_tower_hp", balance.BaseTowerHp }, { "core_hp", balance.CoreHp }, { "tower_damage", balance.TowerDamage }, + { "base_tower_damage", balance.BaseTowerDamage }, { "tower_range", balance.TowerRange }, { "tower_attack_interval", balance.TowerAttackInterval }, + { "building_radius", balance.BuildingRadius }, { "bounty_outer_tower", balance.BountyOuterTower }, { "bounty_inner_tower", balance.BountyInnerTower }, + { "bounty_base_tower", balance.BountyBaseTower }, { "inner_tower_fraction", balance.InnerTowerFraction }, + { "outer_tower_fraction", balance.OuterTowerFraction }, { "tower_side_offset", balance.TowerSideOffset }, + }; + var problems = new List(); + foreach (KeyValuePair pair in expected) + { + if (pair.Key == "monster_pool") + { + if (!MiniJson.Arr(pair.Value).Select(MiniJson.Str).SequenceEqual(balance.MonsterPool)) + problems.Add(pair.Key); + continue; + } + object value; + if (!actual.TryGetValue(pair.Key, out value)) + { + problems.Add("missing " + pair.Key); + continue; + } + if (MiniJson.Num(pair.Value) != Convert.ToDouble(value)) + problems.Add(pair.Key); + } + Check(problems.Count == 0, "balance defaults match lune_balance.gd " + string.Join(", ", problems)); + } + + void CompareMap(OrderedMap lanes, List buildings) + { + var map = new LuneMap(); + double worst = 0.0; + foreach (string lane in LuneMap.Lanes) + { + var expected = MiniJson.Obj(lanes[lane]); + LanePath path = map.LanePaths[lane]; + List points = MiniJson.Arr(expected["points"]); + bool countOk = points.Count == path.Points.Length; + double deviation = Math.Abs(MiniJson.Num(expected["length"]) - path.Length); + for (int i = 0; countOk && i < points.Count; i++) + { + List xy = MiniJson.Arr(points[i]); + deviation = Math.Max(deviation, Math.Max(Math.Abs(MiniJson.Num(xy[0]) - path.Points[i].X), Math.Abs(MiniJson.Num(xy[1]) - path.Points[i].Y))); + } + worst = Math.Max(worst, deviation); + Check(countOk && deviation <= GeometryTolerance, string.Format("{0} lane polyline and length match ({1} points, deviation {2:E2})", lane, path.Points.Length, deviation)); + } + bool buildingsOk = buildings.Count == map.Buildings.Count; + double buildingWorst = 0.0; + for (int i = 0; buildingsOk && i < buildings.Count; i++) + { + var expected = MiniJson.Obj(buildings[i]); + BuildingDef actual = map.Buildings[i]; + List position = MiniJson.Arr(expected["position"]); + buildingsOk = MiniJson.Str(expected["id"]) == actual.Id && MiniJson.Str(expected["tier"]) == actual.Tier && MiniJson.Str(expected["lane"]) == actual.Lane + && MiniJson.Num(expected["max_hp"]) == actual.MaxHp && MiniJson.Int(expected["bounty"]) == actual.Bounty; + buildingWorst = Math.Max(buildingWorst, Math.Abs(MiniJson.Num(expected["progress"]) - actual.Progress)); + buildingWorst = Math.Max(buildingWorst, Math.Max(Math.Abs(MiniJson.Num(position[0]) - actual.Position.X), Math.Abs(MiniJson.Num(position[1]) - actual.Position.Y))); + } + Check(buildingsOk && buildingWorst <= GeometryTolerance, string.Format("18 buildings in reference order, positions match (deviation {0:E2})", buildingWorst)); + Note(string.Format("map geometry: largest deviation lanes {0:E2} m, buildings {1:E2} m", worst, buildingWorst)); + } + } +} diff --git a/Assets/Luneraria/Tests/Core/CoreRulesSuite.cs b/Assets/Luneraria/Tests/Core/CoreRulesSuite.cs new file mode 100644 index 0000000..b4c5c13 --- /dev/null +++ b/Assets/Luneraria/Tests/Core/CoreRulesSuite.cs @@ -0,0 +1,390 @@ +using System; +using System.Collections.Generic; +using System.Linq; + +namespace Luneraria.Core.Tests +{ + /// + /// Port of tests/luneraria/test_lune_core.gd (91 checks in Godot): structure, symmetry, + /// building gates, victory and draw, endless waves, commands and ownership, rewards, + /// persistence, a full bot match and the exact mirror match. + /// + public sealed class CoreRulesSuite : CheckSuite + { + public override string Name { get { return "core"; } } + + static readonly List Bunds = new List { "glutpakt", "wurzelbund", "glutpakt", "wurzelbund", "glutpakt", "wurzelbund" }; + + static LuneMatch NewMatch(int seed = 7, int human = -1) + { + var state = new LuneMatch(); + state.Setup(new MatchOptions { Seed = seed, HumanSlot = human, Bunds = new List(Bunds) }); + return state; + } + + protected override void RunChecks() + { + TestStructure(); + TestSymmetry(); + TestGates(); + TestVictoryAndDraw(); + TestEndlessWaves(); + TestCommandsAndOwnership(); + TestRewards(); + TestPersistenceAndRestart(); + TestFullMatch(); + TestMirrorFairness(); + } + + void TestStructure() + { + LuneMatch state = NewMatch(); + Check(state.Players.Count == 6, "six player slots"); + var teams = new Dictionary(); + var roles = new HashSet(); + foreach (Player player in state.Players) + { + int count; + teams.TryGetValue(player.Team, out count); + teams[player.Team] = count + 1; + roles.Add(player.Team + "-" + player.Lane); + } + Check(teams.Count == 2 && teams[0] == 3 && teams[1] == 3, "exactly two teams of three"); + Check(roles.Count == 6, "six distinct owner roles (team x lane)"); + Check(LuneMap.Lanes.SequenceEqual(new[] { "top", "mid", "bot" }) && state.Map.LanePaths.Count == 3, "three lanes"); + int towers = 0; + int cores = 0; + var perTeamLane = new Dictionary(); + var baseTowers = new int[2]; + foreach (BuildingDef definition in state.Map.Buildings) + { + if (definition.Tier == "core") + { + cores += 1; + } + else + { + towers += 1; + if (definition.Tier == "base") + { + baseTowers[definition.Team] += 1; + } + else + { + string key = definition.Team + "-" + definition.Lane; + int count; + perTeamLane.TryGetValue(key, out count); + perTeamLane[key] = count + 1; + } + } + } + Check(towers == 16 && cores == 2, "sixteen towers and two Ancients"); + Check(perTeamLane.Count == 6 && perTeamLane.Values.All(v => v == 2), "two lane towers per team and lane"); + Check(baseTowers[0] == 2 && baseTowers[1] == 2, "two base towers per team"); + } + + void TestSymmetry() + { + var map = new LuneMap(); + foreach (string lane in LuneMap.Lanes) + { + LanePath path = map.LanePaths[lane]; + double worst = 0.0; + for (int i = 0; i < 21; i++) + { + double s = path.Length * (double)i / 20.0; + worst = GdMath.Max(worst, LuneMap.Mirror(path.PointAt(s)).DistanceTo(path.PointAt(path.Length - s))); + } + Check(worst < 0.001, lane + " lane is its own mirror image (team fairness)"); + } + Check(Math.Abs(map.LanePaths["top"].Length - map.LanePaths["bot"].Length) < 0.001, "top and bottom lanes have equal length"); + foreach (BuildingDef definition in map.Buildings) + { + if (definition.Team == 0) + { + BuildingDef twin = map.BuildingDef(definition.Id.Replace("blau", "rot")); + Check(LuneMap.Mirror(definition.Position).DistanceTo(twin.Position) < 0.001 && GdMath.IsEqualApprox(definition.MaxHp, twin.MaxHp), "mirrored building " + definition.Id); + } + } + foreach (string lane in LuneMap.Lanes) + Check(map.LanePoint(1, lane, 7.0, 1.2).DistanceTo(LuneMap.Mirror(map.LanePoint(0, lane, 7.0, 1.2))) < 0.001, "mirrored spawn points on " + lane); + Check(LuneMap.Mirror(LuneMap.Grotto).DistanceTo(LuneMap.Grotto) < 0.001, "grotto equidistant for both teams"); + LanePath mid = map.LanePaths["mid"]; + double grottoGap = mid.PointAt(mid.Project(LuneMap.Grotto)).DistanceTo(LuneMap.Grotto); + Check(grottoGap > 8.0, string.Format("grotto lies beside, not on, the mid lane ({0:0.0} m)", grottoGap)); + } + + void TestGates() + { + var map = new LuneMap(); + var alive = new Dictionary(); + foreach (BuildingDef definition in map.Buildings) + alive[definition.Id] = true; + Func gate = id => LuneMap.IsAttackable(map.BuildingDef(id), alive); + Check(gate("rot_top_outer") && !gate("rot_top_inner"), "outer before inner tower"); + Check(!gate("rot_base_1") && !gate("rot_ancient"), "base and Ancient protected at start"); + alive["rot_top_outer"] = false; + Check(gate("rot_top_inner") && !gate("rot_base_1"), "inner opens after outer; base still closed"); + alive["rot_mid_outer"] = false; + alive["rot_bot_outer"] = false; + Check(!gate("rot_base_1"), "outer towers of all lanes do not open the base"); + alive["rot_top_inner"] = false; + Check(gate("rot_base_1") && gate("rot_base_2") && !gate("rot_ancient"), "one broken lane opens the base, not the Ancient"); + Check(gate("rot_mid_inner") && gate("rot_bot_inner"), "towers of other lanes keep working and stay attackable in order"); + alive["rot_base_1"] = false; + Check(!gate("rot_ancient"), "Ancient needs both base towers down"); + alive["rot_base_2"] = false; + Check(gate("rot_ancient"), "Ancient vulnerable after both base towers"); + // Gate applies to every damage source inside combat, including splash. + var combat = new LuneCombat(map, LuneBalance.Default(), 1); + LuneUnit inner = combat.AddBuilding(map.BuildingDef("rot_top_inner"), 1000.0); + combat.AddBuilding(map.BuildingDef("rot_top_outer"), 1000.0); + Dictionary gates = combat.AliveMap(); + combat.QueueDamage(inner, 500.0, gates); + Check(!combat.HasPendingDamage(inner), "locked inner tower ignores queued damage (ranged/splash/DoT)"); + } + + static LuneCombat Duel(double coreHpA, double coreHpB) + { + var map = new LuneMap(); + var combat = new LuneCombat(map, LuneBalance.Default(), 1); + foreach (BuildingDef definition in map.Buildings) + { + if (definition.Tier == "core") + combat.AddBuilding(definition, definition.Team == 0 ? coreHpA : coreHpB); + else + combat.AddBuilding(definition, 0.0); + } + return combat; + } + + static LuneUnit Attacker(LuneCombat combat, int team, double damage) + { + UnitDef definition = DataCatalog.GetUnit("g05"); + definition.Damage = damage; + LuneUnit unit = combat.Spawn("troop", team, "mid", definition, 1.0, 0.0); + unit.Position = combat.Map.CorePosition(1 - team) + new Vec2(2.5, 0.0).Rotated(team); + unit.ReachedBase = true; + return unit; + } + + static void RunSteps(LuneCombat combat, int count) + { + for (int i = 0; i < count; i++) + { + combat.Step(); + if (combat.Finished) + break; + } + } + + void TestVictoryAndDraw() + { + LuneCombat combat = Duel(12000.0, 30.0); + Attacker(combat, 0, 200.0); + RunSteps(combat, 200); + Check(combat.Finished && combat.EndReason == "core" && combat.DestroyedCores.SequenceEqual(new[] { 1 }), "destroying an Ancient ends the combat with a core result"); + LuneCombat draw = Duel(30.0, 30.0); + Attacker(draw, 1, 200.0); + Attacker(draw, 0, 200.0); + RunSteps(draw, 200); + Check(draw.DestroyedCores.Count == 2, "both Ancients in the same step are both recorded"); + LuneMatch state = NewMatch(); + state.BeginCombat(); + state.Combat.DestroyedCores.Clear(); + state.Combat.DestroyedCores.Add(0); + state.Combat.DestroyedCores.Add(1); + state.Combat.Finished = true; + state.Combat.EndReason = "core"; + state.Settle(); + Check(state.Phase == Phase.Over && state.Winner == LuneMatch.Draw, "simultaneous Ancient loss is a draw"); + // Unit order must not decide: reversing the spawn order gives the same result. + LuneCombat reversed = Duel(30.0, 30.0); + Attacker(reversed, 0, 200.0); + Attacker(reversed, 1, 200.0); + RunSteps(reversed, 200); + Check(reversed.DestroyedCores.Count == 2 && reversed.Steps == draw.Steps, "processing order gives no advantage"); + var timeout = new LuneMatch(); + timeout.Setup(new MatchOptions { Seed = 3, HumanSlot = -1 }); + timeout.BeginCombat(); + timeout.Combat.Elapsed = timeout.Balance.CombatTimeLimit; + timeout.StepCombat(); + Check(timeout.Combat.EndReason == "timeout" && timeout.Phase == Phase.Planning && timeout.Winner == LuneMatch.Ongoing, "combat time window ends the phase, never the match"); + Check(timeout.CoreHp(0) == timeout.Balance.CoreHp && timeout.CoreHp(1) == timeout.Balance.CoreHp, "time window causes no hidden core damage"); + } + + void TestEndlessWaves() + { + LuneBalance balance = LuneBalance.Default(); + double previous = 0.0; + foreach (int roundNumber in new[] { 1, 5, 8, 20, 21, 50, 200, 5000, 1000000 }) + { + List wave = LuneWaves.Build(balance, roundNumber); + double total = 0.0; + bool finite = true; + foreach (UnitDef monster in wave) + { + total += monster.MaxHp + monster.Damage * 10.0; + finite = finite && !double.IsInfinity(monster.MaxHp) && !double.IsNaN(monster.MaxHp) && !double.IsInfinity(monster.Damage) && monster.Bounty > 0; + } + Check(finite && wave.Count <= balance.WaveMaxCount && wave.Count >= 1, string.Format("wave {0} finite and capped ({1} monsters)", roundNumber, wave.Count)); + Check(total > previous, string.Format("wave {0} stronger than the previous sample", roundNumber)); + previous = total; + } + LuneMatch state = NewMatch(11); + state.RoundNumber = 21; + state.BeginCombat(); + int monsters = state.Combat.Units.Count(u => u.Kind == "monster"); + Check(monsters == 6 * LuneWaves.MonsterCount(balance, 21), "round 21 spawns ordinary waves; no final wave logic"); + state.FinishCombat(); + Check(state.Phase != Phase.Over || state.Winner != LuneMatch.Ongoing, "no match end without a core result"); + Check(state.RoundNumber == 22 || state.Phase == Phase.Over, "round counter continues after 20"); + } + + void TestCommandsAndOwnership() + { + LuneMatch state = NewMatch(5, 1); + int gold = state.GoldOf(1); + Check(!state.Submit(1, Command.Buy("g01")).Ok, "buying another Bund's troop is rejected"); + CommandResult bought = state.Submit(1, Command.Buy("w01")); + Check(bought.Ok && state.GoldOf(1) == gold - 50, "buy costs exactly the catalogue price"); + string uid = state.Players[1].Draft.Roster[0].Uid; + Check(!state.Submit(0, Command.Upgrade(uid)).Ok, "foreign unit id is rejected"); + Check(!state.Submit(1, Command.Upgrade("p1-9999")).Ok, "unknown unit id is rejected"); + Check(state.Players[1].Roster.Count == 0, "draft purchases are not committed before the phase change"); + Check(state.Submit(1, Command.Assign(uid, "top")).Ok && !state.Submit(1, Command.Assign(uid, "grotte")).Ok, "lane assignment validated"); + state.Submit(1, Command.Sell(uid)); + Check(state.GoldOf(1) == gold, "cancelling a purchase in the same planning refunds fully"); + state.Submit(1, Command.Buy("w01")); + state.Players[1].Draft.Gold = -5; + state.BeginCombat(); + Check(state.Players[1].Roster.Count == 0 && state.Players[1].Gold == gold, "invalid draft is rejected atomically at the phase change"); + state.FinishCombat(); + LuneMatch cap = NewMatch(6, 0); + cap.Players[0].Draft.Gold = 100000; + for (int i = 0; i < cap.Balance.SupplyCap + 3; i++) + cap.Submit(0, Command.Buy("g01")); + Check(cap.Players[0].Draft.Roster.Count == cap.Balance.SupplyCap, "supply cap enforced"); + Check(!cap.Submit(0, Command.Buy("g01")).Ok && cap.Phase == Phase.Planning, "no purchases beyond the cap"); + cap.BeginCombat(); + Check(!cap.Submit(0, Command.Buy("g03")).Ok, "no commands during combat"); + LuneMatch bots = NewMatch(9); + int[] before = bots.Players.Select(p => p.Gold).ToArray(); + for (int slot = 0; slot < 6; slot++) + LuneBot.Plan(bots, slot); + bool spentOk = true; + for (int slot = 0; slot < 6; slot++) + { + int invested = bots.Players[slot].Draft.Roster.Sum(e => e.Invested); + spentOk = spentOk && invested + bots.Players[slot].Draft.Gold == before[slot]; + } + Check(spentOk, "bots spend exactly their own gold, no extra resources"); + } + + void TestRewards() + { + LuneMatch state = NewMatch(4); + state.BeginCombat(); + LuneCombat combat = state.Combat; + combat.Events.Clear(); + combat.Events.Add(new CombatEvent { Serial = 1, Team = 1, Lane = "top", Zone = "lane", Kind = "monster", Bounty = 101 }); + combat.Events.Add(new CombatEvent { Serial = 2, Team = 1, Lane = "top", Zone = "lane", Kind = "monster", Bounty = 101 }); + combat.Events.Add(new CombatEvent { Serial = 3, Team = 0, Lane = "mid", Zone = "lane", Kind = "tower", Bounty = 151, BuildingId = "blau_mid_outer" }); + combat.Events.Add(new CombatEvent { Serial = 4, Team = 0, Lane = "bot", Zone = "lane", Kind = "troop", Bounty = 0 }); + combat.Finished = true; + combat.EndReason = "cleared"; + int[] goldBefore = state.Players.Select(p => p.Gold).ToArray(); + state.Settle(); + int[] gains = state.LastSettlement.Gains; + Check(gains[0] + gains[1] + gains[2] == 202, "each monster death pays exactly once, total 2 x 101 to Blau"); + Check(gains[0] >= 50 + 50 && gains[0] - gains[1] >= 90, "Top lane player of the killing team gets the lane share"); + Check(gains[3] + gains[4] + gains[5] == 151, "tower bounty exactly once to Rot"); + Check(Math.Abs(gains[3] - gains[4]) <= 1 && Math.Abs(gains[4] - gains[5]) <= 1, "tower bounty split evenly with integer remainder"); + int income = state.LastSettlement.Income; + bool paid = true; + for (int slot = 0; slot < 6; slot++) + paid = paid && state.Players[slot].Gold == goldBefore[slot] + gains[slot] + income; + Check(paid, "settlement credits gains plus income, nothing else"); + Check(gains.Sum() == 353, "persistent troop deaths pay nothing"); + } + + void TestPersistenceAndRestart() + { + LuneMatch state = NewMatch(8, 0); + state.Submit(0, Command.Buy("g03")); + state.SetReady(0); + string uid = state.Players[0].Draft.Roster[0].Uid; + state.BeginCombat(); + state.Combat.Buildings["blau_mid_outer"].Hp -= 1234.0; + LuneUnit fallen = state.Combat.Units.First(u => u.PersistentUid == uid); + fallen.Hp = 0.0; + fallen.Alive = false; + state.FinishCombat(); + Check(state.Phase == Phase.Planning && state.RoundNumber == 2, "round advances to planning"); + Check(state.Players[0].Roster.Count == 1 && state.Players[0].Roster[0].Uid == uid, "fallen persistent troop returns to the roster"); + Check(GdMath.IsEqualApprox(state.BuildingHp["blau_mid_outer"], state.Balance.TowerOuterHp - 1234.0) || state.BuildingHp["blau_mid_outer"] < state.Balance.TowerOuterHp - 1234.0, "building damage persists between rounds"); + state.BeginCombat(); + bool healed = false; + foreach (LuneUnit unit in state.Combat.Units) + { + if (unit.PersistentUid == uid) + healed = unit.Hp == unit.MaxHp && unit.Effects.Count == 0 && unit.Dots.Count == 0; + } + Check(healed, "returning troop starts the next combat healed and without effects"); + state.FinishCombat(); + LuneMatch fresh = NewMatch(8, 0); + Check(fresh.Players[0].Roster.Count == 0 && fresh.RoundNumber == 1 && fresh.BuildingHp["blau_mid_outer"] == fresh.Balance.TowerOuterHp, "new match starts without previous progress"); + } + + void TestFullMatch() + { + LuneMatch state = NewMatch(2); + int limit = 80; + while (state.Phase != Phase.Over && state.RoundNumber <= limit) + { + for (int slot = 0; slot < 6; slot++) + LuneBot.Plan(state, slot); + state.BeginCombat(); + state.FinishCombat(); + } + Check(state.Phase == Phase.Over, "a six-bot match reaches a regular Ancient result (seed 2)"); + Check(state.Winner == 0 || state.Winner == 1 || state.Winner == LuneMatch.Draw, "result is Blau, Rot or draw"); + int coresDown = (state.CoreHp(0) <= 0.0 ? 1 : 0) + (state.CoreHp(1) <= 0.0 ? 1 : 0); + Check(coresDown >= 1, "the result follows an actually destroyed Ancient"); + Note(string.Format("full match seed 2 -> {0} after {1} rounds", state.Winner == LuneMatch.Draw ? "draw" : (state.Winner == 0 ? "Blau" : "Rot"), state.History.Count)); + } + + void TestMirrorFairness() + { + // Identical Bund and deterministic bot profile on all six slots: the match must stay an + // exact mirror image. Any drift would reveal an order- or id-dependent team advantage. + foreach (string bund in new[] { "glutpakt", "wurzelbund" }) + { + var state = new LuneMatch(); + state.Setup(new MatchOptions { Seed = 3, HumanSlot = -1, Bunds = Enumerable.Repeat(bund, 6).ToList() }); + bool mirrored = true; + for (int roundIndex = 0; roundIndex < 12; roundIndex++) + { + for (int slot = 0; slot < 6; slot++) + LuneBot.Plan(state, slot, "verteidigung"); + state.BeginCombat(); + state.FinishCombat(); + foreach (BuildingDef definition in state.Map.Buildings) + { + if (definition.Team == 0) + { + string twin = definition.Id.Replace("blau", "rot"); + mirrored = mirrored && GdMath.IsEqualApprox(state.BuildingHp[definition.Id], state.BuildingHp[twin]); + } + } + for (int slot = 0; slot < 3; slot++) + mirrored = mirrored && state.Players[slot].Gold == state.Players[slot + 3].Gold; + if (state.Phase == Phase.Over) + break; + } + Check(mirrored, bund + " mirror match stays exactly symmetric for 12 rounds (buildings and gold)"); + Check(state.Phase != Phase.Over || state.Winner == LuneMatch.Draw, bund + " mirror match never produces a one-sided winner"); + } + } + } +} diff --git a/Assets/Luneraria/Tests/Core/DeterminismSuite.cs b/Assets/Luneraria/Tests/Core/DeterminismSuite.cs new file mode 100644 index 0000000..24dacac --- /dev/null +++ b/Assets/Luneraria/Tests/Core/DeterminismSuite.cs @@ -0,0 +1,112 @@ +using System.Collections.Generic; +using System.Linq; + +namespace Luneraria.Core.Tests +{ + /// + /// Determinism of the C# core: the same inputs give the same match, repeatedly, with no + /// dependence on hashing, object identity, wall-clock time or the order in which matches run. + /// Each .NET run also randomises string hashing per process, so passing golden replays in + /// several processes shows that no rule depends on dictionary iteration order. + /// + public sealed class DeterminismSuite : CheckSuite + { + public override string Name { get { return "determinism"; } } + + protected override void RunChecks() + { + foreach (int seed in new[] { 5, 13, 28 }) + { + string first = Fingerprint(Play(seed)); + string second = Fingerprint(Play(seed)); + Check(first == second, "seed " + seed + ": two runs of the same match are identical"); + } + // Interleaving two matches must not change either (no shared static state). + LuneMatch a = New(7); + LuneMatch b = New(9); + for (int round = 0; round < 6; round++) + { + foreach (LuneMatch match in new[] { a, b }) + { + if (match.Phase == Phase.Over) + continue; + for (int slot = 0; slot < 6; slot++) + LuneBot.Plan(match, slot); + match.BeginCombat(); + } + bool running = true; + while (running) + { + running = false; + foreach (LuneMatch match in new[] { a, b }) + { + if (match.Phase == Phase.Combat) + { + match.StepCombat(); + running = true; + } + } + } + } + LuneMatch aAlone = New(7); + LuneMatch bAlone = New(9); + for (int round = 0; round < 6; round++) + { + foreach (LuneMatch match in new[] { aAlone, bAlone }) + { + if (match.Phase == Phase.Over) + continue; + for (int slot = 0; slot < 6; slot++) + LuneBot.Plan(match, slot); + match.BeginCombat(); + match.FinishCombat(); + } + } + Check(Fingerprint(a) == Fingerprint(aAlone) && Fingerprint(b) == Fingerprint(bAlone), "interleaved matches equal matches run alone (no shared state)"); + // Unit ids are sequential per combat and follow spawn order, never object identity. + LuneMatch ids = New(4); + for (int slot = 0; slot < 6; slot++) + LuneBot.Plan(ids, slot); + ids.BeginCombat(); + Check(ids.Combat.Units.Select(u => u.Id).SequenceEqual(Enumerable.Range(1, ids.Combat.Units.Count)), "unit ids are 1..n in spawn order"); + // The combat step is fixed; the simulation never reads a clock or a frame rate. + Check(ids.Balance.SimStep == 0.05, "fixed simulation step of 0.05 s (20 steps per combat second)"); + } + + static LuneMatch New(int seed) + { + var match = new LuneMatch(); + match.Setup(new MatchOptions { Seed = seed, HumanSlot = -1 }); + return match; + } + + static LuneMatch Play(int seed) + { + LuneMatch match = New(seed); + while (match.Phase != Phase.Over && match.RoundNumber <= 60) + { + for (int slot = 0; slot < 6; slot++) + LuneBot.Plan(match, slot); + match.BeginCombat(); + match.FinishCombat(); + } + return match; + } + + static string Fingerprint(LuneMatch match) + { + var parts = new List { match.RoundNumber + "/" + match.Winner + "/" + match.Phase }; + foreach (Player player in match.Players) + { + parts.Add(player.Gold + ":" + player.Earned + ":" + player.Spent + ":" + string.Join(",", player.Roster.Select(e => e.Uid + e.TypeId + e.Lane))); + if (player.Hero != null) + parts.Add(player.Hero.HeroId + player.Hero.Xp + string.Join("+", player.Hero.Items) + string.Join("+", player.Hero.Talents)); + } + foreach (KeyValuePair pair in match.BuildingHp) + parts.Add(pair.Key + "=" + pair.Value.ToString("R", System.Globalization.CultureInfo.InvariantCulture)); + foreach (HistoryEntry entry in match.History) + parts.Add(entry.Round + entry.EndReason + entry.CombatTime.ToString("R", System.Globalization.CultureInfo.InvariantCulture) + string.Join(",", entry.Gold)); + return string.Join("|", parts); + } + } +} diff --git a/Assets/Luneraria/Tests/Core/Golden/content.json b/Assets/Luneraria/Tests/Core/Golden/content.json new file mode 100644 index 0000000..8303010 --- /dev/null +++ b/Assets/Luneraria/Tests/Core/Golden/content.json @@ -0,0 +1,2048 @@ +{ + "engine": "4.7.2-stable (official)", + "units": { + "g01": { + "id": "g01", + "display_name": "Kohlenbeißer", + "cost": 45, + "upgrade_id": "g02", + "max_hp": 260.0, + "damage": 17.0, + "attack_type": 0, + "armor_type": 0, + "attack_range": 1.1, + "speed": 2.4, + "ability": "g01", + "leak_value": 0, + "bounty": 0, + "ability_description": "Jeder 3. Treffer: Brand, 4 Schaden/s für 3 s." + }, + "g02": { + "id": "g02", + "display_name": "Schlackenklaue", + "cost": 90, + "upgrade_id": "", + "max_hp": 690.0, + "damage": 44.0, + "attack_type": 0, + "armor_type": 1, + "attack_range": 1.2, + "speed": 2.4, + "ability": "g02", + "leak_value": 0, + "bounty": 0, + "ability_description": "Jeder 3. Treffer: Brand, 12 Schaden/s für 3 s." + }, + "g03": { + "id": "g03", + "display_name": "Schlackenwacht", + "cost": 70, + "upgrade_id": "g04", + "max_hp": 650.0, + "damage": 11.0, + "attack_type": 0, + "armor_type": 1, + "attack_range": 1.2, + "speed": 2.4, + "ability": "g03", + "leak_value": 0, + "bounty": 0, + "ability_description": "Erste 8 s: 15 % weniger erlittener Schaden." + }, + "g04": { + "id": "g04", + "display_name": "Basaltbastion", + "cost": 150, + "upgrade_id": "", + "max_hp": 1650.0, + "damage": 27.0, + "attack_type": 0, + "armor_type": 1, + "attack_range": 1.4, + "speed": 2.4, + "ability": "g04", + "leak_value": 0, + "bounty": 0, + "ability_description": "Erste 10 s: 25 % weniger Schaden, danach 10 %." + }, + "g05": { + "id": "g05", + "display_name": "Funkenlanze", + "cost": 65, + "upgrade_id": "g06", + "max_hp": 240.0, + "damage": 24.0, + "attack_type": 1, + "armor_type": 0, + "attack_range": 5.5, + "speed": 2.0, + "ability": "g05", + "leak_value": 0, + "bounty": 0, + "ability_description": "Jeder 4. Treffer: 50 % zusätzlicher Grundschaden." + }, + "g06": { + "id": "g06", + "display_name": "Glasballiste", + "cost": 140, + "upgrade_id": "", + "max_hp": 640.0, + "damage": 65.0, + "attack_type": 1, + "armor_type": 0, + "attack_range": 6.5, + "speed": 2.0, + "ability": "g06", + "leak_value": 0, + "bounty": 0, + "ability_description": "Jeder 4. Treffer: 75 % zusätzlicher Grundschaden." + }, + "g07": { + "id": "g07", + "display_name": "Aschenwerfer", + "cost": 95, + "upgrade_id": "g08", + "max_hp": 310.0, + "damage": 23.0, + "attack_type": 2, + "armor_type": 0, + "attack_range": 4.5, + "speed": 2.0, + "ability": "g07", + "leak_value": 0, + "bounty": 0, + "ability_description": "Jeder Treffer: 30 % Flächenschaden an bis zu 3 weiteren Zielen in 1,5 m." + }, + "g08": { + "id": "g08", + "display_name": "Kraterrufer", + "cost": 190, + "upgrade_id": "", + "max_hp": 820.0, + "damage": 58.0, + "attack_type": 2, + "armor_type": 1, + "attack_range": 5.0, + "speed": 2.0, + "ability": "g08", + "leak_value": 0, + "bounty": 0, + "ability_description": "Jeder Treffer: 40 % Flächenschaden an bis zu 4 weiteren Zielen in 2 m." + }, + "g09": { + "id": "g09", + "display_name": "Herdhüter", + "cost": 85, + "upgrade_id": "g10", + "max_hp": 420.0, + "damage": 12.0, + "attack_type": 2, + "armor_type": 2, + "attack_range": 3.5, + "speed": 2.0, + "ability": "g09", + "leak_value": 0, + "bounty": 0, + "ability_description": "Alle 6 s: bis zu 3 Verbündete in 3 m erhalten für 4 s +10 % Grundangriffsschaden." + }, + "g10": { + "id": "g10", + "display_name": "Sonnenesse", + "cost": 170, + "upgrade_id": "", + "max_hp": 1080.0, + "damage": 30.0, + "attack_type": 2, + "armor_type": 2, + "attack_range": 4.0, + "speed": 2.0, + "ability": "g10", + "leak_value": 0, + "bounty": 0, + "ability_description": "Alle 6 s: bis zu 4 Verbündete in 4 m erhalten für 4 s +15 % Grundangriffsschaden und 45 Heilung." + }, + "w01": { + "id": "w01", + "display_name": "Dornhopser", + "cost": 50, + "upgrade_id": "w02", + "max_hp": 290.0, + "damage": 18.0, + "attack_type": 0, + "armor_type": 0, + "attack_range": 1.1, + "speed": 2.4, + "ability": "w01", + "leak_value": 0, + "bounty": 0, + "ability_description": "Jeder 3. Treffer: −20 % Bewegung für 2 s." + }, + "w02": { + "id": "w02", + "display_name": "Rankenschnapper", + "cost": 100, + "upgrade_id": "", + "max_hp": 800.0, + "damage": 47.0, + "attack_type": 0, + "armor_type": 1, + "attack_range": 1.3, + "speed": 2.4, + "ability": "w02", + "leak_value": 0, + "bounty": 0, + "ability_description": "Jeder 3. Treffer: −30 % Bewegung und −10 % Angriffstempo für 3 s." + }, + "w03": { + "id": "w03", + "display_name": "Korkrücken", + "cost": 75, + "upgrade_id": "w04", + "max_hp": 620.0, + "damage": 12.0, + "attack_type": 1, + "armor_type": 1, + "attack_range": 1.2, + "speed": 2.4, + "ability": "w03", + "leak_value": 0, + "bounty": 0, + "ability_description": "Heilt sich alle 5 s um 35 HP, sobald er verwundet ist." + }, + "w04": { + "id": "w04", + "display_name": "Ringborke", + "cost": 155, + "upgrade_id": "", + "max_hp": 1560.0, + "damage": 31.0, + "attack_type": 1, + "armor_type": 1, + "attack_range": 1.4, + "speed": 2.4, + "ability": "w04", + "leak_value": 0, + "bounty": 0, + "ability_description": "Heilt sich alle 5 s um 100 HP, sobald er verwundet ist." + }, + "w05": { + "id": "w05", + "display_name": "Samenschleuder", + "cost": 60, + "upgrade_id": "w06", + "max_hp": 230.0, + "damage": 23.0, + "attack_type": 1, + "armor_type": 0, + "attack_range": 5.5, + "speed": 2.0, + "ability": "w05", + "leak_value": 0, + "bounty": 0, + "ability_description": "Jeder 4. Treffer: Keimbrand, 3 Schaden/s für 4 s." + }, + "w06": { + "id": "w06", + "display_name": "Zapfenkrone", + "cost": 135, + "upgrade_id": "", + "max_hp": 630.0, + "damage": 61.0, + "attack_type": 1, + "armor_type": 0, + "attack_range": 6.0, + "speed": 2.0, + "ability": "w06", + "leak_value": 0, + "bounty": 0, + "ability_description": "Jeder 4. Treffer: Keimbrand, 10 Schaden/s für 4 s." + }, + "w07": { + "id": "w07", + "display_name": "Sporenkelch", + "cost": 100, + "upgrade_id": "w08", + "max_hp": 370.0, + "damage": 22.0, + "attack_type": 2, + "armor_type": 2, + "attack_range": 4.0, + "speed": 2.0, + "ability": "w07", + "leak_value": 0, + "bounty": 0, + "ability_description": "Jeder 3. Treffer: 60 % Grundschaden an bis zu 3 weiteren Zielen in 2 m." + }, + "w08": { + "id": "w08", + "display_name": "Pilzkathedrale", + "cost": 195, + "upgrade_id": "", + "max_hp": 940.0, + "damage": 59.0, + "attack_type": 2, + "armor_type": 2, + "attack_range": 4.5, + "speed": 2.0, + "ability": "w08", + "leak_value": 0, + "bounty": 0, + "ability_description": "Jeder 3. Treffer: 80 % Grundschaden an bis zu 4 weiteren Zielen in 2,5 m." + }, + "w09": { + "id": "w09", + "display_name": "Tauhüter", + "cost": 90, + "upgrade_id": "w10", + "max_hp": 390.0, + "damage": 10.0, + "attack_type": 2, + "armor_type": 0, + "attack_range": 4.0, + "speed": 2.0, + "ability": "w09", + "leak_value": 0, + "bounty": 0, + "ability_description": "Alle 4 s: heilt den am stärksten verwundeten Verbündeten in 4 m um 65 HP." + }, + "w10": { + "id": "w10", + "display_name": "Quellgeflecht", + "cost": 180, + "upgrade_id": "", + "max_hp": 1000.0, + "damage": 27.0, + "attack_type": 2, + "armor_type": 2, + "attack_range": 4.5, + "speed": 2.0, + "ability": "w10", + "leak_value": 0, + "bounty": 0, + "ability_description": "Alle 4 s: heilt bis zu 3 verwundete Verbündete in 4,5 m um je 80 HP." + } + }, + "enemies": { + "e01": { + "id": "e01", + "display_name": "Splitterling", + "max_hp": 90.0, + "damage": 6.0, + "attack_type": 0, + "armor_type": 0, + "attack_range": 1.0, + "speed": 3.0, + "ability": "e01", + "leak_value": 25, + "bounty": 3 + }, + "e02": { + "id": "e02", + "display_name": "Schalenläufer", + "max_hp": 240.0, + "damage": 9.0, + "attack_type": 1, + "armor_type": 1, + "attack_range": 1.2, + "speed": 2.0, + "ability": "e02", + "leak_value": 55, + "bounty": 6 + }, + "e03": { + "id": "e03", + "display_name": "Nebelrest", + "max_hp": 150.0, + "damage": 11.0, + "attack_type": 2, + "armor_type": 2, + "attack_range": 3.5, + "speed": 2.2, + "ability": "e03", + "leak_value": 40, + "bounty": 5 + }, + "e04": { + "id": "e04", + "display_name": "Fadenschütze", + "max_hp": 130.0, + "damage": 12.0, + "attack_type": 1, + "armor_type": 0, + "attack_range": 6.0, + "speed": 2.4, + "ability": "e04", + "leak_value": 35, + "bounty": 5 + }, + "e05": { + "id": "e05", + "display_name": "Bruchstampfer", + "max_hp": 480.0, + "damage": 16.0, + "attack_type": 0, + "armor_type": 1, + "attack_range": 1.4, + "speed": 1.6, + "ability": "e05", + "leak_value": 90, + "bounty": 10 + }, + "e06": { + "id": "e06", + "display_name": "Knotenrufer", + "max_hp": 190.0, + "damage": 7.0, + "attack_type": 2, + "armor_type": 2, + "attack_range": 4.0, + "speed": 2.0, + "ability": "e06", + "leak_value": 45, + "bounty": 6 + }, + "e07": { + "id": "e07", + "display_name": "Bruchhirsch", + "max_hp": 1100.0, + "damage": 28.0, + "attack_type": 0, + "armor_type": 0, + "attack_range": 1.4, + "speed": 1.8, + "ability": "e07", + "leak_value": 250, + "bounty": 30, + "is_boss": true + }, + "e08": { + "id": "e08", + "display_name": "Riegelkoloss", + "max_hp": 1400.0, + "damage": 30.0, + "attack_type": 1, + "armor_type": 1, + "attack_range": 1.5, + "speed": 1.5, + "ability": "e08", + "leak_value": 330, + "bounty": 40, + "is_boss": true + }, + "e09": { + "id": "e09", + "display_name": "Maskenrichter", + "max_hp": 1800.0, + "damage": 34.0, + "attack_type": 2, + "armor_type": 2, + "attack_range": 5.0, + "speed": 1.8, + "ability": "e09", + "leak_value": 400, + "bounty": 50, + "is_boss": true + }, + "e10": { + "id": "e10", + "display_name": "Schlundkrone", + "max_hp": 3000.0, + "damage": 50.0, + "attack_type": 1, + "armor_type": 1, + "attack_range": 1.5, + "speed": 1.3, + "ability": "e10", + "leak_value": 600, + "bounty": 70, + "is_boss": true + } + }, + "sends": { + "s01": { + "id": "s01", + "display_name": "Nadelspäher", + "cost": 20, + "income_gain": 3, + "max_hp": 100.0, + "damage": 8.0, + "attack_type": 1, + "armor_type": 0, + "attack_range": 4.5, + "speed": 2.8, + "ability": "s01", + "leak_value": 30, + "bounty": 3 + }, + "s02": { + "id": "s02", + "display_name": "Rostschieber", + "cost": 40, + "income_gain": 5, + "max_hp": 240.0, + "damage": 8.0, + "attack_type": 0, + "armor_type": 1, + "attack_range": 1.2, + "speed": 1.8, + "ability": "s02", + "leak_value": 55, + "bounty": 6 + }, + "s03": { + "id": "s03", + "display_name": "Dunstsänger", + "cost": 80, + "income_gain": 9, + "max_hp": 320.0, + "damage": 10.0, + "attack_type": 2, + "armor_type": 2, + "attack_range": 5.0, + "speed": 2.0, + "ability": "s03", + "leak_value": 70, + "bounty": 9 + }, + "s04": { + "id": "s04", + "display_name": "Keilbrecher", + "cost": 130, + "income_gain": 12, + "max_hp": 650.0, + "damage": 20.0, + "attack_type": 1, + "armor_type": 1, + "attack_range": 1.3, + "speed": 1.6, + "ability": "s04", + "leak_value": 120, + "bounty": 14 + }, + "s05": { + "id": "s05", + "display_name": "Risszehrer", + "cost": 200, + "income_gain": 17, + "max_hp": 1000.0, + "damage": 30.0, + "attack_type": 2, + "armor_type": 2, + "attack_range": 4.0, + "speed": 1.7, + "ability": "s05", + "leak_value": 180, + "bounty": 20 + } + }, + "faction_names": { + "glutpakt": "Glutpakt", + "wurzelbund": "Wurzelbund" + }, + "armor_names": [ + "Leicht", + "Schwer", + "Ätherisch" + ], + "damage_names": [ + "Klinge", + "Durchschlag", + "Impuls" + ], + "heroes": { + "held_ringborke": { + "name": "Ringborke", + "title": "Wächterin der Wurzeln", + "model": "w04", + "cost": 260, + "role": "Front / Schutz", + "provisional": true, + "def": { + "max_hp": 2200.0, + "damage": 34.0, + "attack_type": 1, + "armor_type": 1, + "attack_range": 1.4, + "speed": 2.4, + "ability": "w04" + }, + "summary": "Hält die Front, heilt sich selbst und schützt nahe Verbündete." + }, + "held_quellgeflecht": { + "name": "Quellgeflecht", + "title": "Hüterin der Quelle", + "model": "w10", + "cost": 260, + "role": "Unterstützung / Heilung", + "provisional": true, + "def": { + "max_hp": 1300.0, + "damage": 28.0, + "attack_type": 2, + "armor_type": 2, + "attack_range": 4.5, + "speed": 2.0, + "ability": "w10" + }, + "summary": "Heilt Verbündete in 4,5 m und stärkt die Armee im Gefecht." + }, + "held_funkenlanze": { + "name": "Funkenlanze", + "title": "Schützin des Glutpakts", + "model": "g05", + "cost": 260, + "role": "Fernkampf / Schaden", + "provisional": true, + "def": { + "max_hp": 950.0, + "damage": 46.0, + "attack_type": 1, + "armor_type": 0, + "attack_range": 6.0, + "speed": 2.0, + "ability": "g05" + }, + "summary": "Hoher Einzelschaden aus der zweiten Reihe." + } + }, + "level_xp": [ + 0, + 120, + 280, + 480, + 720, + 1000, + 1320, + 1680, + 2080, + 2520 + ], + "talent_levels": [ + 3, + 6 + ], + "talents": { + "held_ringborke": [ + [ + { + "id": "borkenhaut", + "name": "Borkenhaut", + "text": "Eigenschutz: +15 % Schadensminderung für die Heldin." + }, + { + "id": "schutzwurzeln", + "name": "Schutzwurzeln", + "text": "Gruppenschutz: alle 4 s erhalten bis zu 4 Verbündete in 4 m 10 % Schadensminderung für 4,5 s." + } + ], + [ + { + "id": "stammschlag", + "name": "Stammschlag", + "text": "Einzelziel: jeder 3. Treffer +60 % Schaden." + }, + { + "id": "wurzelbeben", + "name": "Wurzelbeben", + "text": "Fläche: jeder 3. Treffer 50 % Schaden an bis zu 3 Gegner in 2 m." + } + ] + ], + "held_quellgeflecht": [ + [ + { + "id": "tiefe_quelle", + "name": "Tiefe Quelle", + "text": "Einzelziel: heilt den schwächsten Verbündeten um 190 statt drei um je 80." + }, + { + "id": "weite_quelle", + "name": "Weite Quelle", + "text": "Fläche: heilt bis zu 5 Verbündete in 5,5 m um je 65." + } + ], + [ + { + "id": "quellschild", + "name": "Quellschild", + "text": "Schutz: Geheilte erhalten 4 s lang einen Schild von 70." + }, + { + "id": "keimsaat", + "name": "Keimsaat", + "text": "Druck: jeder 2. Treffer setzt Keimbrand, 9 Schaden/s für 4 s." + } + ] + ], + "held_funkenlanze": [ + [ + { + "id": "durchschlag", + "name": "Durchschlag", + "text": "Einzelziel: jeder 4. Treffer ×2,1 statt ×1,5." + }, + { + "id": "splitterschuss", + "name": "Splitterschuss", + "text": "Fläche: jeder 4. Treffer zusätzlich 45 % an bis zu 3 Gegner in 2 m." + } + ], + [ + { + "id": "fernsicht", + "name": "Fernsicht", + "text": "+1,5 m Reichweite." + }, + { + "id": "glutsalve", + "name": "Glutsalve", + "text": "+20 % Angriffstempo." + } + ] + ] + }, + "items": { + "basaltschild": { + "name": "Basaltschild", + "cost": 180, + "text": "+350 Lebenspunkte", + "hp_flat": 350.0 + }, + "glutklinge": { + "name": "Glutklinge", + "cost": 180, + "text": "+18 % Schaden", + "damage": 0.18 + }, + "rankenmantel": { + "name": "Rankenmantel", + "cost": 200, + "text": "+10 % Schadensminderung", + "reduction": 0.1 + }, + "funkenfokus": { + "name": "Funkenfokus", + "cost": 200, + "text": "+15 % Angriffstempo", + "attack_speed": 0.15 + }, + "quellamulett": { + "name": "Quellamulett", + "cost": 220, + "text": "Regeneriert 1,5 % der Lebenspunkte pro Sekunde", + "regen": 0.015 + }, + "kristallsplitter": { + "name": "Kristallsplitter", + "cost": 260, + "text": "Jeder Treffer: 25 % an bis zu 2 Gegner in 1,5 m · ab Stufe 3", + "splash": 0.25, + "min_level": 3 + } + }, + "champions": { + "ch_schutz": { + "name": "Rostschieber", + "role": "Schutz", + "model": "s02", + "cost": 150, + "base": "s02", + "text": "Schildträger: startet mit Schild, gibt alle 6 s bis zu 4 Verbündeten in 4 m einen Schild von 120.", + "view_scale": 1.25 + }, + "ch_druck": { + "name": "Dunstsänger", + "role": "Druck auf Unterstützer", + "model": "s03", + "cost": 150, + "base": "s03", + "text": "Sucht Unterstützer und Fernkämpfer und verlangsamt deren Angriffe.", + "priority": "support", + "view_scale": 1.25 + }, + "ch_belagerung": { + "name": "Keilbrecher", + "role": "Belagerung", + "model": "s04", + "cost": 180, + "base": "s04", + "text": "Greift bevorzugt Gebäude an und verursacht dort ×1,8 Schaden.", + "priority": "building", + "siege_factor": 1.8, + "view_scale": 1.3 + } + }, + "content_constants": { + "HP_PER_LEVEL": 0.09, + "DAMAGE_PER_LEVEL": 0.07, + "XP_PARTICIPATION": 40, + "XP_PER_ROUND": 6, + "XP_RADIUS": 12.0, + "ITEM_SLOTS": 3, + "ITEM_REFUND": 0.5, + "CHAMPION_HP": 2.2, + "CHAMPION_DAMAGE": 1.6, + "CHAMPION_BOUNTY": 70, + "CHAMPION_BOUNTY_PER_ROUND": 6, + "MAX_BOOKINGS": 2, + "BOSS_MODEL": "e10", + "BOSS_GROTTO_HP": 3600.0, + "BOSS_GROTTO_DAMAGE": 55.0, + "BOSS_DEPLOY_HP": 6800.0, + "BOSS_DEPLOY_DAMAGE": 88.0, + "BOSS_BOUNTY": 520, + "BOSS_BOUNTY_PER_ROUND": 60, + "BOSS_LOCK_ROUNDS": 3, + "BOSS_XP": 220, + "BUILDING_XP": 60 + }, + "match_roles": { + "g01": "melee", + "g03": "front", + "g05": "ranged", + "g07": "splash", + "g09": "support", + "w01": "melee", + "w03": "front", + "w05": "ranged", + "w07": "splash", + "w09": "support" + }, + "hero_roles": { + "held_ringborke": "front", + "held_quellgeflecht": "support", + "held_funkenlanze": "ranged" + }, + "row_order": [ + "front", + "melee", + "splash", + "ranged", + "support" + ], + "bot_names": [ + "Eichrufer", + "Aschenzunge", + "Quellwächter", + "Glutfaust", + "Moosauge", + "Basaltherz", + "Rindenkrone", + "Funkenschritt" + ], + "bot_profiles": { + "ausgewogen": { + "front": 0.3, + "melee": 0.25, + "ranged": 0.25, + "splash": 0.1, + "support": 0.1, + "upgrade_from": 6, + "support_lane": 0.0, + "hero": "held_ringborke", + "hero_round": 4, + "items": [ + "basaltschild", + "glutklinge", + "rankenmantel" + ], + "talents": [ + 0, + 1 + ], + "champion": "" + }, + "verteidigung": { + "front": 0.35, + "melee": 0.2, + "ranged": 0.25, + "splash": 0.1, + "support": 0.1, + "upgrade_from": 7, + "support_lane": 0.15, + "hero": "held_ringborke", + "hero_round": 3, + "items": [ + "basaltschild", + "rankenmantel", + "glutklinge" + ], + "talents": [ + 1, + 1 + ], + "champion": "ch_schutz" + }, + "druck": { + "front": 0.2, + "melee": 0.35, + "ranged": 0.25, + "splash": 0.15, + "support": 0.05, + "upgrade_from": 8, + "support_lane": 0.0, + "hero": "held_funkenlanze", + "hero_round": 3, + "items": [ + "glutklinge", + "funkenfokus", + "kristallsplitter" + ], + "talents": [ + 1, + 1 + ], + "champion": "ch_belagerung" + }, + "fernkampf": { + "front": 0.25, + "melee": 0.1, + "ranged": 0.4, + "splash": 0.15, + "support": 0.1, + "upgrade_from": 6, + "support_lane": 0.0, + "hero": "held_funkenlanze", + "hero_round": 4, + "items": [ + "funkenfokus", + "glutklinge", + "kristallsplitter" + ], + "talents": [ + 0, + 0 + ], + "champion": "ch_druck" + }, + "teamhilfe": { + "front": 0.3, + "melee": 0.2, + "ranged": 0.25, + "splash": 0.1, + "support": 0.15, + "upgrade_from": 6, + "support_lane": 0.22, + "hero": "held_quellgeflecht", + "hero_round": 4, + "items": [ + "quellamulett", + "rankenmantel", + "basaltschild" + ], + "talents": [ + 1, + 0 + ], + "champion": "ch_schutz" + }, + "bossjagd": { + "front": 0.35, + "melee": 0.25, + "ranged": 0.2, + "splash": 0.1, + "support": 0.1, + "upgrade_from": 6, + "support_lane": 0.1, + "hero": "held_ringborke", + "hero_round": 3, + "items": [ + "glutklinge", + "basaltschild", + "rankenmantel" + ], + "talents": [ + 1, + 1 + ], + "champion": "ch_belagerung", + "boss_from": 5, + "boss_troops": 5 + } + }, + "bot_constants": { + "BOSS_BAR": 1.35, + "BOSS_BAR_STEP": 1.25 + }, + "waves_melee": [ + "e01", + "e02", + "e05" + ], + "balance": { + "sim_step": 0.05, + "combat_time_limit": 180.0, + "march_speed_factor": 1.6, + "aggro_radius": 7.0, + "leash_radius": 10.0, + "lane_half_width": 2.6, + "start_gold": 220, + "base_income": 70, + "income_per_round": 4, + "income_growth_cap": 80, + "supply_cap": 12, + "sell_refund": 0.75, + "lane_share": 0.5, + "wave_base_count": 3, + "wave_count_every": 3, + "wave_max_count": 7, + "wave_hp_growth": 0.11, + "wave_damage_growth": 0.07, + "wave_growth_quadratic": 0.0015, + "monster_bounty_scale": 2.0, + "bounty_growth": 0.04, + "monster_pool": [ + "e01", + "e02", + "e04", + "e03", + "e06", + "e05" + ], + "tower_outer_hp": 6000.0, + "tower_inner_hp": 7500.0, + "base_tower_hp": 9000.0, + "core_hp": 12000.0, + "tower_damage": 90.0, + "base_tower_damage": 120.0, + "tower_range": 8.6, + "tower_attack_interval": 1.0, + "building_radius": 1.3, + "bounty_outer_tower": 150, + "bounty_inner_tower": 210, + "bounty_base_tower": 270, + "inner_tower_fraction": 0.17, + "outer_tower_fraction": 0.35, + "tower_side_offset": 3.4 + }, + "lanes": { + "top": { + "length": 96.82083296775818, + "points": [ + [ + -27.399999618530273, + 21.0 + ], + [ + -27.15199851989746, + 19.416000366210938 + ], + [ + -26.856000900268555, + 17.847999572753906 + ], + [ + -26.583999633789063, + 16.272001266479492 + ], + [ + -26.408000946044922, + 14.664000511169434 + ], + [ + -26.399999618530273, + 13.0 + ], + [ + -26.675201416015625, + 11.263999938964844 + ], + [ + -27.18560028076172, + 9.472000122070313 + ], + [ + -27.758399963378906, + 7.647999286651611 + ], + [ + -28.22079849243164, + 5.815999984741211 + ], + [ + -28.399999618530273, + 4.0 + ], + [ + -28.15519905090332, + 2.191999912261963 + ], + [ + -27.601600646972656, + 0.3759998679161072 + ], + [ + -26.950401306152344, + -1.436000108718872 + ], + [ + -26.412799835205078, + -3.2320003509521484 + ], + [ + -26.200000762939453, + -5.0 + ], + [ + -26.427202224731445, + -6.744799613952637 + ], + [ + -26.953601837158203, + -8.474400520324707 + ], + [ + -27.606401443481445, + -10.181599617004395 + ], + [ + -28.212800979614258, + -11.859200477600098 + ], + [ + -28.600000381469727, + -13.5 + ], + [ + -28.807811737060547, + -15.57265567779541 + ], + [ + -28.862499237060547, + -17.643749237060547 + ], + [ + -28.735937118530273, + -19.567970275878906 + ], + [ + -28.399999618530273, + -21.200000762939453 + ], + [ + -27.518516540527344, + -22.770370483398438 + ], + [ + -26.281478881835938, + -23.90740966796875 + ], + [ + -25.0, + -25.0 + ], + [ + -23.90740966796875, + -26.281478881835938 + ], + [ + -22.770370483398438, + -27.518516540527344 + ], + [ + -21.200000762939453, + -28.399999618530273 + ], + [ + -19.567970275878906, + -28.735937118530273 + ], + [ + -17.643749237060547, + -28.862499237060547 + ], + [ + -15.57265567779541, + -28.807811737060547 + ], + [ + -13.5, + -28.600000381469727 + ], + [ + -11.859200477600098, + -28.212800979614258 + ], + [ + -10.181599617004395, + -27.606401443481445 + ], + [ + -8.474400520324707, + -26.953601837158203 + ], + [ + -6.744799613952637, + -26.427202224731445 + ], + [ + -5.0, + -26.200000762939453 + ], + [ + -3.2320003509521484, + -26.412799835205078 + ], + [ + -1.436000108718872, + -26.950401306152344 + ], + [ + 0.3759998679161072, + -27.601600646972656 + ], + [ + 2.191999912261963, + -28.15519905090332 + ], + [ + 4.0, + -28.399999618530273 + ], + [ + 5.815999984741211, + -28.22079849243164 + ], + [ + 7.647999286651611, + -27.758399963378906 + ], + [ + 9.472000122070313, + -27.18560028076172 + ], + [ + 11.263999938964844, + -26.675201416015625 + ], + [ + 13.0, + -26.399999618530273 + ], + [ + 14.664000511169434, + -26.408000946044922 + ], + [ + 16.272001266479492, + -26.583999633789063 + ], + [ + 17.847999572753906, + -26.856000900268555 + ], + [ + 19.416000366210938, + -27.15199851989746 + ], + [ + 21.0, + -27.399999618530273 + ] + ], + "cumulative": [ + 0.0, + 1.6032963991165161, + 3.198990821838379, + 4.7982892990112305, + 6.415893077850342, + 8.079913139343262, + 9.837591171264648, + 11.700860023498535, + 13.612686157226563, + 15.5021390914917, + 17.32695960998535, + 19.151456832885742, + 21.049962997436523, + 22.975425720214844, + 24.850160598754883, + 26.63092041015625, + 28.390451431274414, + 30.198381423950195, + 32.0261344909668, + 33.809967041015625, + 35.49583435058594, + 37.57888412475586, + 39.650699615478516, + 41.57907485961914, + 43.245323181152344, + 45.04617691040039, + 46.72639083862305, + 48.41041564941406, + 50.09444046020508, + 51.774658203125, + 53.57550811767578, + 55.241756439208984, + 57.170135498046875, + 59.24195098876953, + 61.32499694824219, + 63.0108642578125, + 64.7947006225586, + 66.62245178222656, + 68.43038177490234, + 70.18991088867188, + 71.97067260742188, + 73.84540557861328, + 75.77086639404297, + 77.66937255859375, + 79.4938735961914, + 81.31869506835938, + 83.20814514160156, + 85.1199722290039, + 86.98324584960938, + 88.74092102050781, + 90.40493774414063, + 92.02254486083984, + 93.62184143066406, + 95.21753692626953, + 96.82083129882813 + ] + }, + "mid": { + "length": 61.160152435302734, + "points": [ + [ + -21.600000381469727, + 21.600000381469727 + ], + [ + -20.307029724121094, + 20.530467987060547 + ], + [ + -19.01875114440918, + 19.481252670288086 + ], + [ + -17.72109603881836, + 18.391407012939453 + ], + [ + -16.399999618530273, + 17.200000762939453 + ], + [ + -15.041406631469727, + 15.864063262939453 + ], + [ + -13.656249046325684, + 14.425002098083496 + ], + [ + -12.267967224121094, + 12.94843864440918 + ], + [ + -10.899999618530273, + 11.5 + ], + [ + -9.567968368530273, + 10.09999942779541 + ], + [ + -8.25624942779541, + 8.712499618530273 + ], + [ + -6.941405296325684, + 7.318749904632568 + ], + [ + -5.599999904632568, + 5.900000095367432 + ], + [ + -4.503999710083008, + 4.734399795532227 + ], + [ + -3.3959996700286865, + 3.5472002029418945 + ], + [ + -2.2759997844696045, + 2.352800130844116 + ], + [ + -1.143999457359314, + 1.1656004190444946 + ], + [ + 0.0, + 0.0 + ], + [ + 1.1656004190444946, + -1.143999457359314 + ], + [ + 2.352800130844116, + -2.2759997844696045 + ], + [ + 3.5472002029418945, + -3.3959996700286865 + ], + [ + 4.734399795532227, + -4.503999710083008 + ], + [ + 5.900000095367432, + -5.599999904632568 + ], + [ + 7.318749904632568, + -6.941405296325684 + ], + [ + 8.712499618530273, + -8.25624942779541 + ], + [ + 10.09999942779541, + -9.567968368530273 + ], + [ + 11.5, + -10.899999618530273 + ], + [ + 12.94843864440918, + -12.267967224121094 + ], + [ + 14.425002098083496, + -13.656249046325684 + ], + [ + 15.864063262939453, + -15.041406631469727 + ], + [ + 17.200000762939453, + -16.399999618530273 + ], + [ + 18.391407012939453, + -17.72109603881836 + ], + [ + 19.481252670288086, + -19.01875114440918 + ], + [ + 20.530467987060547, + -20.307029724121094 + ], + [ + 21.600000381469727, + -21.600000381469727 + ] + ], + "cumulative": [ + 0.0, + 1.6779966354370117, + 3.3394761085510254, + 5.034077167510986, + 6.813050270080566, + 8.718438148498535, + 10.715826034545898, + 12.742539405822754, + 14.734851837158203, + 16.667287826538086, + 18.576675415039063, + 20.492753982543945, + 22.44524383544922, + 24.045194625854492, + 25.669111251831055, + 27.30648422241211, + 28.946870803833008, + 30.580076217651367, + 32.213279724121094, + 33.853668212890625, + 35.49103927612305, + 37.114959716796875, + 38.714908599853516, + 40.66740036010742, + 42.58347702026367, + 44.492862701416016, + 46.42530059814453, + 48.4176139831543, + 50.4443244934082, + 52.441715240478516, + 54.347103118896484, + 56.126075744628906, + 57.820674896240234, + 59.482154846191406, + 61.160152435302734 + ] + }, + "bot": { + "length": 96.8208339214325, + "points": [ + [ + -21.0, + 27.399999618530273 + ], + [ + -19.299999237060547, + 27.303998947143555 + ], + [ + -17.600000381469727, + 27.191999435424805 + ], + [ + -15.899999618530273, + 27.08799934387207 + ], + [ + -14.199999809265137, + 27.01599884033203 + ], + [ + -12.5, + 27.0 + ], + [ + -10.791999816894531, + 27.120418548583984 + ], + [ + -9.076000213623047, + 27.361255645751953 + ], + [ + -7.363999366760254, + 27.601882934570313 + ], + [ + -5.667999744415283, + 27.7216739654541 + ], + [ + -4.0, + 27.600000381469727 + ], + [ + -2.367999792098999, + 27.093137741088867 + ], + [ + -0.7640000581741333, + 26.281503677368164 + ], + [ + 0.8240002989768982, + 25.380687713623047 + ], + [ + 2.4079999923706055, + 24.606273651123047 + ], + [ + 4.0, + 24.173847198486328 + ], + [ + 5.6080002784729, + 24.166473388671875 + ], + [ + 7.223999977111816, + 24.4404239654541 + ], + [ + 8.836000442504883, + 24.871112823486328 + ], + [ + 10.431999206542969, + 25.33393669128418 + ], + [ + 12.0, + 25.704309463500977 + ], + [ + 14.022655487060547, + 26.05635643005371 + ], + [ + 16.08125114440918, + 26.397808074951172 + ], + [ + 17.974220275878906, + 26.716434478759766 + ], + [ + 19.5, + 27.0 + ], + [ + 21.143749237060547, + 27.65597915649414 + ], + [ + 22.200000762939453, + 27.799999237060547 + ], + [ + 23.59375, + 26.625 + ], + [ + 25.0, + 25.0 + ], + [ + 26.625, + 23.59375 + ], + [ + 27.799999237060547, + 22.200000762939453 + ], + [ + 27.65597915649414, + 21.143749237060547 + ], + [ + 27.0, + 19.5 + ], + [ + 26.716434478759766, + 17.974220275878906 + ], + [ + 26.397808074951172, + 16.08125114440918 + ], + [ + 26.05635643005371, + 14.022655487060547 + ], + [ + 25.704309463500977, + 12.0 + ], + [ + 25.33393669128418, + 10.431999206542969 + ], + [ + 24.871112823486328, + 8.836000442504883 + ], + [ + 24.4404239654541, + 7.223999977111816 + ], + [ + 24.166473388671875, + 5.6080002784729 + ], + [ + 24.173847198486328, + 4.0 + ], + [ + 24.606273651123047, + 2.4079999923706055 + ], + [ + 25.380687713623047, + 0.8240002989768982 + ], + [ + 26.281503677368164, + -0.7640000581741333 + ], + [ + 27.093137741088867, + -2.367999792098999 + ], + [ + 27.600000381469727, + -4.0 + ], + [ + 27.7216739654541, + -5.667999744415283 + ], + [ + 27.601882934570313, + -7.363999366760254 + ], + [ + 27.361255645751953, + -9.076000213623047 + ], + [ + 27.120418548583984, + -10.791999816894531 + ], + [ + 27.0, + -12.5 + ], + [ + 27.01599884033203, + -14.199999809265137 + ], + [ + 27.08799934387207, + -15.899999618530273 + ], + [ + 27.191999435424805, + -17.600000381469727 + ], + [ + 27.303998947143555, + -19.299999237060547 + ], + [ + 27.399999618530273, + -21.0 + ] + ], + "cumulative": [ + 0.0, + 1.7027091979980469, + 3.406393527984619, + 5.109572410583496, + 6.81109619140625, + 8.511171340942383, + 10.223411560058594, + 11.956229209899902, + 13.685057640075684, + 15.385282516479492, + 17.057714462280273, + 18.766613006591797, + 20.564268112182617, + 22.389976501464844, + 24.153148651123047, + 25.802831649780273, + 27.41084861755371, + 29.04990577697754, + 30.718448638916016, + 32.38019943237305, + 33.99134826660156, + 36.04441452026367, + 38.131134033203125, + 40.05073165893555, + 41.602638244628906, + 43.3724479675293, + 44.438472747802734, + 46.26142501831055, + 48.41041564941406, + 50.559410095214844, + 52.382362365722656, + 53.448387145996094, + 55.21819305419922, + 56.77009963989258, + 58.689697265625, + 60.77642059326172, + 62.82948303222656, + 64.44063568115234, + 66.10238647460938, + 67.77092742919922, + 69.40998840332031, + 71.01800537109375, + 72.66768646240234, + 74.43085479736328, + 76.2565689086914, + 78.0542221069336, + 79.76312255859375, + 81.43555450439453, + 83.13577270507813, + 84.86460876464844, + 86.59741973876953, + 88.30966186523438, + 90.00973510742188, + 91.71125793457031, + 93.41444396972656, + 95.11812591552734, + 96.82083129882813 + ] + } + }, + "buildings": [ + { + "id": "blau_top_inner", + "team": 0, + "lane": "top", + "tier": "inner", + "progress": 16.45954160451889, + "position": [ + -24.931251525878906, + 4.5293378829956055 + ], + "max_hp": 7500.0, + "damage": 90.0, + "range": 8.6, + "bounty": 210 + }, + { + "id": "blau_top_outer", + "team": 0, + "lane": "top", + "tier": "outer", + "progress": 33.88729153871536, + "position": [ + -24.921451568603516, + -12.715348243713379 + ], + "max_hp": 6000.0, + "damage": 90.0, + "range": 8.6, + "bounty": 150 + }, + { + "id": "blau_mid_inner", + "team": 0, + "lane": "mid", + "tier": "inner", + "progress": 10.397225914001465, + "position": [ + -11.427590370178223, + 17.012392044067383 + ], + "max_hp": 7500.0, + "damage": 90.0, + "range": 8.6, + "bounty": 210 + }, + { + "id": "blau_mid_outer", + "team": 0, + "lane": "mid", + "tier": "outer", + "progress": 21.406053352355954, + "position": [ + -3.8433847427368164, + 8.990991592407227 + ], + "max_hp": 6000.0, + "damage": 90.0, + "range": 8.6, + "bounty": 150 + }, + { + "id": "blau_bot_inner", + "team": 0, + "lane": "bot", + "tier": "inner", + "progress": 16.459541766643525, + "position": [ + -4.349228858947754, + 31.034507751464844 + ], + "max_hp": 7500.0, + "damage": 90.0, + "range": 8.6, + "bounty": 210 + }, + { + "id": "blau_bot_outer", + "team": 0, + "lane": "bot", + "tier": "outer", + "progress": 33.88729187250137, + "position": [ + 11.117134094238281, + 28.989334106445313 + ], + "max_hp": 6000.0, + "damage": 90.0, + "range": 8.6, + "bounty": 150 + }, + { + "id": "blau_base_1", + "team": 0, + "lane": "base", + "tier": "base", + "progress": -1.0, + "position": [ + -29.476999282836914, + 24.023000717163086 + ], + "max_hp": 9000.0, + "damage": 120.0, + "range": 8.6, + "bounty": 270 + }, + { + "id": "blau_base_2", + "team": 0, + "lane": "base", + "tier": "base", + "progress": -1.0, + "position": [ + -24.023000717163086, + 29.476999282836914 + ], + "max_hp": 9000.0, + "damage": 120.0, + "range": 8.6, + "bounty": 270 + }, + { + "id": "blau_ancient", + "team": 0, + "lane": "base", + "tier": "core", + "progress": -1.0, + "position": [ + -30.0, + 30.0 + ], + "max_hp": 12000.0, + "damage": 0.0, + "range": 0.0, + "bounty": 0 + }, + { + "id": "rot_top_inner", + "team": 1, + "lane": "top", + "tier": "inner", + "progress": 16.45954160451889, + "position": [ + 4.5293378829956055, + -24.931251525878906 + ], + "max_hp": 7500.0, + "damage": 90.0, + "range": 8.6, + "bounty": 210 + }, + { + "id": "rot_top_outer", + "team": 1, + "lane": "top", + "tier": "outer", + "progress": 33.88729153871536, + "position": [ + -12.715348243713379, + -24.921451568603516 + ], + "max_hp": 6000.0, + "damage": 90.0, + "range": 8.6, + "bounty": 150 + }, + { + "id": "rot_mid_inner", + "team": 1, + "lane": "mid", + "tier": "inner", + "progress": 10.397225914001465, + "position": [ + 17.012392044067383, + -11.427590370178223 + ], + "max_hp": 7500.0, + "damage": 90.0, + "range": 8.6, + "bounty": 210 + }, + { + "id": "rot_mid_outer", + "team": 1, + "lane": "mid", + "tier": "outer", + "progress": 21.406053352355954, + "position": [ + 8.990991592407227, + -3.8433847427368164 + ], + "max_hp": 6000.0, + "damage": 90.0, + "range": 8.6, + "bounty": 150 + }, + { + "id": "rot_bot_inner", + "team": 1, + "lane": "bot", + "tier": "inner", + "progress": 16.459541766643525, + "position": [ + 31.034507751464844, + -4.349228858947754 + ], + "max_hp": 7500.0, + "damage": 90.0, + "range": 8.6, + "bounty": 210 + }, + { + "id": "rot_bot_outer", + "team": 1, + "lane": "bot", + "tier": "outer", + "progress": 33.88729187250137, + "position": [ + 28.989334106445313, + 11.117134094238281 + ], + "max_hp": 6000.0, + "damage": 90.0, + "range": 8.6, + "bounty": 150 + }, + { + "id": "rot_base_1", + "team": 1, + "lane": "base", + "tier": "base", + "progress": -1.0, + "position": [ + 24.023000717163086, + -29.476999282836914 + ], + "max_hp": 9000.0, + "damage": 120.0, + "range": 8.6, + "bounty": 270 + }, + { + "id": "rot_base_2", + "team": 1, + "lane": "base", + "tier": "base", + "progress": -1.0, + "position": [ + 29.476999282836914, + -24.023000717163086 + ], + "max_hp": 9000.0, + "damage": 120.0, + "range": 8.6, + "bounty": 270 + }, + { + "id": "rot_ancient", + "team": 1, + "lane": "base", + "tier": "core", + "progress": -1.0, + "position": [ + 30.0, + -30.0 + ], + "max_hp": 12000.0, + "damage": 0.0, + "range": 0.0, + "bounty": 0 + } + ] +} \ No newline at end of file diff --git a/Assets/Luneraria/Tests/Core/Golden/golden.json b/Assets/Luneraria/Tests/Core/Golden/golden.json new file mode 100644 index 0000000..e104049 --- /dev/null +++ b/Assets/Luneraria/Tests/Core/Golden/golden.json @@ -0,0 +1 @@ +{"engine":"4.7.2-stable (official)","reference":"luneraria/g3 1b540f2","scenarios":{"start_three_lanes":{"title":"Normaler Drei-Lane-Start: sechs Bots, Aufmarsch, erste Gefechte, Abrechnung","snapshots":[{"label":"planned","phase":0,"round":1,"winner":-2,"end_note":"","players":[{"gold":220,"draft_gold":35,"ready":true,"earned":0,"spent":0,"next_seq":1,"roster":[],"hero":"","bookings":[],"new_bookings":[],"draft_roster":["p0-1|w03|top|75|true","p0-2|w05|top|60|true","p0-3|w01|top|50|true"],"draft_hero":"","boss_lane":"","undo":3},{"gold":220,"draft_gold":35,"ready":true,"earned":0,"spent":0,"next_seq":1,"roster":[],"hero":"","bookings":[],"new_bookings":[],"draft_roster":["p1-1|w03|mid|75|true","p1-2|w01|mid|50|true","p1-3|w05|mid|60|true"],"draft_hero":"","boss_lane":"","undo":3},{"gold":220,"draft_gold":40,"ready":true,"earned":0,"spent":0,"next_seq":1,"roster":[],"hero":"","bookings":[],"new_bookings":[],"draft_roster":["p2-1|g03|bot|70|true","p2-2|g01|bot|45|true","p2-3|g05|bot|65|true"],"draft_hero":"","boss_lane":"","undo":3},{"gold":220,"draft_gold":40,"ready":true,"earned":0,"spent":0,"next_seq":1,"roster":[],"hero":"","bookings":[],"new_bookings":[],"draft_roster":["p3-1|g03|top|70|true","p3-2|g05|top|65|true","p3-3|g01|top|45|true"],"draft_hero":"","boss_lane":"","undo":3},{"gold":220,"draft_gold":35,"ready":true,"earned":0,"spent":0,"next_seq":1,"roster":[],"hero":"","bookings":[],"new_bookings":[],"draft_roster":["p4-1|w01|mid|50|true","p4-2|w05|mid|60|true","p4-3|w03|mid|75|true"],"draft_hero":"","boss_lane":"","undo":3},{"gold":220,"draft_gold":85,"ready":true,"earned":0,"spent":0,"next_seq":1,"roster":[],"hero":"","bookings":[],"new_bookings":[],"draft_roster":["p5-1|g05|bot|65|true","p5-2|g03|bot|70|true"],"draft_hero":"","boss_lane":"","undo":2}],"buildings":[7500.0,6000.0,7500.0,6000.0,7500.0,6000.0,9000.0,9000.0,12000.0,7500.0,6000.0,7500.0,6000.0,7500.0,6000.0,9000.0,9000.0,12000.0],"boss":{"next":1,"settled":0,"claim":""},"boss_log":[],"announcements":[],"settlement":null,"combat":null},{"label":"spawned","phase":1,"round":1,"winner":-2,"end_note":"","players":[{"gold":35,"draft_gold":35,"ready":true,"earned":0,"spent":185,"next_seq":4,"roster":["p0-1|w03|top|75","p0-2|w05|top|60","p0-3|w01|top|50"],"hero":"","bookings":[],"new_bookings":[],"draft_roster":["p0-1|w03|top|75|true","p0-2|w05|top|60|true","p0-3|w01|top|50|true"],"draft_hero":"","boss_lane":"","undo":0},{"gold":35,"draft_gold":35,"ready":true,"earned":0,"spent":185,"next_seq":4,"roster":["p1-1|w03|mid|75","p1-2|w01|mid|50","p1-3|w05|mid|60"],"hero":"","bookings":[],"new_bookings":[],"draft_roster":["p1-1|w03|mid|75|true","p1-2|w01|mid|50|true","p1-3|w05|mid|60|true"],"draft_hero":"","boss_lane":"","undo":0},{"gold":40,"draft_gold":40,"ready":true,"earned":0,"spent":180,"next_seq":4,"roster":["p2-1|g03|bot|70","p2-2|g01|bot|45","p2-3|g05|bot|65"],"hero":"","bookings":[],"new_bookings":[],"draft_roster":["p2-1|g03|bot|70|true","p2-2|g01|bot|45|true","p2-3|g05|bot|65|true"],"draft_hero":"","boss_lane":"","undo":0},{"gold":40,"draft_gold":40,"ready":true,"earned":0,"spent":180,"next_seq":4,"roster":["p3-1|g03|top|70","p3-2|g05|top|65","p3-3|g01|top|45"],"hero":"","bookings":[],"new_bookings":[],"draft_roster":["p3-1|g03|top|70|true","p3-2|g05|top|65|true","p3-3|g01|top|45|true"],"draft_hero":"","boss_lane":"","undo":0},{"gold":35,"draft_gold":35,"ready":true,"earned":0,"spent":185,"next_seq":4,"roster":["p4-1|w01|mid|50","p4-2|w05|mid|60","p4-3|w03|mid|75"],"hero":"","bookings":[],"new_bookings":[],"draft_roster":["p4-1|w01|mid|50|true","p4-2|w05|mid|60|true","p4-3|w03|mid|75|true"],"draft_hero":"","boss_lane":"","undo":0},{"gold":85,"draft_gold":85,"ready":true,"earned":0,"spent":135,"next_seq":3,"roster":["p5-1|g05|bot|65","p5-2|g03|bot|70"],"hero":"","bookings":[],"new_bookings":[],"draft_roster":["p5-1|g05|bot|65|true","p5-2|g03|bot|70|true"],"draft_hero":"","boss_lane":"","undo":0}],"buildings":[7500.0,6000.0,7500.0,6000.0,7500.0,6000.0,9000.0,9000.0,12000.0,7500.0,6000.0,7500.0,6000.0,7500.0,6000.0,9000.0,9000.0,12000.0],"boss":{"next":1,"settled":0,"claim":""},"boss_log":[],"announcements":[],"settlement":null,"combat":{"round":1,"steps":0,"elapsed":0.0,"finished":false,"end_reason":"","destroyed":[],"grotto":"none|-1|-1|true","grotto_boss":"","grotto_boss_hp":0.0,"events":0,"mobile":[18,17,0]},"units":[{"id":1,"kind":"tower","team":0,"lane":"top","zone":"lane","slot":-1,"uid":"","def":"blau_top_inner","alive":true,"hp":7500.0,"max_hp":7500.0,"shield":0.0,"x":-24.931251525878906,"y":4.5293378829956055,"facing":0.0,"progress":0.0,"target":-1,"hits":0,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":2,"kind":"tower","team":0,"lane":"top","zone":"lane","slot":-1,"uid":"","def":"blau_top_outer","alive":true,"hp":6000.0,"max_hp":6000.0,"shield":0.0,"x":-24.921451568603516,"y":-12.715348243713379,"facing":0.0,"progress":0.0,"target":-1,"hits":0,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":3,"kind":"tower","team":0,"lane":"mid","zone":"lane","slot":-1,"uid":"","def":"blau_mid_inner","alive":true,"hp":7500.0,"max_hp":7500.0,"shield":0.0,"x":-11.427590370178223,"y":17.012392044067383,"facing":0.0,"progress":0.0,"target":-1,"hits":0,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":4,"kind":"tower","team":0,"lane":"mid","zone":"lane","slot":-1,"uid":"","def":"blau_mid_outer","alive":true,"hp":6000.0,"max_hp":6000.0,"shield":0.0,"x":-3.8433847427368164,"y":8.990991592407227,"facing":0.0,"progress":0.0,"target":-1,"hits":0,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":5,"kind":"tower","team":0,"lane":"bot","zone":"lane","slot":-1,"uid":"","def":"blau_bot_inner","alive":true,"hp":7500.0,"max_hp":7500.0,"shield":0.0,"x":-4.349228858947754,"y":31.034507751464844,"facing":0.0,"progress":0.0,"target":-1,"hits":0,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":6,"kind":"tower","team":0,"lane":"bot","zone":"lane","slot":-1,"uid":"","def":"blau_bot_outer","alive":true,"hp":6000.0,"max_hp":6000.0,"shield":0.0,"x":11.117134094238281,"y":28.989334106445313,"facing":0.0,"progress":0.0,"target":-1,"hits":0,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":7,"kind":"tower","team":0,"lane":"base","zone":"lane","slot":-1,"uid":"","def":"blau_base_1","alive":true,"hp":9000.0,"max_hp":9000.0,"shield":0.0,"x":-29.476999282836914,"y":24.023000717163086,"facing":0.0,"progress":0.0,"target":-1,"hits":0,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":8,"kind":"tower","team":0,"lane":"base","zone":"lane","slot":-1,"uid":"","def":"blau_base_2","alive":true,"hp":9000.0,"max_hp":9000.0,"shield":0.0,"x":-24.023000717163086,"y":29.476999282836914,"facing":0.0,"progress":0.0,"target":-1,"hits":0,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":9,"kind":"core","team":0,"lane":"base","zone":"lane","slot":-1,"uid":"","def":"blau_ancient","alive":true,"hp":12000.0,"max_hp":12000.0,"shield":0.0,"x":-30.0,"y":30.0,"facing":0.0,"progress":0.0,"target":-1,"hits":0,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":10,"kind":"tower","team":1,"lane":"top","zone":"lane","slot":-1,"uid":"","def":"rot_top_inner","alive":true,"hp":7500.0,"max_hp":7500.0,"shield":0.0,"x":4.5293378829956055,"y":-24.931251525878906,"facing":0.0,"progress":0.0,"target":-1,"hits":0,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":11,"kind":"tower","team":1,"lane":"top","zone":"lane","slot":-1,"uid":"","def":"rot_top_outer","alive":true,"hp":6000.0,"max_hp":6000.0,"shield":0.0,"x":-12.715348243713379,"y":-24.921451568603516,"facing":0.0,"progress":0.0,"target":-1,"hits":0,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":12,"kind":"tower","team":1,"lane":"mid","zone":"lane","slot":-1,"uid":"","def":"rot_mid_inner","alive":true,"hp":7500.0,"max_hp":7500.0,"shield":0.0,"x":17.012392044067383,"y":-11.427590370178223,"facing":0.0,"progress":0.0,"target":-1,"hits":0,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":13,"kind":"tower","team":1,"lane":"mid","zone":"lane","slot":-1,"uid":"","def":"rot_mid_outer","alive":true,"hp":6000.0,"max_hp":6000.0,"shield":0.0,"x":8.990991592407227,"y":-3.8433847427368164,"facing":0.0,"progress":0.0,"target":-1,"hits":0,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":14,"kind":"tower","team":1,"lane":"bot","zone":"lane","slot":-1,"uid":"","def":"rot_bot_inner","alive":true,"hp":7500.0,"max_hp":7500.0,"shield":0.0,"x":31.034507751464844,"y":-4.349228858947754,"facing":0.0,"progress":0.0,"target":-1,"hits":0,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":15,"kind":"tower","team":1,"lane":"bot","zone":"lane","slot":-1,"uid":"","def":"rot_bot_outer","alive":true,"hp":6000.0,"max_hp":6000.0,"shield":0.0,"x":28.989334106445313,"y":11.117134094238281,"facing":0.0,"progress":0.0,"target":-1,"hits":0,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":16,"kind":"tower","team":1,"lane":"base","zone":"lane","slot":-1,"uid":"","def":"rot_base_1","alive":true,"hp":9000.0,"max_hp":9000.0,"shield":0.0,"x":24.023000717163086,"y":-29.476999282836914,"facing":0.0,"progress":0.0,"target":-1,"hits":0,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":17,"kind":"tower","team":1,"lane":"base","zone":"lane","slot":-1,"uid":"","def":"rot_base_2","alive":true,"hp":9000.0,"max_hp":9000.0,"shield":0.0,"x":29.476999282836914,"y":-24.023000717163086,"facing":0.0,"progress":0.0,"target":-1,"hits":0,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":18,"kind":"core","team":1,"lane":"base","zone":"lane","slot":-1,"uid":"","def":"rot_ancient","alive":true,"hp":12000.0,"max_hp":12000.0,"shield":0.0,"x":30.0,"y":-30.0,"facing":0.0,"progress":0.0,"target":-1,"hits":0,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":19,"kind":"monster","team":0,"lane":"top","zone":"lane","slot":-1,"uid":"","def":"e01","alive":true,"hp":90.0,"max_hp":90.0,"shield":0.0,"x":-28.243892669677734,"y":10.502157211303711,"facing":-2.864119239296395,"progress":11.0,"target":-1,"hits":0,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":20,"kind":"monster","team":0,"lane":"top","zone":"lane","slot":-1,"uid":"","def":"e01","alive":true,"hp":90.0,"max_hp":90.0,"shield":0.0,"x":-26.993616104125977,"y":10.146052360534668,"facing":-2.864119239296395,"progress":11.0,"target":-1,"hits":0,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":21,"kind":"monster","team":0,"lane":"top","zone":"lane","slot":-1,"uid":"","def":"e01","alive":true,"hp":90.0,"max_hp":90.0,"shield":0.0,"x":-25.74333953857422,"y":9.789947509765625,"facing":-2.864119239296395,"progress":11.0,"target":-1,"hits":0,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":22,"kind":"monster","team":0,"lane":"mid","zone":"lane","slot":-1,"uid":"","def":"e01","alive":true,"hp":90.0,"max_hp":90.0,"shield":0.0,"x":-14.408708572387695,"y":13.32747745513916,"facing":2.3870002372622334,"progress":11.0,"target":-1,"hits":0,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":23,"kind":"monster","team":0,"lane":"mid","zone":"lane","slot":-1,"uid":"","def":"e01","alive":true,"hp":90.0,"max_hp":90.0,"shield":0.0,"x":-13.461592674255371,"y":14.21796703338623,"facing":2.3870002372622334,"progress":11.0,"target":-1,"hits":0,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":24,"kind":"monster","team":0,"lane":"mid","zone":"lane","slot":-1,"uid":"","def":"e01","alive":true,"hp":90.0,"max_hp":90.0,"shield":0.0,"x":-12.514476776123047,"y":15.1084566116333,"facing":2.3870002372622334,"progress":11.0,"target":-1,"hits":0,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":25,"kind":"monster","team":0,"lane":"bot","zone":"lane","slot":-1,"uid":"","def":"e01","alive":true,"hp":90.0,"max_hp":90.0,"shield":0.0,"x":-9.842267036437988,"y":25.94097137451172,"facing":1.4313591016628469,"progress":11.0,"target":-1,"hits":0,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":26,"kind":"monster","team":0,"lane":"bot","zone":"lane","slot":-1,"uid":"","def":"e01","alive":true,"hp":90.0,"max_hp":90.0,"shield":0.0,"x":-10.022948265075684,"y":27.22835350036621,"facing":1.4313591016628469,"progress":11.0,"target":-1,"hits":0,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":27,"kind":"monster","team":0,"lane":"bot","zone":"lane","slot":-1,"uid":"","def":"e01","alive":true,"hp":90.0,"max_hp":90.0,"shield":0.0,"x":-10.203629493713379,"y":28.515735626220703,"facing":1.4313591016628469,"progress":11.0,"target":-1,"hits":0,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":28,"kind":"monster","team":1,"lane":"top","zone":"lane","slot":-1,"uid":"","def":"e01","alive":true,"hp":90.0,"max_hp":90.0,"shield":0.0,"x":10.502157211303711,"y":-28.243892669677734,"facing":-1.8482697410882951,"progress":11.0,"target":-1,"hits":0,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":29,"kind":"monster","team":1,"lane":"top","zone":"lane","slot":-1,"uid":"","def":"e01","alive":true,"hp":90.0,"max_hp":90.0,"shield":0.0,"x":10.146052360534668,"y":-26.993616104125977,"facing":-1.8482697410882951,"progress":11.0,"target":-1,"hits":0,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":30,"kind":"monster","team":1,"lane":"top","zone":"lane","slot":-1,"uid":"","def":"e01","alive":true,"hp":90.0,"max_hp":90.0,"shield":0.0,"x":9.789947509765625,"y":-25.74333953857422,"facing":-1.8482697410882951,"progress":11.0,"target":-1,"hits":0,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":31,"kind":"monster","team":1,"lane":"mid","zone":"lane","slot":-1,"uid":"","def":"e01","alive":true,"hp":90.0,"max_hp":90.0,"shield":0.0,"x":13.32747745513916,"y":-14.408708572387695,"facing":-0.816203910467337,"progress":11.0,"target":-1,"hits":0,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":32,"kind":"monster","team":1,"lane":"mid","zone":"lane","slot":-1,"uid":"","def":"e01","alive":true,"hp":90.0,"max_hp":90.0,"shield":0.0,"x":14.21796703338623,"y":-13.461592674255371,"facing":-0.816203910467337,"progress":11.0,"target":-1,"hits":0,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":33,"kind":"monster","team":1,"lane":"mid","zone":"lane","slot":-1,"uid":"","def":"e01","alive":true,"hp":90.0,"max_hp":90.0,"shield":0.0,"x":15.1084566116333,"y":-12.514476776123047,"facing":-0.816203910467337,"progress":11.0,"target":-1,"hits":0,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":34,"kind":"monster","team":1,"lane":"bot","zone":"lane","slot":-1,"uid":"","def":"e01","alive":true,"hp":90.0,"max_hp":90.0,"shield":0.0,"x":25.94097137451172,"y":-9.842267036437988,"facing":0.13943722513204979,"progress":11.0,"target":-1,"hits":0,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":35,"kind":"monster","team":1,"lane":"bot","zone":"lane","slot":-1,"uid":"","def":"e01","alive":true,"hp":90.0,"max_hp":90.0,"shield":0.0,"x":27.22835350036621,"y":-10.022948265075684,"facing":0.13943722513204979,"progress":11.0,"target":-1,"hits":0,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":36,"kind":"monster","team":1,"lane":"bot","zone":"lane","slot":-1,"uid":"","def":"e01","alive":true,"hp":90.0,"max_hp":90.0,"shield":0.0,"x":28.515735626220703,"y":-10.203629493713379,"facing":0.13943722513204979,"progress":11.0,"target":-1,"hits":0,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":37,"kind":"troop","team":0,"lane":"top","zone":"lane","slot":0,"uid":"p0-1","def":"w03","alive":true,"hp":620.0,"max_hp":620.0,"shield":0.0,"x":-28.204208374023438,"y":13.871247291564941,"facing":3.1367842018723553,"progress":7.2,"target":-1,"hits":0,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":38,"kind":"troop","team":0,"lane":"top","zone":"lane","slot":0,"uid":"p0-3","def":"w01","alive":true,"hp":290.0,"max_hp":290.0,"shield":0.0,"x":-27.004222869873047,"y":13.877017974853516,"facing":3.1367842018723553,"progress":7.2,"target":-1,"hits":0,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":39,"kind":"troop","team":0,"lane":"top","zone":"lane","slot":0,"uid":"p0-2","def":"w05","alive":true,"hp":230.0,"max_hp":230.0,"shield":0.0,"x":-25.804237365722656,"y":13.882787704467773,"facing":3.1367842018723553,"progress":7.2,"target":-1,"hits":0,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":40,"kind":"troop","team":0,"lane":"mid","zone":"lane","slot":1,"uid":"p1-1","def":"w03","alive":true,"hp":620.0,"max_hp":620.0,"shield":0.0,"x":-17.386140823364258,"y":15.645247459411621,"facing":2.347786769279204,"progress":7.2,"target":-1,"hits":0,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":41,"kind":"troop","team":0,"lane":"mid","zone":"lane","slot":1,"uid":"p1-2","def":"w01","alive":true,"hp":290.0,"max_hp":290.0,"shield":0.0,"x":-16.544776916503906,"y":16.500879287719727,"facing":2.347786769279204,"progress":7.2,"target":-1,"hits":0,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":42,"kind":"troop","team":0,"lane":"mid","zone":"lane","slot":1,"uid":"p1-3","def":"w05","alive":true,"hp":230.0,"max_hp":230.0,"shield":0.0,"x":-15.703412055969238,"y":17.35651206970215,"facing":2.347786769279204,"progress":7.2,"target":-1,"hits":0,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":43,"kind":"troop","team":0,"lane":"bot","zone":"lane","slot":2,"uid":"p2-1","def":"g03","alive":true,"hp":650.0,"max_hp":650.0,"shield":0.0,"x":-13.828052520751953,"y":25.212417602539063,"facing":1.5802071320513056,"progress":7.2,"target":-1,"hits":0,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":44,"kind":"troop","team":0,"lane":"bot","zone":"lane","slot":2,"uid":"p2-2","def":"g01","alive":true,"hp":260.0,"max_hp":260.0,"shield":0.0,"x":-13.816760063171387,"y":26.412364959716797,"facing":1.5802071320513056,"progress":7.2,"target":-1,"hits":0,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":45,"kind":"troop","team":0,"lane":"bot","zone":"lane","slot":2,"uid":"p2-3","def":"g05","alive":true,"hp":240.0,"max_hp":240.0,"shield":0.0,"x":-13.805466651916504,"y":27.61231231689453,"facing":1.5802071320513056,"progress":7.2,"target":-1,"hits":0,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":46,"kind":"troop","team":1,"lane":"top","zone":"lane","slot":3,"uid":"p3-1","def":"g03","alive":true,"hp":650.0,"max_hp":650.0,"shield":0.0,"x":13.871247291564941,"y":-28.204208374023438,"facing":-1.5659878750774585,"progress":7.2,"target":-1,"hits":0,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":47,"kind":"troop","team":1,"lane":"top","zone":"lane","slot":3,"uid":"p3-3","def":"g01","alive":true,"hp":260.0,"max_hp":260.0,"shield":0.0,"x":13.877017974853516,"y":-27.004222869873047,"facing":-1.5659878750774585,"progress":7.2,"target":-1,"hits":0,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":48,"kind":"troop","team":1,"lane":"top","zone":"lane","slot":3,"uid":"p3-2","def":"g05","alive":true,"hp":240.0,"max_hp":240.0,"shield":0.0,"x":13.882787704467773,"y":-25.804237365722656,"facing":-1.5659878750774585,"progress":7.2,"target":-1,"hits":0,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":49,"kind":"troop","team":1,"lane":"mid","zone":"lane","slot":4,"uid":"p4-3","def":"w03","alive":true,"hp":620.0,"max_hp":620.0,"shield":0.0,"x":15.645247459411621,"y":-17.386140823364258,"facing":-0.7769904424843075,"progress":7.2,"target":-1,"hits":0,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":50,"kind":"troop","team":1,"lane":"mid","zone":"lane","slot":4,"uid":"p4-1","def":"w01","alive":true,"hp":290.0,"max_hp":290.0,"shield":0.0,"x":16.500879287719727,"y":-16.544776916503906,"facing":-0.7769904424843075,"progress":7.2,"target":-1,"hits":0,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":51,"kind":"troop","team":1,"lane":"mid","zone":"lane","slot":4,"uid":"p4-2","def":"w05","alive":true,"hp":230.0,"max_hp":230.0,"shield":0.0,"x":17.35651206970215,"y":-15.703412055969238,"facing":-0.7769904424843075,"progress":7.2,"target":-1,"hits":0,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":52,"kind":"troop","team":1,"lane":"bot","zone":"lane","slot":5,"uid":"p5-2","def":"g03","alive":true,"hp":650.0,"max_hp":650.0,"shield":0.0,"x":25.212417602539063,"y":-13.828052520751953,"facing":-0.009410805256408956,"progress":7.2,"target":-1,"hits":0,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":53,"kind":"troop","team":1,"lane":"bot","zone":"lane","slot":5,"uid":"p5-1","def":"g05","alive":true,"hp":240.0,"max_hp":240.0,"shield":0.0,"x":26.412364959716797,"y":-13.816760063171387,"facing":-0.009410805256408956,"progress":7.2,"target":-1,"hits":0,"reached":false,"dormant":false,"effects":[],"dots":[]}],"wave":[["e01",90.0,6.0,6],["e01",90.0,6.0,6],["e01",90.0,6.0,6]]},{"label":"t10","phase":1,"round":1,"winner":-2,"end_note":"","players":[{"gold":35,"draft_gold":35,"ready":true,"earned":0,"spent":185,"next_seq":4,"roster":["p0-1|w03|top|75","p0-2|w05|top|60","p0-3|w01|top|50"],"hero":"","bookings":[],"new_bookings":[],"draft_roster":["p0-1|w03|top|75|true","p0-2|w05|top|60|true","p0-3|w01|top|50|true"],"draft_hero":"","boss_lane":"","undo":0},{"gold":35,"draft_gold":35,"ready":true,"earned":0,"spent":185,"next_seq":4,"roster":["p1-1|w03|mid|75","p1-2|w01|mid|50","p1-3|w05|mid|60"],"hero":"","bookings":[],"new_bookings":[],"draft_roster":["p1-1|w03|mid|75|true","p1-2|w01|mid|50|true","p1-3|w05|mid|60|true"],"draft_hero":"","boss_lane":"","undo":0},{"gold":40,"draft_gold":40,"ready":true,"earned":0,"spent":180,"next_seq":4,"roster":["p2-1|g03|bot|70","p2-2|g01|bot|45","p2-3|g05|bot|65"],"hero":"","bookings":[],"new_bookings":[],"draft_roster":["p2-1|g03|bot|70|true","p2-2|g01|bot|45|true","p2-3|g05|bot|65|true"],"draft_hero":"","boss_lane":"","undo":0},{"gold":40,"draft_gold":40,"ready":true,"earned":0,"spent":180,"next_seq":4,"roster":["p3-1|g03|top|70","p3-2|g05|top|65","p3-3|g01|top|45"],"hero":"","bookings":[],"new_bookings":[],"draft_roster":["p3-1|g03|top|70|true","p3-2|g05|top|65|true","p3-3|g01|top|45|true"],"draft_hero":"","boss_lane":"","undo":0},{"gold":35,"draft_gold":35,"ready":true,"earned":0,"spent":185,"next_seq":4,"roster":["p4-1|w01|mid|50","p4-2|w05|mid|60","p4-3|w03|mid|75"],"hero":"","bookings":[],"new_bookings":[],"draft_roster":["p4-1|w01|mid|50|true","p4-2|w05|mid|60|true","p4-3|w03|mid|75|true"],"draft_hero":"","boss_lane":"","undo":0},{"gold":85,"draft_gold":85,"ready":true,"earned":0,"spent":135,"next_seq":3,"roster":["p5-1|g05|bot|65","p5-2|g03|bot|70"],"hero":"","bookings":[],"new_bookings":[],"draft_roster":["p5-1|g05|bot|65|true","p5-2|g03|bot|70|true"],"draft_hero":"","boss_lane":"","undo":0}],"buildings":[7500.0,6000.0,7500.0,6000.0,7500.0,6000.0,9000.0,9000.0,12000.0,7500.0,6000.0,7500.0,6000.0,7500.0,6000.0,9000.0,9000.0,12000.0],"boss":{"next":1,"settled":0,"claim":""},"boss_log":[],"announcements":[],"settlement":null,"combat":{"round":1,"steps":200,"elapsed":10.000000000000007,"finished":false,"end_reason":"","destroyed":[],"grotto":"none|-1|-1|true","grotto_boss":"","grotto_boss_hp":0.0,"events":4,"mobile":[16,15,0]},"units":[{"id":1,"kind":"tower","team":0,"lane":"top","zone":"lane","slot":-1,"uid":"","def":"blau_top_inner","alive":true,"hp":7500.0,"max_hp":7500.0,"shield":0.0,"x":-24.931251525878906,"y":4.5293378829956055,"facing":0.0,"progress":0.0,"target":-1,"hits":0,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":2,"kind":"tower","team":0,"lane":"top","zone":"lane","slot":-1,"uid":"","def":"blau_top_outer","alive":true,"hp":6000.0,"max_hp":6000.0,"shield":0.0,"x":-24.921451568603516,"y":-12.715348243713379,"facing":0.0,"progress":0.0,"target":-1,"hits":0,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":3,"kind":"tower","team":0,"lane":"mid","zone":"lane","slot":-1,"uid":"","def":"blau_mid_inner","alive":true,"hp":7500.0,"max_hp":7500.0,"shield":0.0,"x":-11.427590370178223,"y":17.012392044067383,"facing":0.0,"progress":0.0,"target":-1,"hits":0,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":4,"kind":"tower","team":0,"lane":"mid","zone":"lane","slot":-1,"uid":"","def":"blau_mid_outer","alive":true,"hp":6000.0,"max_hp":6000.0,"shield":0.0,"x":-3.8433847427368164,"y":8.990991592407227,"facing":0.0,"progress":0.0,"target":-1,"hits":0,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":5,"kind":"tower","team":0,"lane":"bot","zone":"lane","slot":-1,"uid":"","def":"blau_bot_inner","alive":true,"hp":7500.0,"max_hp":7500.0,"shield":0.0,"x":-4.349228858947754,"y":31.034507751464844,"facing":0.0,"progress":0.0,"target":-1,"hits":0,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":6,"kind":"tower","team":0,"lane":"bot","zone":"lane","slot":-1,"uid":"","def":"blau_bot_outer","alive":true,"hp":6000.0,"max_hp":6000.0,"shield":0.0,"x":11.117134094238281,"y":28.989334106445313,"facing":0.0,"progress":0.0,"target":-1,"hits":0,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":7,"kind":"tower","team":0,"lane":"base","zone":"lane","slot":-1,"uid":"","def":"blau_base_1","alive":true,"hp":9000.0,"max_hp":9000.0,"shield":0.0,"x":-29.476999282836914,"y":24.023000717163086,"facing":0.0,"progress":0.0,"target":-1,"hits":0,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":8,"kind":"tower","team":0,"lane":"base","zone":"lane","slot":-1,"uid":"","def":"blau_base_2","alive":true,"hp":9000.0,"max_hp":9000.0,"shield":0.0,"x":-24.023000717163086,"y":29.476999282836914,"facing":0.0,"progress":0.0,"target":-1,"hits":0,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":9,"kind":"core","team":0,"lane":"base","zone":"lane","slot":-1,"uid":"","def":"blau_ancient","alive":true,"hp":12000.0,"max_hp":12000.0,"shield":0.0,"x":-30.0,"y":30.0,"facing":0.0,"progress":0.0,"target":-1,"hits":0,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":10,"kind":"tower","team":1,"lane":"top","zone":"lane","slot":-1,"uid":"","def":"rot_top_inner","alive":true,"hp":7500.0,"max_hp":7500.0,"shield":0.0,"x":4.5293378829956055,"y":-24.931251525878906,"facing":0.0,"progress":0.0,"target":-1,"hits":0,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":11,"kind":"tower","team":1,"lane":"top","zone":"lane","slot":-1,"uid":"","def":"rot_top_outer","alive":true,"hp":6000.0,"max_hp":6000.0,"shield":0.0,"x":-12.715348243713379,"y":-24.921451568603516,"facing":0.0,"progress":0.0,"target":-1,"hits":0,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":12,"kind":"tower","team":1,"lane":"mid","zone":"lane","slot":-1,"uid":"","def":"rot_mid_inner","alive":true,"hp":7500.0,"max_hp":7500.0,"shield":0.0,"x":17.012392044067383,"y":-11.427590370178223,"facing":0.0,"progress":0.0,"target":-1,"hits":0,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":13,"kind":"tower","team":1,"lane":"mid","zone":"lane","slot":-1,"uid":"","def":"rot_mid_outer","alive":true,"hp":6000.0,"max_hp":6000.0,"shield":0.0,"x":8.990991592407227,"y":-3.8433847427368164,"facing":0.0,"progress":0.0,"target":-1,"hits":0,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":14,"kind":"tower","team":1,"lane":"bot","zone":"lane","slot":-1,"uid":"","def":"rot_bot_inner","alive":true,"hp":7500.0,"max_hp":7500.0,"shield":0.0,"x":31.034507751464844,"y":-4.349228858947754,"facing":0.0,"progress":0.0,"target":-1,"hits":0,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":15,"kind":"tower","team":1,"lane":"bot","zone":"lane","slot":-1,"uid":"","def":"rot_bot_outer","alive":true,"hp":6000.0,"max_hp":6000.0,"shield":0.0,"x":28.989334106445313,"y":11.117134094238281,"facing":0.0,"progress":0.0,"target":-1,"hits":0,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":16,"kind":"tower","team":1,"lane":"base","zone":"lane","slot":-1,"uid":"","def":"rot_base_1","alive":true,"hp":9000.0,"max_hp":9000.0,"shield":0.0,"x":24.023000717163086,"y":-29.476999282836914,"facing":0.0,"progress":0.0,"target":-1,"hits":0,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":17,"kind":"tower","team":1,"lane":"base","zone":"lane","slot":-1,"uid":"","def":"rot_base_2","alive":true,"hp":9000.0,"max_hp":9000.0,"shield":0.0,"x":29.476999282836914,"y":-24.023000717163086,"facing":0.0,"progress":0.0,"target":-1,"hits":0,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":18,"kind":"core","team":1,"lane":"base","zone":"lane","slot":-1,"uid":"","def":"rot_ancient","alive":true,"hp":12000.0,"max_hp":12000.0,"shield":0.0,"x":30.0,"y":-30.0,"facing":0.0,"progress":0.0,"target":-1,"hits":0,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":19,"kind":"monster","team":0,"lane":"top","zone":"lane","slot":-1,"uid":"","def":"e01","alive":true,"hp":74.4,"max_hp":90.0,"shield":0.0,"x":-26.336877822875977,"y":-25.78684425354004,"facing":2.356194490192345,"progress":47.90360550768908,"target":28,"hits":2,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":20,"kind":"monster","team":0,"lane":"top","zone":"lane","slot":-1,"uid":"","def":"e01","alive":true,"hp":90.0,"max_hp":90.0,"shield":0.0,"x":-24.333051681518555,"y":-24.48856544494629,"facing":-2.9445368830574505,"progress":48.45394747825185,"target":30,"hits":2,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":21,"kind":"monster","team":0,"lane":"top","zone":"lane","slot":-1,"uid":"","def":"e01","alive":true,"hp":58.80000000000001,"max_hp":90.0,"shield":0.0,"x":-24.10462760925293,"y":-23.425823211669922,"facing":2.3466250841180427,"progress":48.119907427881714,"target":30,"hits":2,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":22,"kind":"monster","team":0,"lane":"mid","zone":"lane","slot":-1,"uid":"","def":"e01","alive":false,"hp":0.0,"max_hp":90.0,"shield":0.0,"x":-0.8889985084533691,"y":-0.8805634379386902,"facing":-3.0537923109537504,"progress":30.580075979232788,"target":-1,"hits":4,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":23,"kind":"monster","team":0,"lane":"mid","zone":"lane","slot":-1,"uid":"","def":"e01","alive":false,"hp":0.0,"max_hp":90.0,"shield":0.0,"x":0.08255975693464279,"y":0.081083282828331,"facing":2.1537038491238154,"progress":30.582202377266157,"target":-1,"hits":3,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":24,"kind":"monster","team":0,"lane":"mid","zone":"lane","slot":-1,"uid":"","def":"e01","alive":true,"hp":20.200000000000017,"max_hp":90.0,"shield":0.0,"x":0.6764076948165894,"y":1.2298187017440796,"facing":2.356194703746955,"progress":30.176166371817065,"target":33,"hits":6,"reached":false,"dormant":false,"effects":[],"dots":[["seed_burn",3.0,4.0,1.0,1]]},{"id":25,"kind":"monster","team":0,"lane":"bot","zone":"lane","slot":-1,"uid":"","def":"e01","alive":true,"hp":58.80000000000001,"max_hp":90.0,"shield":0.0,"x":23.04811668395996,"y":23.06899642944336,"facing":-2.6070052055054567,"progress":48.4104163646698,"target":34,"hits":2,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":26,"kind":"monster","team":0,"lane":"bot","zone":"lane","slot":-1,"uid":"","def":"e01","alive":true,"hp":90.0,"max_hp":90.0,"shield":0.0,"x":23.326805114746094,"y":24.02138900756836,"facing":-2.3918823331073202,"progress":48.055513201630205,"target":34,"hits":1,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":27,"kind":"monster","team":0,"lane":"bot","zone":"lane","slot":-1,"uid":"","def":"e01","alive":true,"hp":90.0,"max_hp":90.0,"shield":0.0,"x":24.038423538208008,"y":23.323423385620117,"facing":-2.4026513287137115,"progress":48.78178407157381,"target":34,"hits":1,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":28,"kind":"monster","team":1,"lane":"top","zone":"lane","slot":-1,"uid":"","def":"e01","alive":true,"hp":74.4,"max_hp":90.0,"shield":0.0,"x":-25.78684425354004,"y":-26.336877822875977,"facing":-0.7853981633974483,"progress":47.90360550768908,"target":19,"hits":2,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":29,"kind":"monster","team":1,"lane":"top","zone":"lane","slot":-1,"uid":"","def":"e01","alive":true,"hp":90.0,"max_hp":90.0,"shield":0.0,"x":-24.48856544494629,"y":-24.333051681518555,"facing":-1.7678520973272394,"progress":48.45394747825185,"target":21,"hits":2,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":30,"kind":"monster","team":1,"lane":"top","zone":"lane","slot":-1,"uid":"","def":"e01","alive":true,"hp":58.80000000000001,"max_hp":90.0,"shield":0.0,"x":-23.425823211669922,"y":-24.10462760925293,"facing":-0.7758287573231462,"progress":48.119907427881714,"target":21,"hits":2,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":31,"kind":"monster","team":1,"lane":"mid","zone":"lane","slot":-1,"uid":"","def":"e01","alive":false,"hp":0.0,"max_hp":90.0,"shield":0.0,"x":-0.8805634379386902,"y":-0.8889985084533691,"facing":-1.6585966694309395,"progress":30.580075979232788,"target":-1,"hits":4,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":32,"kind":"monster","team":1,"lane":"mid","zone":"lane","slot":-1,"uid":"","def":"e01","alive":false,"hp":0.0,"max_hp":90.0,"shield":0.0,"x":0.081083282828331,"y":0.08255975693464279,"facing":-0.5829075223289186,"progress":30.582202377266157,"target":-1,"hits":3,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":33,"kind":"monster","team":1,"lane":"mid","zone":"lane","slot":-1,"uid":"","def":"e01","alive":true,"hp":20.200000000000017,"max_hp":90.0,"shield":0.0,"x":1.2298187017440796,"y":0.6764076948165894,"facing":-0.7853983769520584,"progress":30.176166371817065,"target":24,"hits":6,"reached":false,"dormant":false,"effects":[],"dots":[["seed_burn",3.0,4.0,1.0,1]]},{"id":34,"kind":"monster","team":1,"lane":"bot","zone":"lane","slot":-1,"uid":"","def":"e01","alive":true,"hp":58.80000000000001,"max_hp":90.0,"shield":0.0,"x":23.068952560424805,"y":23.048269271850586,"facing":-2.1016653569233905,"progress":48.4104163646698,"target":25,"hits":2,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":35,"kind":"monster","team":1,"lane":"bot","zone":"lane","slot":-1,"uid":"","def":"e01","alive":true,"hp":90.0,"max_hp":90.0,"shield":0.0,"x":24.024150848388672,"y":23.316905975341797,"facing":-2.4384854854339713,"progress":48.055513201630205,"target":25,"hits":1,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":36,"kind":"monster","team":1,"lane":"bot","zone":"lane","slot":-1,"uid":"","def":"e01","alive":true,"hp":90.0,"max_hp":90.0,"shield":0.0,"x":23.324817657470703,"y":24.03773307800293,"facing":-2.3375804442147543,"progress":48.78178407157381,"target":25,"hits":1,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":37,"kind":"troop","team":0,"lane":"top","zone":"lane","slot":0,"uid":"p0-1","def":"w03","alive":true,"hp":620.0,"max_hp":620.0,"shield":0.0,"x":-27.765329360961914,"y":-22.471847534179688,"facing":2.087314204762464,"progress":44.665050335088765,"target":29,"hits":0,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":38,"kind":"troop","team":0,"lane":"top","zone":"lane","slot":0,"uid":"p0-3","def":"w01","alive":true,"hp":290.0,"max_hp":290.0,"shield":0.0,"x":-26.47719383239746,"y":-22.48335838317871,"facing":2.319940296699712,"progress":45.61861068106676,"target":29,"hits":0,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":39,"kind":"troop","team":0,"lane":"top","zone":"lane","slot":0,"uid":"p0-2","def":"w05","alive":true,"hp":230.0,"max_hp":230.0,"shield":0.0,"x":-28.250812530517578,"y":-17.209043502807617,"facing":-3.1151847797061727,"progress":39.19999999999987,"target":-1,"hits":0,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":40,"kind":"troop","team":0,"lane":"mid","zone":"lane","slot":1,"uid":"p1-1","def":"w03","alive":true,"hp":620.0,"max_hp":620.0,"shield":0.0,"x":-0.8488954305648804,"y":-0.639401376247406,"facing":-2.7425718083609354,"progress":30.4417898443998,"target":50,"hits":3,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":41,"kind":"troop","team":0,"lane":"mid","zone":"lane","slot":1,"uid":"p1-2","def":"w01","alive":true,"hp":243.20000000000002,"max_hp":290.0,"shield":0.0,"x":-0.43635040521621704,"y":0.3390342593193054,"facing":0.3990184170704089,"progress":30.087009024205507,"target":50,"hits":3,"reached":false,"dormant":false,"effects":[["root_grasp","movement_slow",0.2,1.95]],"dots":[]},{"id":42,"kind":"troop","team":0,"lane":"mid","zone":"lane","slot":1,"uid":"p1-3","def":"w05","alive":true,"hp":230.0,"max_hp":230.0,"shield":0.0,"x":-3.1128389835357666,"y":4.018820762634277,"facing":2.226768764710126,"progress":25.517524102031892,"target":33,"hits":4,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":43,"kind":"troop","team":0,"lane":"bot","zone":"lane","slot":2,"uid":"p2-1","def":"g03","alive":true,"hp":650.0,"max_hp":650.0,"shield":0.0,"x":22.06703758239746,"y":23.50967788696289,"facing":-1.1666023771027474,"progress":47.64064647383732,"target":34,"hits":0,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":44,"kind":"troop","team":0,"lane":"bot","zone":"lane","slot":2,"uid":"p2-2","def":"g01","alive":true,"hp":260.0,"max_hp":260.0,"shield":0.0,"x":22.39777183532715,"y":24.559009552001953,"facing":-1.0543444134835132,"progress":47.05294361818198,"target":36,"hits":0,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":45,"kind":"troop","team":0,"lane":"bot","zone":"lane","slot":2,"uid":"p2-3","def":"g05","alive":true,"hp":240.0,"max_hp":240.0,"shield":0.0,"x":17.03569793701172,"y":27.166902542114258,"facing":1.404038673419821,"progress":39.19999999999987,"target":-1,"hits":0,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":46,"kind":"troop","team":1,"lane":"top","zone":"lane","slot":3,"uid":"p3-1","def":"g03","alive":true,"hp":650.0,"max_hp":650.0,"shield":0.0,"x":-22.471847534179688,"y":-27.765329360961914,"facing":-0.5165178779675674,"progress":44.665050335088765,"target":20,"hits":0,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":47,"kind":"troop","team":1,"lane":"top","zone":"lane","slot":3,"uid":"p3-3","def":"g01","alive":true,"hp":260.0,"max_hp":260.0,"shield":0.0,"x":-22.48335838317871,"y":-26.47719383239746,"facing":-0.7491439699048152,"progress":45.61861068106676,"target":20,"hits":0,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":48,"kind":"troop","team":1,"lane":"top","zone":"lane","slot":3,"uid":"p3-2","def":"g05","alive":true,"hp":240.0,"max_hp":240.0,"shield":0.0,"x":-17.209043502807617,"y":-28.250812530517578,"facing":-1.5972042006785172,"progress":39.19999999999987,"target":-1,"hits":0,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":49,"kind":"troop","team":1,"lane":"mid","zone":"lane","slot":4,"uid":"p4-3","def":"w03","alive":true,"hp":620.0,"max_hp":620.0,"shield":0.0,"x":-0.639401376247406,"y":-0.8488954305648804,"facing":-1.9698171720237547,"progress":30.4417898443998,"target":41,"hits":3,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":50,"kind":"troop","team":1,"lane":"mid","zone":"lane","slot":4,"uid":"p4-1","def":"w01","alive":true,"hp":243.20000000000002,"max_hp":290.0,"shield":0.0,"x":0.3390342593193054,"y":-0.43635040521621704,"facing":1.1717779097244878,"progress":30.087009024205507,"target":41,"hits":3,"reached":false,"dormant":false,"effects":[["root_grasp","movement_slow",0.2,1.95]],"dots":[]},{"id":51,"kind":"troop","team":1,"lane":"mid","zone":"lane","slot":4,"uid":"p4-2","def":"w05","alive":true,"hp":230.0,"max_hp":230.0,"shield":0.0,"x":4.018820762634277,"y":-3.1128389835357666,"facing":-0.6559724379152297,"progress":25.517524102031892,"target":24,"hits":4,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":52,"kind":"troop","team":1,"lane":"bot","zone":"lane","slot":5,"uid":"p5-2","def":"g03","alive":true,"hp":650.0,"max_hp":650.0,"shield":0.0,"x":23.510141372680664,"y":22.06721305847168,"facing":2.733594976079501,"progress":47.64064647383732,"target":25,"hits":0,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":53,"kind":"troop","team":1,"lane":"bot","zone":"lane","slot":5,"uid":"p5-1","def":"g05","alive":true,"hp":240.0,"max_hp":240.0,"shield":0.0,"x":25.840801239013672,"y":17.226511001586914,"facing":-0.2850591563077598,"progress":39.168051593460966,"target":27,"hits":0,"reached":false,"dormant":false,"effects":[],"dots":[]}]},{"label":"t30","phase":1,"round":1,"winner":-2,"end_note":"","players":[{"gold":35,"draft_gold":35,"ready":true,"earned":0,"spent":185,"next_seq":4,"roster":["p0-1|w03|top|75","p0-2|w05|top|60","p0-3|w01|top|50"],"hero":"","bookings":[],"new_bookings":[],"draft_roster":["p0-1|w03|top|75|true","p0-2|w05|top|60|true","p0-3|w01|top|50|true"],"draft_hero":"","boss_lane":"","undo":0},{"gold":35,"draft_gold":35,"ready":true,"earned":0,"spent":185,"next_seq":4,"roster":["p1-1|w03|mid|75","p1-2|w01|mid|50","p1-3|w05|mid|60"],"hero":"","bookings":[],"new_bookings":[],"draft_roster":["p1-1|w03|mid|75|true","p1-2|w01|mid|50|true","p1-3|w05|mid|60|true"],"draft_hero":"","boss_lane":"","undo":0},{"gold":40,"draft_gold":40,"ready":true,"earned":0,"spent":180,"next_seq":4,"roster":["p2-1|g03|bot|70","p2-2|g01|bot|45","p2-3|g05|bot|65"],"hero":"","bookings":[],"new_bookings":[],"draft_roster":["p2-1|g03|bot|70|true","p2-2|g01|bot|45|true","p2-3|g05|bot|65|true"],"draft_hero":"","boss_lane":"","undo":0},{"gold":40,"draft_gold":40,"ready":true,"earned":0,"spent":180,"next_seq":4,"roster":["p3-1|g03|top|70","p3-2|g05|top|65","p3-3|g01|top|45"],"hero":"","bookings":[],"new_bookings":[],"draft_roster":["p3-1|g03|top|70|true","p3-2|g05|top|65|true","p3-3|g01|top|45|true"],"draft_hero":"","boss_lane":"","undo":0},{"gold":35,"draft_gold":35,"ready":true,"earned":0,"spent":185,"next_seq":4,"roster":["p4-1|w01|mid|50","p4-2|w05|mid|60","p4-3|w03|mid|75"],"hero":"","bookings":[],"new_bookings":[],"draft_roster":["p4-1|w01|mid|50|true","p4-2|w05|mid|60|true","p4-3|w03|mid|75|true"],"draft_hero":"","boss_lane":"","undo":0},{"gold":85,"draft_gold":85,"ready":true,"earned":0,"spent":135,"next_seq":3,"roster":["p5-1|g05|bot|65","p5-2|g03|bot|70"],"hero":"","bookings":[],"new_bookings":[],"draft_roster":["p5-1|g05|bot|65|true","p5-2|g03|bot|70|true"],"draft_hero":"","boss_lane":"","undo":0}],"buildings":[7500.0,6000.0,7500.0,6000.0,7500.0,6000.0,9000.0,9000.0,12000.0,7500.0,6000.0,7500.0,6000.0,7500.0,6000.0,9000.0,9000.0,12000.0],"boss":{"next":1,"settled":0,"claim":""},"boss_log":[],"announcements":[],"settlement":null,"combat":{"round":1,"steps":600,"elapsed":30.00000000000029,"finished":false,"end_reason":"","destroyed":[],"grotto":"none|-1|-1|true","grotto_boss":"","grotto_boss_hp":0.0,"events":26,"mobile":[5,4,0]},"units":[{"id":1,"kind":"tower","team":0,"lane":"top","zone":"lane","slot":-1,"uid":"","def":"blau_top_inner","alive":true,"hp":7500.0,"max_hp":7500.0,"shield":0.0,"x":-24.931251525878906,"y":4.5293378829956055,"facing":0.0,"progress":0.0,"target":-1,"hits":0,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":2,"kind":"tower","team":0,"lane":"top","zone":"lane","slot":-1,"uid":"","def":"blau_top_outer","alive":true,"hp":6000.0,"max_hp":6000.0,"shield":0.0,"x":-24.921451568603516,"y":-12.715348243713379,"facing":0.0,"progress":0.0,"target":-1,"hits":0,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":3,"kind":"tower","team":0,"lane":"mid","zone":"lane","slot":-1,"uid":"","def":"blau_mid_inner","alive":true,"hp":7500.0,"max_hp":7500.0,"shield":0.0,"x":-11.427590370178223,"y":17.012392044067383,"facing":0.0,"progress":0.0,"target":-1,"hits":0,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":4,"kind":"tower","team":0,"lane":"mid","zone":"lane","slot":-1,"uid":"","def":"blau_mid_outer","alive":true,"hp":6000.0,"max_hp":6000.0,"shield":0.0,"x":-3.8433847427368164,"y":8.990991592407227,"facing":0.0,"progress":0.0,"target":-1,"hits":0,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":5,"kind":"tower","team":0,"lane":"bot","zone":"lane","slot":-1,"uid":"","def":"blau_bot_inner","alive":true,"hp":7500.0,"max_hp":7500.0,"shield":0.0,"x":-4.349228858947754,"y":31.034507751464844,"facing":0.0,"progress":0.0,"target":-1,"hits":0,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":6,"kind":"tower","team":0,"lane":"bot","zone":"lane","slot":-1,"uid":"","def":"blau_bot_outer","alive":true,"hp":6000.0,"max_hp":6000.0,"shield":0.0,"x":11.117134094238281,"y":28.989334106445313,"facing":0.0,"progress":0.0,"target":-1,"hits":0,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":7,"kind":"tower","team":0,"lane":"base","zone":"lane","slot":-1,"uid":"","def":"blau_base_1","alive":true,"hp":9000.0,"max_hp":9000.0,"shield":0.0,"x":-29.476999282836914,"y":24.023000717163086,"facing":0.0,"progress":0.0,"target":-1,"hits":0,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":8,"kind":"tower","team":0,"lane":"base","zone":"lane","slot":-1,"uid":"","def":"blau_base_2","alive":true,"hp":9000.0,"max_hp":9000.0,"shield":0.0,"x":-24.023000717163086,"y":29.476999282836914,"facing":0.0,"progress":0.0,"target":-1,"hits":0,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":9,"kind":"core","team":0,"lane":"base","zone":"lane","slot":-1,"uid":"","def":"blau_ancient","alive":true,"hp":12000.0,"max_hp":12000.0,"shield":0.0,"x":-30.0,"y":30.0,"facing":0.0,"progress":0.0,"target":-1,"hits":0,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":10,"kind":"tower","team":1,"lane":"top","zone":"lane","slot":-1,"uid":"","def":"rot_top_inner","alive":true,"hp":7500.0,"max_hp":7500.0,"shield":0.0,"x":4.5293378829956055,"y":-24.931251525878906,"facing":0.0,"progress":0.0,"target":-1,"hits":0,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":11,"kind":"tower","team":1,"lane":"top","zone":"lane","slot":-1,"uid":"","def":"rot_top_outer","alive":true,"hp":6000.0,"max_hp":6000.0,"shield":0.0,"x":-12.715348243713379,"y":-24.921451568603516,"facing":0.0,"progress":0.0,"target":-1,"hits":0,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":12,"kind":"tower","team":1,"lane":"mid","zone":"lane","slot":-1,"uid":"","def":"rot_mid_inner","alive":true,"hp":7500.0,"max_hp":7500.0,"shield":0.0,"x":17.012392044067383,"y":-11.427590370178223,"facing":0.0,"progress":0.0,"target":-1,"hits":0,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":13,"kind":"tower","team":1,"lane":"mid","zone":"lane","slot":-1,"uid":"","def":"rot_mid_outer","alive":true,"hp":6000.0,"max_hp":6000.0,"shield":0.0,"x":8.990991592407227,"y":-3.8433847427368164,"facing":0.0,"progress":0.0,"target":-1,"hits":0,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":14,"kind":"tower","team":1,"lane":"bot","zone":"lane","slot":-1,"uid":"","def":"rot_bot_inner","alive":true,"hp":7500.0,"max_hp":7500.0,"shield":0.0,"x":31.034507751464844,"y":-4.349228858947754,"facing":0.0,"progress":0.0,"target":-1,"hits":0,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":15,"kind":"tower","team":1,"lane":"bot","zone":"lane","slot":-1,"uid":"","def":"rot_bot_outer","alive":true,"hp":6000.0,"max_hp":6000.0,"shield":0.0,"x":28.989334106445313,"y":11.117134094238281,"facing":0.0,"progress":0.0,"target":-1,"hits":0,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":16,"kind":"tower","team":1,"lane":"base","zone":"lane","slot":-1,"uid":"","def":"rot_base_1","alive":true,"hp":9000.0,"max_hp":9000.0,"shield":0.0,"x":24.023000717163086,"y":-29.476999282836914,"facing":0.0,"progress":0.0,"target":-1,"hits":0,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":17,"kind":"tower","team":1,"lane":"base","zone":"lane","slot":-1,"uid":"","def":"rot_base_2","alive":true,"hp":9000.0,"max_hp":9000.0,"shield":0.0,"x":29.476999282836914,"y":-24.023000717163086,"facing":0.0,"progress":0.0,"target":-1,"hits":0,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":18,"kind":"core","team":1,"lane":"base","zone":"lane","slot":-1,"uid":"","def":"rot_ancient","alive":true,"hp":12000.0,"max_hp":12000.0,"shield":0.0,"x":30.0,"y":-30.0,"facing":0.0,"progress":0.0,"target":-1,"hits":0,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":19,"kind":"monster","team":0,"lane":"top","zone":"lane","slot":-1,"uid":"","def":"e01","alive":false,"hp":0.0,"max_hp":90.0,"shield":0.0,"x":-26.336877822875977,"y":-25.78684425354004,"facing":2.356194490192345,"progress":47.90360550768908,"target":-1,"hits":12,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":20,"kind":"monster","team":0,"lane":"top","zone":"lane","slot":-1,"uid":"","def":"e01","alive":false,"hp":0.0,"max_hp":90.0,"shield":0.0,"x":-24.200542449951172,"y":-24.43142318725586,"facing":-2.8215975099120114,"progress":48.49643599379128,"target":-1,"hits":4,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":21,"kind":"monster","team":0,"lane":"top","zone":"lane","slot":-1,"uid":"","def":"e01","alive":false,"hp":0.0,"max_hp":90.0,"shield":0.0,"x":-23.441768646240234,"y":-23.300872802734375,"facing":1.264927112187464,"progress":48.4104163646698,"target":-1,"hits":6,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":22,"kind":"monster","team":0,"lane":"mid","zone":"lane","slot":-1,"uid":"","def":"e01","alive":false,"hp":0.0,"max_hp":90.0,"shield":0.0,"x":-0.8889985084533691,"y":-0.8805634379386902,"facing":-3.0537923109537504,"progress":30.580075979232788,"target":-1,"hits":4,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":23,"kind":"monster","team":0,"lane":"mid","zone":"lane","slot":-1,"uid":"","def":"e01","alive":false,"hp":0.0,"max_hp":90.0,"shield":0.0,"x":0.08255975693464279,"y":0.081083282828331,"facing":2.1537038491238154,"progress":30.582202377266157,"target":-1,"hits":3,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":24,"kind":"monster","team":0,"lane":"mid","zone":"lane","slot":-1,"uid":"","def":"e01","alive":false,"hp":0.0,"max_hp":90.0,"shield":0.0,"x":0.6764076948165894,"y":1.2298187017440796,"facing":2.356194703746955,"progress":30.176166371817065,"target":-1,"hits":7,"reached":false,"dormant":false,"effects":[],"dots":[["seed_burn",3.0,3.0000000000000036,0.9999999999999997,1]]},{"id":25,"kind":"monster","team":0,"lane":"bot","zone":"lane","slot":-1,"uid":"","def":"e01","alive":false,"hp":0.0,"max_hp":90.0,"shield":0.0,"x":22.720935821533203,"y":22.707666397094727,"facing":-2.260610277961388,"progress":48.4104163646698,"target":-1,"hits":4,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":26,"kind":"monster","team":0,"lane":"bot","zone":"lane","slot":-1,"uid":"","def":"e01","alive":false,"hp":0.0,"max_hp":90.0,"shield":0.0,"x":24.111921310424805,"y":22.832439422607422,"facing":1.911213882469501,"progress":49.15727951464866,"target":-1,"hits":5,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":27,"kind":"monster","team":0,"lane":"bot","zone":"lane","slot":-1,"uid":"","def":"e01","alive":false,"hp":0.0,"max_hp":90.0,"shield":0.0,"x":23.831138610839844,"y":22.68653106689453,"facing":2.732200311480404,"progress":49.04043952415074,"target":-1,"hits":4,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":28,"kind":"monster","team":1,"lane":"top","zone":"lane","slot":-1,"uid":"","def":"e01","alive":false,"hp":0.0,"max_hp":90.0,"shield":0.0,"x":-25.78684425354004,"y":-26.336877822875977,"facing":-0.7853981633974483,"progress":47.90360550768908,"target":-1,"hits":12,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":29,"kind":"monster","team":1,"lane":"top","zone":"lane","slot":-1,"uid":"","def":"e01","alive":false,"hp":0.0,"max_hp":90.0,"shield":0.0,"x":-24.43142318725586,"y":-24.200542449951172,"facing":-1.8907914704726783,"progress":48.49643599379128,"target":-1,"hits":4,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":30,"kind":"monster","team":1,"lane":"top","zone":"lane","slot":-1,"uid":"","def":"e01","alive":false,"hp":0.0,"max_hp":90.0,"shield":0.0,"x":-23.300872802734375,"y":-23.441768646240234,"facing":0.3058692146074327,"progress":48.4104163646698,"target":-1,"hits":6,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":31,"kind":"monster","team":1,"lane":"mid","zone":"lane","slot":-1,"uid":"","def":"e01","alive":false,"hp":0.0,"max_hp":90.0,"shield":0.0,"x":-0.8805634379386902,"y":-0.8889985084533691,"facing":-1.6585966694309395,"progress":30.580075979232788,"target":-1,"hits":4,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":32,"kind":"monster","team":1,"lane":"mid","zone":"lane","slot":-1,"uid":"","def":"e01","alive":false,"hp":0.0,"max_hp":90.0,"shield":0.0,"x":0.081083282828331,"y":0.08255975693464279,"facing":-0.5829075223289186,"progress":30.582202377266157,"target":-1,"hits":3,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":33,"kind":"monster","team":1,"lane":"mid","zone":"lane","slot":-1,"uid":"","def":"e01","alive":false,"hp":0.0,"max_hp":90.0,"shield":0.0,"x":1.2298187017440796,"y":0.6764076948165894,"facing":-0.7853983769520584,"progress":30.176166371817065,"target":-1,"hits":7,"reached":false,"dormant":false,"effects":[],"dots":[["seed_burn",3.0,3.0000000000000036,0.9999999999999997,1]]},{"id":34,"kind":"monster","team":1,"lane":"bot","zone":"lane","slot":-1,"uid":"","def":"e01","alive":false,"hp":0.0,"max_hp":90.0,"shield":0.0,"x":22.705503463745117,"y":22.723621368408203,"facing":-2.4323677583669117,"progress":48.4104163646698,"target":-1,"hits":4,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":35,"kind":"monster","team":1,"lane":"bot","zone":"lane","slot":-1,"uid":"","def":"e01","alive":false,"hp":0.0,"max_hp":90.0,"shield":0.0,"x":23.783607482910156,"y":23.11890983581543,"facing":0.2566253910622563,"progress":48.09927267039231,"target":-1,"hits":5,"reached":false,"dormant":false,"effects":[],"dots":[["burn",4.0,2.100000000000003,0.09999999999999969,0]]},{"id":36,"kind":"monster","team":1,"lane":"bot","zone":"lane","slot":-1,"uid":"","def":"e01","alive":false,"hp":0.0,"max_hp":90.0,"shield":0.0,"x":22.91436767578125,"y":23.704227447509766,"facing":-0.8701125455350757,"progress":48.79538230538446,"target":-1,"hits":3,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":37,"kind":"troop","team":0,"lane":"top","zone":"lane","slot":0,"uid":"p0-1","def":"w03","alive":true,"hp":234.20000000000005,"max_hp":620.0,"shield":0.0,"x":-25.28739356994629,"y":-24.50891876220703,"facing":2.356194490192345,"progress":47.87310884801354,"target":46,"hits":19,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":38,"kind":"troop","team":0,"lane":"top","zone":"lane","slot":0,"uid":"p0-3","def":"w01","alive":false,"hp":0.0,"max_hp":290.0,"shield":0.0,"x":-24.36732292175293,"y":-23.619245529174805,"facing":2.356194490192345,"progress":47.99603031695066,"target":-1,"hits":8,"reached":false,"dormant":false,"effects":[],"dots":[["burn",4.0,0.9000000000000026,0.8999999999999992,0]]},{"id":39,"kind":"troop","team":0,"lane":"top","zone":"lane","slot":0,"uid":"p0-2","def":"w05","alive":true,"hp":230.0,"max_hp":230.0,"shield":0.0,"x":-27.059839248657227,"y":-20.437320709228516,"facing":2.657396777410056,"progress":42.76849703855608,"target":46,"hits":17,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":40,"kind":"troop","team":0,"lane":"mid","zone":"lane","slot":1,"uid":"p1-1","def":"w03","alive":false,"hp":0.0,"max_hp":620.0,"shield":0.0,"x":-0.7991273999214172,"y":-0.665195643901825,"facing":-2.774590634448467,"progress":30.495059703431746,"target":-1,"hits":21,"reached":false,"dormant":false,"effects":[],"dots":[["seed_burn",3.0,1.0000000000000062,0.999999999999999,1]]},{"id":41,"kind":"troop","team":0,"lane":"mid","zone":"lane","slot":1,"uid":"p1-2","def":"w01","alive":false,"hp":0.0,"max_hp":290.0,"shield":0.0,"x":-0.4044324457645416,"y":0.3615542948246002,"facing":0.3670020191413261,"progress":30.087009024205507,"target":-1,"hits":10,"reached":false,"dormant":false,"effects":[["root_grasp","movement_slow",0.2,0.9999999999999991]],"dots":[]},{"id":42,"kind":"troop","team":0,"lane":"mid","zone":"lane","slot":1,"uid":"p1-3","def":"w05","alive":true,"hp":230.0,"max_hp":230.0,"shield":0.0,"x":-1.4292080402374268,"y":2.349886894226074,"facing":2.3561951120430598,"progress":27.892947899783255,"target":51,"hits":23,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":43,"kind":"troop","team":0,"lane":"bot","zone":"lane","slot":2,"uid":"p2-1","def":"g03","alive":true,"hp":374.7499999999999,"max_hp":650.0,"shield":0.0,"x":24.838329315185547,"y":19.200788497924805,"facing":2.5252042771483483,"progress":55.907349410876044,"target":53,"hits":18,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":44,"kind":"troop","team":0,"lane":"bot","zone":"lane","slot":2,"uid":"p2-2","def":"g01","alive":false,"hp":0.0,"max_hp":260.0,"shield":0.0,"x":23.384788513183594,"y":23.1483097076416,"facing":1.0399185216753972,"progress":48.4104163646698,"target":-1,"hits":10,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":45,"kind":"troop","team":0,"lane":"bot","zone":"lane","slot":2,"uid":"p2-3","def":"g05","alive":true,"hp":240.0,"max_hp":240.0,"shield":0.0,"x":24.499513626098633,"y":26.495243072509766,"facing":2.428235248982429,"progress":46.95225405805147,"target":-1,"hits":17,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":46,"kind":"troop","team":1,"lane":"top","zone":"lane","slot":3,"uid":"p3-1","def":"g03","alive":true,"hp":50.69999999999967,"max_hp":650.0,"shield":0.0,"x":-24.50891876220703,"y":-25.28739356994629,"facing":-0.7853981633974483,"progress":47.87310884801354,"target":37,"hits":19,"reached":false,"dormant":false,"effects":[],"dots":[["seed_burn",3.0,2.2000000000000064,0.19999999999999934,1]]},{"id":47,"kind":"troop","team":1,"lane":"top","zone":"lane","slot":3,"uid":"p3-3","def":"g01","alive":false,"hp":0.0,"max_hp":260.0,"shield":0.0,"x":-23.619245529174805,"y":-24.36732292175293,"facing":-0.7853981633974483,"progress":47.99603031695066,"target":-1,"hits":8,"reached":false,"dormant":false,"effects":[],"dots":[["seed_burn",3.0,1.0000000000000062,0.999999999999999,1]]},{"id":48,"kind":"troop","team":1,"lane":"top","zone":"lane","slot":3,"uid":"p3-2","def":"g05","alive":true,"hp":240.0,"max_hp":240.0,"shield":0.0,"x":-20.437320709228516,"y":-27.059839248657227,"facing":-1.0866004506151594,"progress":42.76849703855608,"target":37,"hits":17,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":49,"kind":"troop","team":1,"lane":"mid","zone":"lane","slot":4,"uid":"p4-3","def":"w03","alive":false,"hp":0.0,"max_hp":620.0,"shield":0.0,"x":-0.665195643901825,"y":-0.7991273999214172,"facing":-1.9377983459362227,"progress":30.495059703431746,"target":-1,"hits":21,"reached":false,"dormant":false,"effects":[],"dots":[["seed_burn",3.0,1.0000000000000062,0.999999999999999,1]]},{"id":50,"kind":"troop","team":1,"lane":"mid","zone":"lane","slot":4,"uid":"p4-1","def":"w01","alive":false,"hp":0.0,"max_hp":290.0,"shield":0.0,"x":0.3615542948246002,"y":-0.4044324457645416,"facing":1.2037943076535706,"progress":30.087009024205507,"target":-1,"hits":10,"reached":false,"dormant":false,"effects":[["root_grasp","movement_slow",0.2,0.9999999999999991]],"dots":[]},{"id":51,"kind":"troop","team":1,"lane":"mid","zone":"lane","slot":4,"uid":"p4-2","def":"w05","alive":true,"hp":230.0,"max_hp":230.0,"shield":0.0,"x":2.349886894226074,"y":-1.4292080402374268,"facing":-0.7853987852481631,"progress":27.892947899783255,"target":42,"hits":23,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":52,"kind":"troop","team":1,"lane":"bot","zone":"lane","slot":5,"uid":"p5-2","def":"g03","alive":false,"hp":0.0,"max_hp":650.0,"shield":0.0,"x":23.504980087280273,"y":22.055574417114258,"facing":-2.884967262527537,"progress":47.65861447492083,"target":-1,"hits":17,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":53,"kind":"troop","team":1,"lane":"bot","zone":"lane","slot":5,"uid":"p5-1","def":"g05","alive":true,"hp":225.7,"max_hp":240.0,"shield":0.0,"x":25.520475387573242,"y":18.237939834594727,"facing":-0.35629544431516813,"progress":40.09148489418724,"target":43,"hits":19,"reached":false,"dormant":false,"effects":[],"dots":[]}]},{"label":"settled","phase":0,"round":2,"winner":-2,"end_note":"","players":[{"gold":123,"draft_gold":123,"ready":true,"earned":88,"spent":185,"next_seq":4,"roster":["p0-1|w03|top|75","p0-2|w05|top|60","p0-3|w01|top|50"],"hero":"","bookings":[],"new_bookings":[],"draft_roster":["p0-1|w03|top|75|false","p0-2|w05|top|60|false","p0-3|w01|top|50|false"],"draft_hero":"","boss_lane":"","undo":0},{"gold":123,"draft_gold":123,"ready":true,"earned":88,"spent":185,"next_seq":4,"roster":["p1-1|w03|mid|75","p1-2|w01|mid|50","p1-3|w05|mid|60"],"hero":"","bookings":[],"new_bookings":[],"draft_roster":["p1-1|w03|mid|75|false","p1-2|w01|mid|50|false","p1-3|w05|mid|60|false"],"draft_hero":"","boss_lane":"","undo":0},{"gold":128,"draft_gold":128,"ready":true,"earned":88,"spent":180,"next_seq":4,"roster":["p2-1|g03|bot|70","p2-2|g01|bot|45","p2-3|g05|bot|65"],"hero":"","bookings":[],"new_bookings":[],"draft_roster":["p2-1|g03|bot|70|false","p2-2|g01|bot|45|false","p2-3|g05|bot|65|false"],"draft_hero":"","boss_lane":"","undo":0},{"gold":128,"draft_gold":128,"ready":true,"earned":88,"spent":180,"next_seq":4,"roster":["p3-1|g03|top|70","p3-2|g05|top|65","p3-3|g01|top|45"],"hero":"","bookings":[],"new_bookings":[],"draft_roster":["p3-1|g03|top|70|false","p3-2|g05|top|65|false","p3-3|g01|top|45|false"],"draft_hero":"","boss_lane":"","undo":0},{"gold":123,"draft_gold":123,"ready":true,"earned":88,"spent":185,"next_seq":4,"roster":["p4-1|w01|mid|50","p4-2|w05|mid|60","p4-3|w03|mid|75"],"hero":"","bookings":[],"new_bookings":[],"draft_roster":["p4-1|w01|mid|50|false","p4-2|w05|mid|60|false","p4-3|w03|mid|75|false"],"draft_hero":"","boss_lane":"","undo":0},{"gold":173,"draft_gold":173,"ready":true,"earned":88,"spent":135,"next_seq":3,"roster":["p5-1|g05|bot|65","p5-2|g03|bot|70"],"hero":"","bookings":[],"new_bookings":[],"draft_roster":["p5-1|g05|bot|65|false","p5-2|g03|bot|70|false"],"draft_hero":"","boss_lane":"","undo":0}],"buildings":[7500.0,6000.0,7500.0,6000.0,7500.0,6000.0,9000.0,9000.0,12000.0,7500.0,5970.1,7500.0,6000.0,7500.0,5890.8,9000.0,9000.0,12000.0],"boss":{"next":1,"settled":1,"claim":""},"boss_log":[],"announcements":[],"settlement":{"round":1,"gains":[18,18,18,18,18,18],"income":70,"lost":[],"end_reason":"cleared","combat_time":44.89999999999959,"boss":"none","lane_kills":{"mid":6,"bot":6,"top":6},"xp":{}},"combat":{"round":1,"steps":898,"elapsed":44.89999999999959,"finished":true,"end_reason":"cleared","destroyed":[],"grotto":"none|-1|-1|true","grotto_boss":"","grotto_boss_hp":0.0,"events":35,"mobile":[0,0,0]},"events":[[1,154,7.699999999999981,0,"mid","lane","monster",23,"e01",6,"",13,[]],[2,154,7.699999999999981,1,"mid","lane","monster",32,"e01",6,"",13,[]],[3,177,8.84999999999999,0,"mid","lane","monster",22,"e01",6,"",13,[]],[4,177,8.84999999999999,1,"mid","lane","monster",31,"e01",6,"",13,[]],[5,220,11.000000000000021,0,"mid","lane","monster",24,"e01",6,"",13,[]],[6,220,11.000000000000021,1,"mid","lane","monster",33,"e01",6,"",13,[]],[7,231,11.55000000000003,0,"bot","lane","monster",25,"e01",6,"",13,[]],[8,231,11.55000000000003,1,"bot","lane","monster",34,"e01",6,"",13,[]],[9,249,12.450000000000042,1,"bot","lane","monster",36,"e01",6,"",13,[]],[10,253,12.650000000000045,0,"top","lane","monster",20,"e01",6,"",13,[]],[11,253,12.650000000000045,1,"top","lane","monster",29,"e01",6,"",13,[]],[12,264,13.200000000000053,0,"bot","lane","monster",27,"e01",6,"",13,[]],[13,276,13.800000000000061,0,"top","lane","monster",21,"e01",6,"",13,[]],[14,276,13.800000000000061,1,"top","lane","monster",30,"e01",6,"",13,[]],[15,294,14.700000000000074,1,"bot","lane","monster",35,"e01",6,"",13,[]],[16,307,15.350000000000083,0,"bot","lane","monster",26,"e01",6,"",13,[]],[17,339,16.950000000000106,0,"mid","lane","troop",41,"w01",0,"",15,[]],[18,339,16.950000000000106,1,"mid","lane","troop",50,"w01",0,"",15,[]],[19,380,19.000000000000135,0,"top","lane","troop",38,"w01",0,"",15,[]],[20,380,19.000000000000135,1,"top","lane","troop",47,"g01",0,"",15,[]],[21,393,19.650000000000144,0,"top","lane","monster",19,"e01",6,"",13,[]],[22,393,19.650000000000144,1,"top","lane","monster",28,"e01",6,"",13,[]],[23,450,22.500000000000185,0,"bot","lane","troop",44,"g01",0,"",15,[]],[24,559,27.950000000000262,1,"bot","lane","troop",52,"g03",0,"",15,[]],[25,580,29.000000000000277,0,"mid","lane","troop",40,"w03",0,"",15,[]],[26,580,29.000000000000277,1,"mid","lane","troop",49,"w03",0,"",15,[]],[27,624,31.20000000000031,1,"top","lane","troop",46,"g03",0,"",15,[]],[28,740,37.000000000000036,1,"bot","lane","troop",53,"g05",0,"",15,[]],[29,744,37.200000000000024,0,"top","lane","troop",37,"w03",0,"",15,[]],[30,774,38.69999999999994,0,"mid","lane","troop",42,"w05",0,"",15,[]],[31,774,38.69999999999994,1,"mid","lane","troop",51,"w05",0,"",15,[]],[32,786,39.299999999999905,0,"bot","lane","troop",43,"g03",0,"",15,[]],[33,817,40.84999999999982,1,"top","lane","troop",48,"g05",0,"",15,[]],[34,846,42.299999999999734,0,"bot","lane","troop",45,"g05",0,"",15,[]],[35,898,44.89999999999959,0,"top","lane","troop",39,"w05",0,"",15,[]]]}],"results":[["begin",-1,"",true,""]]},"lane_outer_lost":{"title":"Lane verliert äußeren Turm: Bastion wird angreifbar, Marschgrenze rückt vor","snapshots":[{"label":"t25","phase":1,"round":6,"winner":-2,"end_note":"","players":[{"gold":40,"draft_gold":40,"ready":true,"earned":0,"spent":180,"next_seq":2,"roster":[],"hero":"","bookings":["c0-1|ch_belagerung|top|180|7"],"new_bookings":["c0-1|ch_belagerung|top|180"],"draft_roster":[],"draft_hero":"","boss_lane":"","undo":0},{"gold":40,"draft_gold":40,"ready":true,"earned":0,"spent":180,"next_seq":4,"roster":["p1-1|g03|mid|70","p1-2|g01|mid|45","p1-3|g05|mid|65"],"hero":"","bookings":[],"new_bookings":[],"draft_roster":["p1-1|g03|mid|70|true","p1-2|g01|mid|45|true","p1-3|g05|mid|65|true"],"draft_hero":"","boss_lane":"","undo":0},{"gold":70,"draft_gold":70,"ready":true,"earned":0,"spent":150,"next_seq":2,"roster":[],"hero":"","bookings":["c2-1|ch_schutz|bot|150|7"],"new_bookings":["c2-1|ch_schutz|bot|150"],"draft_roster":[],"draft_hero":"","boss_lane":"","undo":0},{"gold":0,"draft_gold":0,"ready":true,"earned":0,"spent":220,"next_seq":11,"roster":["p3-3|g01|top|45","p3-4|g05|top|65","p3-5|g03|top|70","p3-6|g07|top|95","p3-7|g01|top|45","p3-8|g05|top|65","p3-9|g01|top|45","p3-10|g03|top|70"],"hero":"h3-1|held_funkenlanze|0|top|glutklinge||260|false|","bookings":["c3-2|ch_belagerung|top|180|7"],"new_bookings":["c3-2|ch_belagerung|top|180"],"draft_roster":["p3-3|g01|top|45|true","p3-4|g05|top|65|true","p3-5|g03|top|70|true","p3-6|g07|top|95|true","p3-7|g01|top|45|true","p3-8|g05|top|65|true","p3-9|g01|top|45|true","p3-10|g03|top|70|true"],"draft_hero":"h3-1|held_funkenlanze|0|top|glutklinge||260|true|glutklinge","boss_lane":"","undo":0},{"gold":10,"draft_gold":10,"ready":true,"earned":0,"spent":210,"next_seq":3,"roster":["p4-2|w05|mid|60"],"hero":"","bookings":["c4-1|ch_druck|mid|150|7"],"new_bookings":["c4-1|ch_druck|mid|150"],"draft_roster":["p4-2|w05|mid|60|true"],"draft_hero":"","boss_lane":"","undo":0},{"gold":0,"draft_gold":0,"ready":true,"earned":0,"spent":220,"next_seq":3,"roster":["p5-2|g03|bot|70"],"hero":"","bookings":["c5-1|ch_schutz|bot|150|7"],"new_bookings":["c5-1|ch_schutz|bot|150"],"draft_roster":["p5-2|g03|bot|70|true"],"draft_hero":"","boss_lane":"","undo":0}],"buildings":[7500.0,0.0,7500.0,6000.0,7500.0,6000.0,9000.0,9000.0,12000.0,7500.0,6000.0,7500.0,6000.0,7500.0,6000.0,9000.0,9000.0,12000.0],"boss":{"next":1,"settled":0,"claim":""},"boss_log":[],"announcements":[],"settlement":null,"combat":{"round":6,"steps":500,"elapsed":25.00000000000022,"finished":false,"end_reason":"","destroyed":[],"grotto":"none|-1|-1|true","grotto_boss":"","grotto_boss_hp":0.0,"events":21,"mobile":[3,14,0]},"units":[{"id":1,"kind":"tower","team":0,"lane":"top","zone":"lane","slot":-1,"uid":"","def":"blau_top_inner","alive":true,"hp":7466.25,"max_hp":7500.0,"shield":0.0,"x":-24.931251525878906,"y":4.5293378829956055,"facing":0.0,"progress":0.0,"target":47,"hits":3,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":2,"kind":"tower","team":0,"lane":"mid","zone":"lane","slot":-1,"uid":"","def":"blau_mid_inner","alive":true,"hp":7500.0,"max_hp":7500.0,"shield":0.0,"x":-11.427590370178223,"y":17.012392044067383,"facing":0.0,"progress":0.0,"target":-1,"hits":0,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":3,"kind":"tower","team":0,"lane":"mid","zone":"lane","slot":-1,"uid":"","def":"blau_mid_outer","alive":true,"hp":6000.0,"max_hp":6000.0,"shield":0.0,"x":-3.8433847427368164,"y":8.990991592407227,"facing":0.0,"progress":0.0,"target":-1,"hits":0,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":4,"kind":"tower","team":0,"lane":"bot","zone":"lane","slot":-1,"uid":"","def":"blau_bot_inner","alive":true,"hp":7500.0,"max_hp":7500.0,"shield":0.0,"x":-4.349228858947754,"y":31.034507751464844,"facing":0.0,"progress":0.0,"target":-1,"hits":0,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":5,"kind":"tower","team":0,"lane":"bot","zone":"lane","slot":-1,"uid":"","def":"blau_bot_outer","alive":true,"hp":6000.0,"max_hp":6000.0,"shield":0.0,"x":11.117134094238281,"y":28.989334106445313,"facing":0.0,"progress":0.0,"target":-1,"hits":0,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":6,"kind":"tower","team":0,"lane":"base","zone":"lane","slot":-1,"uid":"","def":"blau_base_1","alive":true,"hp":9000.0,"max_hp":9000.0,"shield":0.0,"x":-29.476999282836914,"y":24.023000717163086,"facing":0.0,"progress":0.0,"target":-1,"hits":0,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":7,"kind":"tower","team":0,"lane":"base","zone":"lane","slot":-1,"uid":"","def":"blau_base_2","alive":true,"hp":9000.0,"max_hp":9000.0,"shield":0.0,"x":-24.023000717163086,"y":29.476999282836914,"facing":0.0,"progress":0.0,"target":-1,"hits":0,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":8,"kind":"core","team":0,"lane":"base","zone":"lane","slot":-1,"uid":"","def":"blau_ancient","alive":true,"hp":12000.0,"max_hp":12000.0,"shield":0.0,"x":-30.0,"y":30.0,"facing":0.0,"progress":0.0,"target":-1,"hits":0,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":9,"kind":"tower","team":1,"lane":"top","zone":"lane","slot":-1,"uid":"","def":"rot_top_inner","alive":true,"hp":7500.0,"max_hp":7500.0,"shield":0.0,"x":4.5293378829956055,"y":-24.931251525878906,"facing":0.0,"progress":0.0,"target":-1,"hits":0,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":10,"kind":"tower","team":1,"lane":"top","zone":"lane","slot":-1,"uid":"","def":"rot_top_outer","alive":true,"hp":6000.0,"max_hp":6000.0,"shield":0.0,"x":-12.715348243713379,"y":-24.921451568603516,"facing":0.0,"progress":0.0,"target":-1,"hits":0,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":11,"kind":"tower","team":1,"lane":"mid","zone":"lane","slot":-1,"uid":"","def":"rot_mid_inner","alive":true,"hp":7500.0,"max_hp":7500.0,"shield":0.0,"x":17.012392044067383,"y":-11.427590370178223,"facing":0.0,"progress":0.0,"target":-1,"hits":0,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":12,"kind":"tower","team":1,"lane":"mid","zone":"lane","slot":-1,"uid":"","def":"rot_mid_outer","alive":true,"hp":5825.864999999999,"max_hp":6000.0,"shield":0.0,"x":8.990991592407227,"y":-3.8433847427368164,"facing":0.0,"progress":0.0,"target":44,"hits":11,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":13,"kind":"tower","team":1,"lane":"bot","zone":"lane","slot":-1,"uid":"","def":"rot_bot_inner","alive":true,"hp":7500.0,"max_hp":7500.0,"shield":0.0,"x":31.034507751464844,"y":-4.349228858947754,"facing":0.0,"progress":0.0,"target":-1,"hits":0,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":14,"kind":"tower","team":1,"lane":"bot","zone":"lane","slot":-1,"uid":"","def":"rot_bot_outer","alive":true,"hp":6000.0,"max_hp":6000.0,"shield":0.0,"x":28.989334106445313,"y":11.117134094238281,"facing":0.0,"progress":0.0,"target":-1,"hits":0,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":15,"kind":"tower","team":1,"lane":"base","zone":"lane","slot":-1,"uid":"","def":"rot_base_1","alive":true,"hp":9000.0,"max_hp":9000.0,"shield":0.0,"x":24.023000717163086,"y":-29.476999282836914,"facing":0.0,"progress":0.0,"target":-1,"hits":0,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":16,"kind":"tower","team":1,"lane":"base","zone":"lane","slot":-1,"uid":"","def":"rot_base_2","alive":true,"hp":9000.0,"max_hp":9000.0,"shield":0.0,"x":29.476999282836914,"y":-24.023000717163086,"facing":0.0,"progress":0.0,"target":-1,"hits":0,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":17,"kind":"core","team":1,"lane":"base","zone":"lane","slot":-1,"uid":"","def":"rot_ancient","alive":true,"hp":12000.0,"max_hp":12000.0,"shield":0.0,"x":30.0,"y":-30.0,"facing":0.0,"progress":0.0,"target":-1,"hits":0,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":18,"kind":"monster","team":0,"lane":"top","zone":"lane","slot":-1,"uid":"","def":"e01","alive":false,"hp":0.0,"max_hp":142.875,"shield":0.0,"x":-26.333011627197266,"y":-25.782655715942383,"facing":2.357863506170092,"progress":47.9038301189518,"target":-1,"hits":5,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":19,"kind":"monster","team":0,"lane":"top","zone":"lane","slot":-1,"uid":"","def":"e02","alive":false,"hp":0.0,"max_hp":381.00000000000006,"shield":0.0,"x":-25.446674346923828,"y":-23.391029357910156,"facing":-1.0772757447219299,"progress":47.049296215976476,"target":-1,"hits":3,"reached":false,"dormant":false,"effects":[],"dots":[["burn",4.0,2.8000000000000007,0.5999999999999993,0]]},{"id":20,"kind":"monster","team":0,"lane":"top","zone":"lane","slot":-1,"uid":"","def":"e01","alive":false,"hp":0.0,"max_hp":142.875,"shield":0.0,"x":-24.478246688842773,"y":-23.91180419921875,"facing":2.0643169088678635,"progress":48.10143267370166,"target":-1,"hits":4,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":21,"kind":"monster","team":0,"lane":"top","zone":"lane","slot":-1,"uid":"","def":"e04","alive":false,"hp":0.0,"max_hp":206.37500000000003,"shield":0.0,"x":-29.317790985107422,"y":-21.509798049926758,"facing":2.509319025582201,"progress":43.245321393013,"target":-1,"hits":8,"reached":false,"dormant":false,"effects":[],"dots":[["burn",4.0,2.3000000000000025,0.29999999999999966,0]]},{"id":22,"kind":"monster","team":0,"lane":"mid","zone":"lane","slot":-1,"uid":"","def":"e01","alive":false,"hp":0.0,"max_hp":142.875,"shield":0.0,"x":-0.5065575838088989,"y":-1.0903542041778564,"facing":1.072325225628468,"progress":30.982304258239957,"target":-1,"hits":4,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":23,"kind":"monster","team":0,"lane":"mid","zone":"lane","slot":-1,"uid":"","def":"e02","alive":false,"hp":0.0,"max_hp":381.00000000000006,"shield":0.0,"x":2.6122539043426514,"y":-3.4977974891662598,"facing":0.41448960909332544,"progress":34.886324493338336,"target":-1,"hits":9,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":24,"kind":"monster","team":0,"lane":"mid","zone":"lane","slot":-1,"uid":"","def":"e01","alive":false,"hp":0.0,"max_hp":142.875,"shield":0.0,"x":1.9041410684585571,"y":0.8424826264381409,"facing":1.7138173437657855,"progress":31.348912833227896,"target":-1,"hits":7,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":25,"kind":"monster","team":0,"lane":"mid","zone":"lane","slot":-1,"uid":"","def":"e04","alive":true,"hp":206.37500000000003,"max_hp":206.37500000000003,"shield":0.0,"x":1.7766871452331543,"y":-2.8675708770751953,"facing":1.7052390929340722,"progress":33.84494720964946,"target":12,"hits":16,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":26,"kind":"monster","team":0,"lane":"bot","zone":"lane","slot":-1,"uid":"","def":"e01","alive":false,"hp":0.0,"max_hp":142.875,"shield":0.0,"x":23.207666397094727,"y":23.957345962524414,"facing":2.9590328004588864,"progress":48.025977360288756,"target":-1,"hits":4,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":27,"kind":"monster","team":0,"lane":"bot","zone":"lane","slot":-1,"uid":"","def":"e02","alive":false,"hp":0.0,"max_hp":381.00000000000006,"shield":0.0,"x":22.894752502441406,"y":25.010494232177734,"facing":-0.28927100560914176,"progress":47.09076384464836,"target":-1,"hits":12,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":28,"kind":"monster","team":0,"lane":"bot","zone":"lane","slot":-1,"uid":"","def":"e01","alive":false,"hp":0.0,"max_hp":142.875,"shield":0.0,"x":24.261028289794922,"y":24.273759841918945,"facing":1.3453379605118367,"progress":48.4104163646698,"target":-1,"hits":6,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":29,"kind":"monster","team":0,"lane":"bot","zone":"lane","slot":-1,"uid":"","def":"e04","alive":true,"hp":206.37500000000003,"max_hp":206.37500000000003,"shield":0.0,"x":18.27719497680664,"y":25.196977615356445,"facing":1.858462709477901,"progress":40.07096938590723,"target":55,"hits":17,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":30,"kind":"monster","team":1,"lane":"top","zone":"lane","slot":-1,"uid":"","def":"e01","alive":false,"hp":0.0,"max_hp":142.875,"shield":0.0,"x":-26.447927474975586,"y":-23.475067138671875,"facing":-0.8558845354012935,"progress":50.50956223457659,"target":-1,"hits":6,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":31,"kind":"monster","team":1,"lane":"top","zone":"lane","slot":-1,"uid":"","def":"e02","alive":true,"hp":381.00000000000006,"max_hp":381.00000000000006,"shield":0.0,"x":-25.52280616760254,"y":1.655232310295105,"facing":0.17044757211350164,"progress":76.38833543599881,"target":1,"hits":2,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":32,"kind":"monster","team":1,"lane":"top","zone":"lane","slot":-1,"uid":"","def":"e01","alive":false,"hp":0.0,"max_hp":142.875,"shield":0.0,"x":-24.99301528930664,"y":1.0902845859527588,"facing":0.017961833546033604,"progress":75.56082728074564,"target":-1,"hits":7,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":33,"kind":"monster","team":1,"lane":"top","zone":"lane","slot":-1,"uid":"","def":"e04","alive":true,"hp":206.37500000000003,"max_hp":206.37500000000003,"shield":0.0,"x":-27.593053817749023,"y":-2.2281253337860107,"facing":0.7858683091079894,"progress":73.27083813701115,"target":1,"hits":6,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":34,"kind":"monster","team":1,"lane":"mid","zone":"lane","slot":-1,"uid":"","def":"e01","alive":false,"hp":0.0,"max_hp":142.875,"shield":0.0,"x":-0.6002305746078491,"y":-1.1809258460998535,"facing":-0.7865089085837635,"progress":30.18125924636331,"target":-1,"hits":4,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":35,"kind":"monster","team":1,"lane":"mid","zone":"lane","slot":-1,"uid":"","def":"e02","alive":false,"hp":0.0,"max_hp":381.00000000000006,"shield":0.0,"x":1.4388078451156616,"y":-0.030587155371904373,"facing":2.8440590802952332,"progress":29.697552512135495,"target":-1,"hits":6,"reached":false,"dormant":false,"effects":[],"dots":[["burn",4.0,2.8000000000000007,0.7999999999999998,0]]},{"id":36,"kind":"monster","team":1,"lane":"mid","zone":"lane","slot":-1,"uid":"","def":"e01","alive":false,"hp":0.0,"max_hp":142.875,"shield":0.0,"x":1.116278052330017,"y":1.0210646390914917,"facing":-0.2975394445210082,"progress":30.49861845298569,"target":-1,"hits":4,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":37,"kind":"monster","team":1,"lane":"mid","zone":"lane","slot":-1,"uid":"","def":"e04","alive":false,"hp":0.0,"max_hp":206.37500000000003,"shield":0.0,"x":3.2686283588409424,"y":-4.496224880218506,"facing":1.2362110046284376,"progress":25.164338588882558,"target":-1,"hits":16,"reached":false,"dormant":false,"effects":[],"dots":[["burn",4.0,3.0,1.0,0]]},{"id":38,"kind":"monster","team":1,"lane":"bot","zone":"lane","slot":-1,"uid":"","def":"e01","alive":false,"hp":0.0,"max_hp":142.875,"shield":0.0,"x":23.84368896484375,"y":23.571542739868164,"facing":0.7332829182762721,"progress":48.35040165454588,"target":-1,"hits":4,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":39,"kind":"monster","team":1,"lane":"bot","zone":"lane","slot":-1,"uid":"","def":"e02","alive":true,"hp":381.00000000000006,"max_hp":381.00000000000006,"shield":0.0,"x":19.47996711730957,"y":25.245149612426758,"facing":-0.19903792861866773,"progress":55.58432855995054,"target":29,"hits":11,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":40,"kind":"monster","team":1,"lane":"bot","zone":"lane","slot":-1,"uid":"","def":"e01","alive":false,"hp":0.0,"max_hp":142.875,"shield":0.0,"x":23.83830451965332,"y":25.33006477355957,"facing":0.0419785554332119,"progress":49.42018680059612,"target":-1,"hits":12,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":41,"kind":"monster","team":1,"lane":"bot","zone":"lane","slot":-1,"uid":"","def":"e04","alive":true,"hp":206.37500000000003,"max_hp":206.37500000000003,"shield":0.0,"x":24.03540802001953,"y":23.57599639892578,"facing":-1.2963924879236302,"progress":48.20797566540711,"target":29,"hits":13,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":42,"kind":"troop","team":0,"lane":"mid","zone":"lane","slot":1,"uid":"p1-1","def":"g03","alive":false,"hp":0.0,"max_hp":650.0,"shield":0.0,"x":2.16664981842041,"y":-4.83034610748291,"facing":2.35372135515755,"progress":35.46510864668858,"target":-1,"hits":8,"reached":false,"dormant":false,"effects":[],"dots":[["seed_burn",3.0,1.900000000000007,0.8999999999999992,1]]},{"id":43,"kind":"troop","team":0,"lane":"mid","zone":"lane","slot":1,"uid":"p1-2","def":"g01","alive":false,"hp":0.0,"max_hp":260.0,"shield":0.0,"x":6.622032165527344,"y":-4.072361946105957,"facing":1.474434268440447,"progress":38.19446194963247,"target":-1,"hits":12,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":44,"kind":"troop","team":0,"lane":"mid","zone":"lane","slot":1,"uid":"p1-3","def":"g05","alive":true,"hp":60.0,"max_hp":240.0,"shield":0.0,"x":2.7751405239105225,"y":-1.1356934309005737,"facing":1.9816188843551596,"progress":33.372423046612724,"target":12,"hits":16,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":45,"kind":"troop","team":1,"lane":"top","zone":"lane","slot":3,"uid":"p3-5","def":"g03","alive":true,"hp":650.0,"max_hp":650.0,"shield":0.0,"x":-26.06999397277832,"y":2.3192663192749023,"facing":-0.20240797439671696,"progress":77.18306937228034,"target":1,"hits":4,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":46,"kind":"troop","team":1,"lane":"top","zone":"lane","slot":3,"uid":"p3-10","def":"g03","alive":true,"hp":650.0,"max_hp":650.0,"shield":0.0,"x":-25.153207778930664,"y":2.088304042816162,"facing":0.9974525003072502,"progress":76.8098762511544,"target":1,"hits":4,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":47,"kind":"troop","team":1,"lane":"top","zone":"lane","slot":3,"uid":"p3-3","def":"g01","alive":true,"hp":80.0,"max_hp":260.0,"shield":0.0,"x":-25.194660186767578,"y":3.059556245803833,"facing":-0.013227770966871747,"progress":78.13185618443711,"target":1,"hits":5,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":48,"kind":"troop","team":1,"lane":"top","zone":"lane","slot":3,"uid":"p3-7","def":"g01","alive":true,"hp":260.0,"max_hp":260.0,"shield":0.0,"x":-24.242090225219727,"y":2.2323131561279297,"facing":1.3996824573196402,"progress":76.61472908270532,"target":1,"hits":6,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":49,"kind":"troop","team":1,"lane":"top","zone":"lane","slot":3,"uid":"p3-9","def":"g01","alive":true,"hp":260.0,"max_hp":260.0,"shield":0.0,"x":-26.553598403930664,"y":3.0607423782348633,"facing":-0.5671754816562697,"progress":78.31536606691597,"target":1,"hits":3,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":50,"kind":"troop","team":1,"lane":"top","zone":"lane","slot":3,"uid":"p3-6","def":"g07","alive":true,"hp":310.0,"max_hp":310.0,"shield":0.0,"x":-26.456178665161133,"y":-1.7355650663375854,"facing":0.23876152795099503,"progress":73.41670007718959,"target":1,"hits":2,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":51,"kind":"hero","team":1,"lane":"top","zone":"lane","slot":3,"uid":"h3-1","def":"g05","alive":true,"hp":950.0,"max_hp":950.0,"shield":0.0,"x":-25.721187591552734,"y":-2.7469992637634277,"facing":0.10814264391910546,"progress":72.23697703292356,"target":1,"hits":3,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":52,"kind":"troop","team":1,"lane":"top","zone":"lane","slot":3,"uid":"p3-4","def":"g05","alive":true,"hp":240.0,"max_hp":240.0,"shield":0.0,"x":-24.63284683227539,"y":-2.4424636363983154,"facing":-0.042773403147639305,"progress":72.21662878973851,"target":1,"hits":3,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":53,"kind":"troop","team":1,"lane":"top","zone":"lane","slot":3,"uid":"p3-8","def":"g05","alive":true,"hp":240.0,"max_hp":240.0,"shield":0.0,"x":-28.40916633605957,"y":-2.844017505645752,"facing":-0.29876738027632427,"progress":72.91552072082924,"target":-1,"hits":2,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":54,"kind":"troop","team":1,"lane":"mid","zone":"lane","slot":4,"uid":"p4-2","def":"w05","alive":false,"hp":0.0,"max_hp":230.0,"shield":0.0,"x":2.2122550010681152,"y":-4.837136268615723,"facing":-0.7098310884786565,"progress":25.661763393180767,"target":-1,"hits":11,"reached":false,"dormant":false,"effects":[],"dots":[["burn",4.0,2.8000000000000007,0.7999999999999998,0]]},{"id":55,"kind":"troop","team":1,"lane":"bot","zone":"lane","slot":5,"uid":"p5-2","def":"g03","alive":true,"hp":336.14750000000026,"max_hp":650.0,"shield":0.0,"x":18.959611892700195,"y":24.63099479675293,"facing":-2.413101445210958,"progress":56.182350025557824,"target":29,"hits":12,"reached":false,"dormant":false,"effects":[],"dots":[]}]},{"label":"settled","phase":0,"round":7,"winner":-2,"end_note":"","players":[{"gold":170,"draft_gold":170,"ready":true,"earned":130,"spent":180,"next_seq":2,"roster":[],"hero":"","bookings":["c0-1|ch_belagerung|top|180|7"],"new_bookings":[],"draft_roster":[],"draft_hero":"","boss_lane":"","undo":0},{"gold":170,"draft_gold":170,"ready":true,"earned":130,"spent":180,"next_seq":4,"roster":["p1-1|g03|mid|70","p1-2|g01|mid|45","p1-3|g05|mid|65"],"hero":"","bookings":[],"new_bookings":[],"draft_roster":["p1-1|g03|mid|70|false","p1-2|g01|mid|45|false","p1-3|g05|mid|65|false"],"draft_hero":"","boss_lane":"","undo":0},{"gold":200,"draft_gold":200,"ready":true,"earned":130,"spent":150,"next_seq":2,"roster":[],"hero":"","bookings":["c2-1|ch_schutz|bot|150|7"],"new_bookings":[],"draft_roster":[],"draft_hero":"","boss_lane":"","undo":0},{"gold":200,"draft_gold":200,"ready":true,"earned":200,"spent":220,"next_seq":11,"roster":["p3-3|g01|top|45","p3-4|g05|top|65","p3-5|g03|top|70","p3-6|g07|top|95","p3-7|g01|top|45","p3-8|g05|top|65","p3-9|g01|top|45","p3-10|g03|top|70"],"hero":"h3-1|held_funkenlanze|208|top|glutklinge||260|false|","bookings":["c3-2|ch_belagerung|top|180|7"],"new_bookings":[],"draft_roster":["p3-3|g01|top|45|false","p3-4|g05|top|65|false","p3-5|g03|top|70|false","p3-6|g07|top|95|false","p3-7|g01|top|45|false","p3-8|g05|top|65|false","p3-9|g01|top|45|false","p3-10|g03|top|70|false"],"draft_hero":"h3-1|held_funkenlanze|208|top|glutklinge||260|false|","boss_lane":"","undo":0},{"gold":210,"draft_gold":210,"ready":true,"earned":200,"spent":210,"next_seq":3,"roster":["p4-2|w05|mid|60"],"hero":"","bookings":["c4-1|ch_druck|mid|150|7"],"new_bookings":[],"draft_roster":["p4-2|w05|mid|60|false"],"draft_hero":"","boss_lane":"","undo":0},{"gold":200,"draft_gold":200,"ready":true,"earned":200,"spent":220,"next_seq":3,"roster":["p5-2|g03|bot|70"],"hero":"","bookings":["c5-1|ch_schutz|bot|150|7"],"new_bookings":[],"draft_roster":["p5-2|g03|bot|70|false"],"draft_hero":"","boss_lane":"","undo":0}],"buildings":[0.0,0.0,7500.0,6000.0,7500.0,5759.066249999995,8753.026,9000.0,12000.0,7500.0,6000.0,7500.0,5760.929999999998,7500.0,6000.0,9000.0,9000.0,12000.0],"boss":{"next":1,"settled":6,"claim":""},"boss_log":[],"announcements":["champion|0|0|top|ch_belagerung|0","champion|0|2|bot|ch_schutz|0","champion|1|3|top|ch_belagerung|0","champion|1|4|mid|ch_druck|0","champion|1|5|bot|ch_schutz|0"],"settlement":{"round":6,"gains":[40,40,40,110,110,110],"income":90,"lost":["blau_top_inner"],"end_reason":"cleared","combat_time":77.29999999999775,"boss":"none","lane_kills":{"mid":8,"bot":8,"top":8},"xp":{"h3-1":208}},"combat":{"round":6,"steps":1546,"elapsed":77.29999999999775,"finished":true,"end_reason":"cleared","destroyed":[],"grotto":"none|-1|-1|true","grotto_boss":"","grotto_boss_hp":0.0,"events":39,"mobile":[0,0,0]},"events":[[1,159,7.94999999999998,1,"mid","lane","monster",34,"e01",7,"",18,[]],[2,160,7.99999999999998,0,"mid","lane","monster",22,"e01",7,"",18,[]],[3,177,8.84999999999999,1,"mid","lane","monster",36,"e01",7,"",18,[]],[4,232,11.60000000000003,0,"mid","lane","monster",24,"e01",7,"",18,[]],[5,236,11.800000000000033,0,"bot","lane","monster",26,"e01",7,"",18,[]],[6,238,11.900000000000034,1,"bot","lane","monster",38,"e01",7,"",18,[]],[7,245,12.250000000000039,0,"top","lane","monster",20,"e01",7,"",18,["h3-1"]],[8,255,12.750000000000046,0,"top","lane","monster",18,"e01",7,"",18,["h3-1"]],[9,263,13.150000000000052,1,"mid","lane","monster",35,"e02",14,"",18,[]],[10,295,14.750000000000075,1,"top","lane","monster",30,"e01",7,"",18,[]],[11,296,14.800000000000075,0,"bot","lane","monster",28,"e01",7,"",18,[]],[12,298,14.900000000000077,0,"top","lane","monster",19,"e02",14,"",18,["h3-1"]],[13,323,16.150000000000095,0,"mid","lane","troop",42,"g03",0,"",15,[]],[14,348,17.400000000000112,0,"top","lane","monster",21,"e04",12,"",18,["h3-1"]],[15,352,17.600000000000115,1,"mid","lane","troop",54,"w05",0,"",15,[]],[16,384,19.200000000000138,0,"mid","lane","monster",23,"e02",14,"",18,[]],[17,414,20.70000000000016,1,"bot","lane","monster",40,"e01",7,"",18,[]],[18,418,20.900000000000162,1,"mid","lane","monster",37,"e04",12,"",18,[]],[19,444,22.20000000000018,0,"mid","lane","troop",43,"g01",0,"",15,[]],[20,447,22.350000000000183,1,"top","lane","monster",32,"e01",7,"",18,[]],[21,463,23.150000000000194,0,"bot","lane","monster",27,"e02",14,"",18,[]],[22,504,25.200000000000223,0,"mid","lane","troop",44,"g05",0,"",15,[]],[23,507,25.350000000000225,1,"top","lane","troop",47,"g01",0,"",15,[]],[24,564,28.200000000000266,0,"mid","lane","monster",25,"e04",12,"",18,[]],[25,567,28.350000000000268,1,"top","lane","troop",49,"g01",0,"",15,[]],[26,599,29.95000000000029,0,"bot","lane","monster",29,"e04",12,"",18,[]],[27,627,31.35000000000031,1,"top","lane","troop",48,"g01",0,"",15,[]],[28,663,33.150000000000254,1,"bot","lane","troop",55,"g03",0,"",15,[]],[29,743,37.15000000000003,1,"bot","lane","monster",39,"e02",14,"",18,[]],[30,747,37.350000000000016,1,"top","lane","troop",46,"g03",0,"",15,[]],[31,803,40.14999999999986,1,"bot","lane","monster",41,"e04",12,"",18,[]],[32,827,41.34999999999979,1,"top","lane","monster",31,"e02",14,"",18,[]],[33,947,47.34999999999945,1,"top","lane","troop",45,"g03",0,"",15,[]],[34,1027,51.34999999999922,1,"top","lane","troop",50,"g07",0,"",15,[]],[35,1087,54.34999999999905,1,"top","lane","troop",53,"g05",0,"",15,[]],[36,1147,57.34999999999888,1,"top","lane","troop",52,"g05",0,"",15,[]],[37,1207,60.34999999999871,1,"top","lane","monster",33,"e04",12,"",18,[]],[38,1339,66.94999999999834,0,"top","lane","tower",1,"blau_top_inner",210,"blau_top_inner",60,["h3-1"]],[39,1546,77.29999999999775,1,"top","lane","hero",51,"g05",0,"",15,[]]]}],"results":[["begin",-1,"",true,""]]},"lane_both_lost":{"title":"Lane verliert beide Türme: Basistürme angreifbar","snapshots":[{"label":"t35","phase":1,"round":8,"winner":-2,"end_note":"","players":[{"gold":40,"draft_gold":40,"ready":true,"earned":0,"spent":180,"next_seq":4,"roster":["p0-1|g03|top|70","p0-2|g01|top|45","p0-3|g05|top|65"],"hero":"","bookings":[],"new_bookings":[],"draft_roster":["p0-1|g03|top|70|true","p0-2|g01|top|45|true","p0-3|g05|top|65|true"],"draft_hero":"","boss_lane":"","undo":0},{"gold":70,"draft_gold":70,"ready":true,"earned":0,"spent":150,"next_seq":2,"roster":[],"hero":"","bookings":["c1-1|ch_schutz|mid|150|9"],"new_bookings":["c1-1|ch_schutz|mid|150"],"draft_roster":[],"draft_hero":"","boss_lane":"","undo":0},{"gold":40,"draft_gold":40,"ready":true,"earned":0,"spent":180,"next_seq":2,"roster":[],"hero":"","bookings":["c2-1|ch_belagerung|bot|180|9"],"new_bookings":["c2-1|ch_belagerung|bot|180"],"draft_roster":[],"draft_hero":"","boss_lane":"","undo":0},{"gold":10,"draft_gold":10,"ready":true,"earned":0,"spent":210,"next_seq":3,"roster":["p3-2|w05|top|60"],"hero":"","bookings":["c3-1|ch_druck|top|150|9"],"new_bookings":["c3-1|ch_druck|top|150"],"draft_roster":["p3-2|w05|top|60|true"],"draft_hero":"","boss_lane":"","undo":0},{"gold":0,"draft_gold":0,"ready":true,"earned":0,"spent":220,"next_seq":3,"roster":["p4-2|g03|mid|70"],"hero":"","bookings":["c4-1|ch_schutz|mid|150|9"],"new_bookings":["c4-1|ch_schutz|mid|150"],"draft_roster":["p4-2|g03|mid|70|true"],"draft_hero":"","boss_lane":"","undo":0},{"gold":55,"draft_gold":55,"ready":true,"earned":0,"spent":165,"next_seq":10,"roster":["p5-3|w04|top|230","p5-4|w02|top|150","p5-5|w06|top|195","p5-6|w04|top|230","p5-7|w07|top|100","p5-8|w09|top|90","p5-9|w01|top|50"],"hero":"h5-1|held_ringborke|0|bot|glutklinge||260|false|","bookings":["c5-2|ch_belagerung|bot|180|9"],"new_bookings":["c5-2|ch_belagerung|bot|180"],"draft_roster":["p5-3|w04|top|230|true","p5-4|w02|top|150|true","p5-5|w06|top|195|true","p5-6|w04|top|230|true","p5-7|w07|top|100|true","p5-8|w09|top|90|true","p5-9|w01|top|50|true"],"draft_hero":"h5-1|held_ringborke|0|bot|glutklinge||260|true|glutklinge","boss_lane":"","undo":0}],"buildings":[7500.0,6000.0,7500.0,6000.0,0.0,0.0,9000.0,9000.0,12000.0,7500.0,6000.0,7500.0,6000.0,7500.0,6000.0,9000.0,9000.0,12000.0],"boss":{"next":1,"settled":0,"claim":""},"boss_log":[],"announcements":[],"settlement":null,"combat":{"round":8,"steps":700,"elapsed":35.00000000000015,"finished":false,"end_reason":"","destroyed":[],"grotto":"none|-1|-1|true","grotto_boss":"","grotto_boss_hp":0.0,"events":30,"mobile":[0,13,0]},"units":[{"id":1,"kind":"tower","team":0,"lane":"top","zone":"lane","slot":-1,"uid":"","def":"blau_top_inner","alive":true,"hp":7500.0,"max_hp":7500.0,"shield":0.0,"x":-24.931251525878906,"y":4.5293378829956055,"facing":0.0,"progress":0.0,"target":-1,"hits":0,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":2,"kind":"tower","team":0,"lane":"top","zone":"lane","slot":-1,"uid":"","def":"blau_top_outer","alive":true,"hp":3660.326299999997,"max_hp":6000.0,"shield":0.0,"x":-24.921451568603516,"y":-12.715348243713379,"facing":0.0,"progress":0.0,"target":51,"hits":14,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":3,"kind":"tower","team":0,"lane":"mid","zone":"lane","slot":-1,"uid":"","def":"blau_mid_inner","alive":true,"hp":7500.0,"max_hp":7500.0,"shield":0.0,"x":-11.427590370178223,"y":17.012392044067383,"facing":0.0,"progress":0.0,"target":59,"hits":0,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":4,"kind":"tower","team":0,"lane":"mid","zone":"lane","slot":-1,"uid":"","def":"blau_mid_outer","alive":true,"hp":6000.0,"max_hp":6000.0,"shield":0.0,"x":-3.8433847427368164,"y":8.990991592407227,"facing":0.0,"progress":0.0,"target":-1,"hits":10,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":5,"kind":"tower","team":0,"lane":"base","zone":"lane","slot":-1,"uid":"","def":"blau_base_1","alive":true,"hp":9000.0,"max_hp":9000.0,"shield":0.0,"x":-29.476999282836914,"y":24.023000717163086,"facing":0.0,"progress":0.0,"target":-1,"hits":0,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":6,"kind":"tower","team":0,"lane":"base","zone":"lane","slot":-1,"uid":"","def":"blau_base_2","alive":true,"hp":9000.0,"max_hp":9000.0,"shield":0.0,"x":-24.023000717163086,"y":29.476999282836914,"facing":0.0,"progress":0.0,"target":-1,"hits":0,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":7,"kind":"core","team":0,"lane":"base","zone":"lane","slot":-1,"uid":"","def":"blau_ancient","alive":true,"hp":12000.0,"max_hp":12000.0,"shield":0.0,"x":-30.0,"y":30.0,"facing":0.0,"progress":0.0,"target":-1,"hits":0,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":8,"kind":"tower","team":1,"lane":"top","zone":"lane","slot":-1,"uid":"","def":"rot_top_inner","alive":true,"hp":7500.0,"max_hp":7500.0,"shield":0.0,"x":4.5293378829956055,"y":-24.931251525878906,"facing":0.0,"progress":0.0,"target":-1,"hits":0,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":9,"kind":"tower","team":1,"lane":"top","zone":"lane","slot":-1,"uid":"","def":"rot_top_outer","alive":true,"hp":6000.0,"max_hp":6000.0,"shield":0.0,"x":-12.715348243713379,"y":-24.921451568603516,"facing":0.0,"progress":0.0,"target":-1,"hits":0,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":10,"kind":"tower","team":1,"lane":"mid","zone":"lane","slot":-1,"uid":"","def":"rot_mid_inner","alive":true,"hp":7500.0,"max_hp":7500.0,"shield":0.0,"x":17.012392044067383,"y":-11.427590370178223,"facing":0.0,"progress":0.0,"target":-1,"hits":0,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":11,"kind":"tower","team":1,"lane":"mid","zone":"lane","slot":-1,"uid":"","def":"rot_mid_outer","alive":true,"hp":6000.0,"max_hp":6000.0,"shield":0.0,"x":8.990991592407227,"y":-3.8433847427368164,"facing":0.0,"progress":0.0,"target":-1,"hits":0,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":12,"kind":"tower","team":1,"lane":"bot","zone":"lane","slot":-1,"uid":"","def":"rot_bot_inner","alive":true,"hp":7500.0,"max_hp":7500.0,"shield":0.0,"x":31.034507751464844,"y":-4.349228858947754,"facing":0.0,"progress":0.0,"target":-1,"hits":0,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":13,"kind":"tower","team":1,"lane":"bot","zone":"lane","slot":-1,"uid":"","def":"rot_bot_outer","alive":true,"hp":6000.0,"max_hp":6000.0,"shield":0.0,"x":28.989334106445313,"y":11.117134094238281,"facing":0.0,"progress":0.0,"target":-1,"hits":0,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":14,"kind":"tower","team":1,"lane":"base","zone":"lane","slot":-1,"uid":"","def":"rot_base_1","alive":true,"hp":9000.0,"max_hp":9000.0,"shield":0.0,"x":24.023000717163086,"y":-29.476999282836914,"facing":0.0,"progress":0.0,"target":-1,"hits":0,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":15,"kind":"tower","team":1,"lane":"base","zone":"lane","slot":-1,"uid":"","def":"rot_base_2","alive":true,"hp":9000.0,"max_hp":9000.0,"shield":0.0,"x":29.476999282836914,"y":-24.023000717163086,"facing":0.0,"progress":0.0,"target":-1,"hits":0,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":16,"kind":"core","team":1,"lane":"base","zone":"lane","slot":-1,"uid":"","def":"rot_ancient","alive":true,"hp":12000.0,"max_hp":12000.0,"shield":0.0,"x":30.0,"y":-30.0,"facing":0.0,"progress":0.0,"target":-1,"hits":0,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":17,"kind":"monster","team":0,"lane":"top","zone":"lane","slot":-1,"uid":"","def":"e01","alive":false,"hp":0.0,"max_hp":165.91500000000002,"shield":0.0,"x":-26.059507369995117,"y":-26.069705963134766,"facing":2.383142143281609,"progress":48.53701591529808,"target":-1,"hits":4,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":18,"kind":"monster","team":0,"lane":"top","zone":"lane","slot":-1,"uid":"","def":"e02","alive":false,"hp":0.0,"max_hp":442.44000000000005,"shield":0.0,"x":-24.832082748413086,"y":-23.177865982055664,"facing":1.3824686686038294,"progress":47.356000205270995,"target":-1,"hits":4,"reached":false,"dormant":false,"effects":[["root_grasp","movement_slow",0.3,2.6500000000000012],["root_grasp_attack","attack_slow",0.1,2.6500000000000012]],"dots":[]},{"id":19,"kind":"monster","team":0,"lane":"top","zone":"lane","slot":-1,"uid":"","def":"e01","alive":false,"hp":0.0,"max_hp":165.91500000000002,"shield":0.0,"x":-24.223581314086914,"y":-23.8474063873291,"facing":2.198791045872204,"progress":48.25344218601525,"target":-1,"hits":4,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":20,"kind":"monster","team":0,"lane":"top","zone":"lane","slot":-1,"uid":"","def":"e04","alive":false,"hp":0.0,"max_hp":239.65500000000003,"shield":0.0,"x":-29.099031448364258,"y":-21.481630325317383,"facing":0.31955917733465167,"progress":43.245321393013,"target":-1,"hits":12,"reached":false,"dormant":false,"effects":[],"dots":[["seed_burn",3.0,2.900000000000004,0.8999999999999996,1]]},{"id":21,"kind":"monster","team":0,"lane":"top","zone":"lane","slot":-1,"uid":"","def":"e03","alive":false,"hp":0.0,"max_hp":276.52500000000003,"shield":0.0,"x":-25.909164428710938,"y":-21.5747127532959,"facing":0.24233316665301483,"progress":45.43237070646658,"target":-1,"hits":9,"reached":false,"dormant":false,"effects":[["root_grasp","movement_slow",0.3,3.0],["root_grasp_attack","attack_slow",0.1,3.0]],"dots":[]},{"id":22,"kind":"monster","team":0,"lane":"mid","zone":"lane","slot":-1,"uid":"","def":"e01","alive":false,"hp":0.0,"max_hp":165.91500000000002,"shield":0.0,"x":-1.179997205734253,"y":-0.5992006063461304,"facing":2.3540202381311173,"progress":30.18117472277681,"target":-1,"hits":4,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":23,"kind":"monster","team":0,"lane":"mid","zone":"lane","slot":-1,"uid":"","def":"e02","alive":false,"hp":0.0,"max_hp":442.44000000000005,"shield":0.0,"x":-0.004938625264912844,"y":1.437745451927185,"facing":-1.2711463325241776,"progress":29.7147853970048,"target":-1,"hits":10,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":24,"kind":"monster","team":0,"lane":"mid","zone":"lane","slot":-1,"uid":"","def":"e01","alive":false,"hp":0.0,"max_hp":165.91500000000002,"shield":0.0,"x":1.0460548400878906,"y":1.1130739450454712,"facing":1.8704315024828433,"progress":30.51841011060836,"target":-1,"hits":5,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":25,"kind":"monster","team":0,"lane":"mid","zone":"lane","slot":-1,"uid":"","def":"e04","alive":false,"hp":0.0,"max_hp":239.65500000000003,"shield":0.0,"x":-4.47983980178833,"y":2.965071678161621,"facing":2.044415216236691,"progress":25.355184335589716,"target":-1,"hits":29,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":26,"kind":"monster","team":0,"lane":"mid","zone":"lane","slot":-1,"uid":"","def":"e03","alive":false,"hp":0.0,"max_hp":276.52500000000003,"shield":0.0,"x":-1.6166037321090698,"y":2.7004899978637695,"facing":-0.9261394050203304,"progress":27.514669084997617,"target":-1,"hits":15,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":27,"kind":"monster","team":0,"lane":"bot","zone":"lane","slot":-1,"uid":"","def":"e01","alive":false,"hp":0.0,"max_hp":165.91500000000002,"shield":0.0,"x":23.441667556762695,"y":23.792510986328125,"facing":2.619067651559464,"progress":48.335237329516715,"target":-1,"hits":3,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":28,"kind":"monster","team":0,"lane":"bot","zone":"lane","slot":-1,"uid":"","def":"e02","alive":false,"hp":0.0,"max_hp":442.44000000000005,"shield":0.0,"x":23.21225357055664,"y":24.609777450561523,"facing":2.174903031630074,"progress":47.5356308270613,"target":-1,"hits":6,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":29,"kind":"monster","team":0,"lane":"bot","zone":"lane","slot":-1,"uid":"","def":"e01","alive":false,"hp":0.0,"max_hp":165.91500000000002,"shield":0.0,"x":24.496599197387695,"y":24.091350555419922,"facing":1.3042555106869385,"progress":48.624358787208045,"target":-1,"hits":5,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":30,"kind":"monster","team":0,"lane":"bot","zone":"lane","slot":-1,"uid":"","def":"e04","alive":false,"hp":0.0,"max_hp":239.65500000000003,"shield":0.0,"x":18.631696701049805,"y":25.311710357666016,"facing":1.9262786390101263,"progress":40.44046707288637,"target":-1,"hits":18,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":31,"kind":"monster","team":0,"lane":"bot","zone":"lane","slot":-1,"uid":"","def":"e03","alive":false,"hp":0.0,"max_hp":276.52500000000003,"shield":0.0,"x":21.502681732177734,"y":25.7037296295166,"facing":-0.6579674384496856,"progress":42.98805457983437,"target":-1,"hits":12,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":32,"kind":"monster","team":1,"lane":"top","zone":"lane","slot":-1,"uid":"","def":"e01","alive":false,"hp":0.0,"max_hp":165.91500000000002,"shield":0.0,"x":-26.745759963989258,"y":-25.4490966796875,"facing":-0.6869799259513032,"progress":49.447499648516086,"target":-1,"hits":5,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":33,"kind":"monster","team":1,"lane":"top","zone":"lane","slot":-1,"uid":"","def":"e02","alive":false,"hp":0.0,"max_hp":442.44000000000005,"shield":0.0,"x":-24.760099411010742,"y":-14.785272598266602,"facing":1.1122995184525255,"progress":60.42921835962973,"target":-1,"hits":12,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":34,"kind":"monster","team":1,"lane":"top","zone":"lane","slot":-1,"uid":"","def":"e01","alive":false,"hp":0.0,"max_hp":165.91500000000002,"shield":0.0,"x":-25.157032012939453,"y":-23.927743911743164,"facing":-1.2568833251464888,"progress":49.225587331147764,"target":-1,"hits":5,"reached":false,"dormant":false,"effects":[],"dots":[["burn",4.0,2.6000000000000014,0.5999999999999996,0]]},{"id":35,"kind":"monster","team":1,"lane":"top","zone":"lane","slot":-1,"uid":"","def":"e04","alive":true,"hp":239.65500000000003,"max_hp":239.65500000000003,"shield":0.0,"x":-29.501821517944336,"y":-18.30329704284668,"facing":2.764343593947434,"progress":56.68793333383189,"target":2,"hits":19,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":36,"kind":"monster","team":1,"lane":"top","zone":"lane","slot":-1,"uid":"","def":"e03","alive":true,"hp":276.52500000000003,"max_hp":276.52500000000003,"shield":0.0,"x":-26.926532745361328,"y":-16.867103576660156,"facing":1.4383643259344212,"progress":57.99761220988322,"target":2,"hits":20,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":37,"kind":"monster","team":1,"lane":"mid","zone":"lane","slot":-1,"uid":"","def":"e01","alive":false,"hp":0.0,"max_hp":165.91500000000002,"shield":0.0,"x":-0.7701103091239929,"y":0.9953120350837708,"facing":-0.7763357939350762,"progress":31.829853062295456,"target":-1,"hits":5,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":38,"kind":"monster","team":1,"lane":"mid","zone":"lane","slot":-1,"uid":"","def":"e02","alive":false,"hp":0.0,"max_hp":442.44000000000005,"shield":0.0,"x":-0.5081915855407715,"y":2.241551399230957,"facing":0.878763927852327,"progress":32.55569083022652,"target":-1,"hits":14,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":39,"kind":"monster","team":1,"lane":"mid","zone":"lane","slot":-1,"uid":"","def":"e01","alive":false,"hp":0.0,"max_hp":165.91500000000002,"shield":0.0,"x":0.9041731357574463,"y":1.1859300136566162,"facing":-0.10726089938166493,"progress":30.793121712960744,"target":-1,"hits":5,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":40,"kind":"monster","team":1,"lane":"mid","zone":"lane","slot":-1,"uid":"","def":"e04","alive":true,"hp":108.32100000000003,"max_hp":239.65500000000003,"shield":0.0,"x":-1.2443114519119263,"y":-0.588111162185669,"facing":-0.7760456046186353,"progress":31.03194127342438,"target":-1,"hits":29,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":41,"kind":"monster","team":1,"lane":"mid","zone":"lane","slot":-1,"uid":"","def":"e03","alive":false,"hp":0.0,"max_hp":276.52500000000003,"shield":0.0,"x":-1.382906198501587,"y":1.3778090476989746,"facing":-1.0971761798174808,"progress":32.53172694322518,"target":-1,"hits":20,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":42,"kind":"monster","team":1,"lane":"bot","zone":"lane","slot":-1,"uid":"","def":"e01","alive":false,"hp":0.0,"max_hp":165.91500000000002,"shield":0.0,"x":24.22103500366211,"y":23.787601470947266,"facing":0.7514878634573791,"progress":48.20621941547872,"target":-1,"hits":4,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":43,"kind":"monster","team":1,"lane":"bot","zone":"lane","slot":-1,"uid":"","def":"e02","alive":true,"hp":405.8541,"max_hp":442.44000000000005,"shield":0.0,"x":-5.690584182739258,"y":27.72007942199707,"facing":-1.518218754339031,"progress":81.45819508075658,"target":-1,"hits":12,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":44,"kind":"monster","team":1,"lane":"bot","zone":"lane","slot":-1,"uid":"","def":"e01","alive":false,"hp":0.0,"max_hp":165.91500000000002,"shield":0.0,"x":24.112274169921875,"y":25.020774841308594,"facing":-0.062282579494790706,"progress":49.00703205591409,"target":-1,"hits":6,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":45,"kind":"monster","team":1,"lane":"bot","zone":"lane","slot":-1,"uid":"","def":"e04","alive":true,"hp":239.65500000000003,"max_hp":239.65500000000003,"shield":0.0,"x":-4.3238725662231445,"y":26.320171356201172,"facing":-1.4979844827114148,"progress":79.99302626229894,"target":-1,"hits":14,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":46,"kind":"monster","team":1,"lane":"bot","zone":"lane","slot":-1,"uid":"","def":"e03","alive":true,"hp":276.52500000000003,"max_hp":276.52500000000003,"shield":0.0,"x":-1.7524555921554565,"y":26.781667709350586,"facing":-1.1023618145276035,"progress":77.36436227783878,"target":-1,"hits":14,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":47,"kind":"troop","team":0,"lane":"top","zone":"lane","slot":0,"uid":"p0-1","def":"g03","alive":false,"hp":0.0,"max_hp":650.0,"shield":0.0,"x":-26.81538963317871,"y":-25.271501541137695,"facing":-0.7584505103081841,"progress":47.33387957070161,"target":-1,"hits":7,"reached":false,"dormant":false,"effects":[["root_grasp","movement_slow",0.2,1.4999999999999996]],"dots":[["seed_burn",10.0,3.450000000000002,0.9999999999999993,1]]},{"id":48,"kind":"troop","team":0,"lane":"top","zone":"lane","slot":0,"uid":"p0-2","def":"g01","alive":false,"hp":0.0,"max_hp":260.0,"shield":0.0,"x":-25.261646270751953,"y":-24.25381851196289,"facing":1.5508256133461642,"progress":47.72719335851287,"target":-1,"hits":3,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":49,"kind":"troop","team":0,"lane":"top","zone":"lane","slot":0,"uid":"p0-3","def":"g05","alive":false,"hp":0.0,"max_hp":240.0,"shield":0.0,"x":-27.567060470581055,"y":-19.78891944885254,"facing":2.5350333495730664,"progress":42.03114798667099,"target":-1,"hits":12,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":50,"kind":"troop","team":1,"lane":"top","zone":"lane","slot":3,"uid":"p3-2","def":"w05","alive":true,"hp":230.0,"max_hp":230.0,"shield":0.0,"x":-29.907289505004883,"y":-17.280763626098633,"facing":-0.37724905964235905,"progress":57.50541642501738,"target":2,"hits":17,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":51,"kind":"troop","team":1,"lane":"top","zone":"lane","slot":5,"uid":"p5-3","def":"w04","alive":true,"hp":1326.0,"max_hp":1560.0,"shield":0.0,"x":-26.696435928344727,"y":-14.736519813537598,"facing":-2.504679768563231,"progress":60.2913882187144,"target":2,"hits":16,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":52,"kind":"troop","team":1,"lane":"top","zone":"lane","slot":5,"uid":"p5-6","def":"w04","alive":true,"hp":1560.0,"max_hp":1560.0,"shield":0.0,"x":-25.74095916748047,"y":-15.281538009643555,"facing":-2.8382127357503126,"progress":60.05228995723562,"target":2,"hits":17,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":53,"kind":"troop","team":1,"lane":"top","zone":"lane","slot":5,"uid":"p5-4","def":"w02","alive":false,"hp":0.0,"max_hp":800.0,"shield":0.0,"x":-25.350683212280273,"y":-15.199334144592285,"facing":0.8194407342458122,"progress":59.9583040241968,"target":-1,"hits":11,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":54,"kind":"troop","team":1,"lane":"top","zone":"lane","slot":5,"uid":"p5-9","def":"w01","alive":false,"hp":0.0,"max_hp":290.0,"shield":0.0,"x":-26.88559913635254,"y":-13.65295124053955,"facing":-0.1776441220141853,"progress":61.43354142904282,"target":-1,"hits":13,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":55,"kind":"troop","team":1,"lane":"top","zone":"lane","slot":5,"uid":"p5-7","def":"w07","alive":true,"hp":370.0,"max_hp":370.0,"shield":0.0,"x":-28.016868591308594,"y":-17.012544631958008,"facing":-1.7032283276553721,"progress":57.82661933385667,"target":2,"hits":13,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":56,"kind":"troop","team":1,"lane":"top","zone":"lane","slot":5,"uid":"p5-5","def":"w06","alive":true,"hp":630.0,"max_hp":630.0,"shield":0.0,"x":-27.71896743774414,"y":-19.436382293701172,"facing":0.39441938622606953,"progress":55.1656059217059,"target":2,"hits":15,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":57,"kind":"troop","team":1,"lane":"top","zone":"lane","slot":5,"uid":"p5-8","def":"w09","alive":true,"hp":390.0,"max_hp":390.0,"shield":0.0,"x":-25.96113395690918,"y":-17.8919734954834,"facing":0.1982044049238104,"progress":56.732025430202576,"target":2,"hits":16,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":58,"kind":"troop","team":1,"lane":"mid","zone":"lane","slot":4,"uid":"p4-2","def":"g03","alive":false,"hp":0.0,"max_hp":650.0,"shield":0.0,"x":-1.3551254272460938,"y":1.5396349430084229,"facing":-2.26279684660987,"progress":32.62967448461082,"target":-1,"hits":12,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":59,"kind":"hero","team":1,"lane":"bot","zone":"lane","slot":5,"uid":"h5-1","def":"w04","alive":true,"hp":2128.5123999999996,"max_hp":2200.0,"shield":0.0,"x":-11.308335304260254,"y":25.279550552368164,"facing":-1.64118792943928,"progress":87.24194270729566,"target":-1,"hits":15,"reached":false,"dormant":false,"effects":[],"dots":[]}]},{"label":"settled","phase":0,"round":9,"winner":-2,"end_note":"","players":[{"gold":195,"draft_gold":195,"ready":true,"earned":155,"spent":180,"next_seq":4,"roster":["p0-1|g03|top|70","p0-2|g01|top|45","p0-3|g05|top|65"],"hero":"","bookings":[],"new_bookings":[],"draft_roster":["p0-1|g03|top|70|false","p0-2|g01|top|45|false","p0-3|g05|top|65|false"],"draft_hero":"","boss_lane":"","undo":0},{"gold":225,"draft_gold":225,"ready":true,"earned":155,"spent":150,"next_seq":2,"roster":[],"hero":"","bookings":["c1-1|ch_schutz|mid|150|9"],"new_bookings":[],"draft_roster":[],"draft_hero":"","boss_lane":"","undo":0},{"gold":195,"draft_gold":195,"ready":true,"earned":155,"spent":180,"next_seq":2,"roster":[],"hero":"","bookings":["c2-1|ch_belagerung|bot|180|9"],"new_bookings":[],"draft_roster":[],"draft_hero":"","boss_lane":"","undo":0},{"gold":285,"draft_gold":285,"ready":true,"earned":275,"spent":210,"next_seq":3,"roster":["p3-2|w05|top|60"],"hero":"","bookings":["c3-1|ch_druck|top|150|9"],"new_bookings":[],"draft_roster":["p3-2|w05|top|60|false"],"draft_hero":"","boss_lane":"","undo":0},{"gold":275,"draft_gold":275,"ready":true,"earned":275,"spent":220,"next_seq":3,"roster":["p4-2|g03|mid|70"],"hero":"","bookings":["c4-1|ch_schutz|mid|150|9"],"new_bookings":[],"draft_roster":["p4-2|g03|mid|70|false"],"draft_hero":"","boss_lane":"","undo":0},{"gold":330,"draft_gold":330,"ready":true,"earned":275,"spent":165,"next_seq":10,"roster":["p5-3|w04|top|230","p5-4|w02|top|150","p5-5|w06|top|195","p5-6|w04|top|230","p5-7|w07|top|100","p5-8|w09|top|90","p5-9|w01|top|50"],"hero":"h5-1|held_ringborke|188|bot|glutklinge||260|false|","bookings":["c5-2|ch_belagerung|bot|180|9"],"new_bookings":[],"draft_roster":["p5-3|w04|top|230|false","p5-4|w02|top|150|false","p5-5|w06|top|195|false","p5-6|w04|top|230|false","p5-7|w07|top|100|false","p5-8|w09|top|90|false","p5-9|w01|top|50|false"],"draft_hero":"h5-1|held_ringborke|188|bot|glutklinge||260|false|","boss_lane":"","undo":0}],"buildings":[0.0,0.0,7500.0,5975.6094,0.0,0.0,6585.413900000004,7804.285349999991,12000.0,7500.0,6000.0,7500.0,6000.0,7500.0,6000.0,9000.0,9000.0,12000.0],"boss":{"next":1,"settled":8,"claim":""},"boss_log":[],"announcements":["champion|0|1|mid|ch_schutz|0","champion|0|2|bot|ch_belagerung|0","champion|1|3|top|ch_druck|0","champion|1|4|mid|ch_schutz|0","champion|1|5|bot|ch_belagerung|0"],"settlement":{"round":8,"gains":[57,57,57,177,177,177],"income":98,"lost":["blau_top_outer","blau_top_inner"],"end_reason":"cleared","combat_time":112.94999999999573,"boss":"none","lane_kills":{"mid":10,"bot":10,"top":10},"xp":{"h5-1":188}},"combat":{"round":8,"steps":2259,"elapsed":112.94999999999573,"finished":true,"end_reason":"cleared","destroyed":[],"grotto":"none|-1|-1|true","grotto_boss":"","grotto_boss_hp":0.0,"events":45,"mobile":[0,0,0]},"events":[[1,178,8.899999999999991,0,"mid","lane","monster",22,"e01",8,"",20,[]],[2,185,9.249999999999996,0,"mid","lane","monster",24,"e01",8,"",20,[]],[3,193,9.650000000000002,1,"mid","lane","monster",39,"e01",8,"",20,[]],[4,214,10.700000000000017,1,"mid","lane","monster",37,"e01",8,"",20,[]],[5,218,10.90000000000002,0,"bot","lane","monster",27,"e01",8,"",20,["h5-1"]],[6,243,12.150000000000038,0,"top","lane","monster",19,"e01",8,"",20,[]],[7,248,12.400000000000041,0,"top","lane","monster",17,"e01",8,"",20,[]],[8,259,12.950000000000049,1,"bot","lane","monster",42,"e01",8,"",20,[]],[9,260,13.00000000000005,0,"bot","lane","monster",29,"e01",8,"",20,["h5-1"]],[10,274,13.70000000000006,1,"top","lane","monster",32,"e01",8,"",20,[]],[11,277,13.850000000000062,1,"top","lane","monster",34,"e01",8,"",20,[]],[12,286,14.300000000000068,0,"top","lane","troop",48,"g01",0,"",15,[]],[13,300,15.000000000000078,1,"bot","lane","monster",44,"e01",8,"",20,[]],[14,329,16.4500000000001,0,"mid","lane","monster",23,"e02",15,"",20,[]],[15,333,16.6500000000001,0,"top","lane","monster",18,"e02",15,"",20,[]],[16,350,17.500000000000114,0,"bot","lane","monster",28,"e02",15,"",20,["h5-1"]],[17,367,18.350000000000126,0,"top","lane","troop",47,"g03",0,"",15,[]],[18,396,19.800000000000146,1,"mid","lane","troop",58,"g03",0,"",15,[]],[19,402,20.10000000000015,0,"top","lane","monster",21,"e03",13,"",20,[]],[20,442,22.10000000000018,0,"bot","lane","monster",31,"e03",13,"",20,["h5-1"]],[21,452,22.600000000000186,0,"top","lane","monster",20,"e04",13,"",20,[]],[22,456,22.80000000000019,1,"mid","lane","monster",38,"e02",15,"",20,[]],[23,460,23.000000000000192,0,"mid","lane","monster",26,"e03",13,"",20,[]],[24,474,23.700000000000202,0,"top","lane","troop",49,"g05",0,"",15,[]],[25,506,25.300000000000225,1,"top","lane","troop",53,"w02",0,"",15,[]],[26,532,26.600000000000243,0,"bot","lane","monster",30,"e04",13,"",20,["h5-1"]],[27,552,27.600000000000257,1,"mid","lane","monster",41,"e03",13,"",20,[]],[28,606,30.300000000000296,1,"top","lane","monster",33,"e02",15,"",20,[]],[29,626,31.30000000000031,1,"top","lane","troop",54,"w01",0,"",15,[]],[30,691,34.550000000000175,0,"mid","lane","monster",25,"e04",13,"",20,[]],[31,752,37.6,1,"mid","lane","monster",40,"e04",13,"",20,[]],[32,926,46.29999999999951,1,"bot","lane","hero",59,"w04",0,"",15,[]],[33,975,48.74999999999937,0,"top","lane","tower",2,"blau_top_outer",150,"blau_top_outer",60,[]],[34,986,49.299999999999336,1,"bot","lane","monster",43,"e02",15,"",20,[]],[35,1066,53.29999999999911,1,"bot","lane","monster",46,"e03",13,"",20,[]],[36,1106,55.299999999998995,1,"bot","lane","monster",45,"e04",13,"",20,[]],[37,1423,71.1499999999981,1,"top","lane","troop",52,"w04",0,"",15,[]],[38,1623,81.14999999999753,1,"top","lane","troop",51,"w04",0,"",15,[]],[39,1720,85.99999999999726,0,"top","lane","tower",1,"blau_top_inner",210,"blau_top_inner",60,[]],[40,1859,92.94999999999686,1,"top","lane","monster",35,"e04",13,"",20,[]],[41,1919,95.94999999999669,1,"top","lane","monster",36,"e03",13,"",20,[]],[42,1999,99.94999999999646,1,"top","lane","troop",57,"w09",0,"",15,[]],[43,2099,104.94999999999618,1,"top","lane","troop",55,"w07",0,"",15,[]],[44,2139,106.94999999999607,1,"top","lane","troop",50,"w05",0,"",15,[]],[45,2259,112.94999999999573,1,"top","lane","troop",56,"w06",0,"",15,[]]]}],"results":[["begin",-1,"",true,""]]},"base_tower_attack":{"title":"Angriff auf Basistürme durch eine starke Rot-Armee","snapshots":[{"label":"t60","phase":1,"round":12,"winner":-2,"end_note":"","players":[{"gold":70,"draft_gold":70,"ready":true,"earned":0,"spent":150,"next_seq":2,"roster":[],"hero":"","bookings":["c0-1|ch_schutz|top|150|13"],"new_bookings":["c0-1|ch_schutz|top|150"],"draft_roster":[],"draft_hero":"","boss_lane":"","undo":0},{"gold":40,"draft_gold":40,"ready":true,"earned":0,"spent":180,"next_seq":2,"roster":[],"hero":"","bookings":["c1-1|ch_belagerung|mid|180|13"],"new_bookings":["c1-1|ch_belagerung|mid|180"],"draft_roster":[],"draft_hero":"","boss_lane":"","undo":0},{"gold":10,"draft_gold":10,"ready":true,"earned":0,"spent":210,"next_seq":3,"roster":["p2-2|w05|bot|60"],"hero":"","bookings":["c2-1|ch_druck|bot|150|13"],"new_bookings":["c2-1|ch_druck|bot|150"],"draft_roster":["p2-2|w05|bot|60|true"],"draft_hero":"","boss_lane":"","undo":0},{"gold":3030,"draft_gold":3030,"ready":true,"earned":0,"spent":0,"next_seq":15,"roster":["p3-3|g04|top|220","p3-4|g06|top|205","p3-5|g02|top|135","p3-6|g10|top|255","p3-7|g04|top|220","p3-8|g08|top|285","p3-9|g06|top|205","p3-10|g02|top|135","p3-11|g04|top|220","p3-12|g06|top|205","p3-13|g10|top|255","p3-14|g04|top|220"],"hero":"h3-1|held_quellgeflecht|0|top|quellamulett||260|false|","bookings":["c3-2|ch_schutz|top|150|13"],"new_bookings":["c3-2|ch_schutz|top|150"],"draft_roster":["p3-3|g04|top|220|true","p3-4|g06|top|205|true","p3-5|g02|top|135|true","p3-6|g10|top|255|true","p3-7|g04|top|220|true","p3-8|g08|top|285|true","p3-9|g06|top|205|true","p3-10|g02|top|135|true","p3-11|g04|top|220|true","p3-12|g06|top|205|true","p3-13|g10|top|255|true","p3-14|g04|top|220|true"],"draft_hero":"h3-1|held_quellgeflecht|0|top|quellamulett||260|true|quellamulett","boss_lane":"","undo":0},{"gold":3080,"draft_gold":3080,"ready":true,"earned":0,"spent":0,"next_seq":15,"roster":["p4-3|w04|mid|230","p4-4|w02|mid|150","p4-5|w06|mid|195","p4-6|w04|mid|230","p4-7|w08|mid|295","p4-8|w10|mid|270","p4-9|w02|mid|150","p4-10|w04|mid|230","p4-11|w06|mid|195","p4-12|w04|mid|230","p4-13|w02|mid|150","p4-14|w06|mid|195"],"hero":"h4-1|held_ringborke|0|mid|glutklinge||260|false|","bookings":["c4-2|ch_belagerung|mid|180|13"],"new_bookings":["c4-2|ch_belagerung|mid|180"],"draft_roster":["p4-3|w04|mid|230|true","p4-4|w02|mid|150|true","p4-5|w06|mid|195|true","p4-6|w04|mid|230|true","p4-7|w08|mid|295|true","p4-8|w10|mid|270|true","p4-9|w02|mid|150|true","p4-10|w04|mid|230|true","p4-11|w06|mid|195|true","p4-12|w04|mid|230|true","p4-13|w02|mid|150|true","p4-14|w06|mid|195|true"],"draft_hero":"h4-1|held_ringborke|0|mid|glutklinge||260|true|glutklinge","boss_lane":"","undo":0},{"gold":3340,"draft_gold":3340,"ready":true,"earned":0,"spent":0,"next_seq":14,"roster":["p5-2|g04|bot|220","p5-3|g02|bot|135","p5-4|g06|bot|205","p5-5|g08|bot|285","p5-6|g04|bot|220","p5-7|g10|bot|255","p5-8|g02|bot|135","p5-9|g06|bot|205","p5-10|g04|bot|220","p5-11|g02|bot|135","p5-12|g06|bot|205","p5-13|g04|bot|220"],"hero":"h5-1|held_ringborke|0|bot|basaltschild||260|false|","bookings":[],"new_bookings":[],"draft_roster":["p5-2|g04|bot|220|true","p5-3|g02|bot|135|true","p5-4|g06|bot|205|true","p5-5|g08|bot|285|true","p5-6|g04|bot|220|true","p5-7|g10|bot|255|true","p5-8|g02|bot|135|true","p5-9|g06|bot|205|true","p5-10|g04|bot|220|true","p5-11|g02|bot|135|true","p5-12|g06|bot|205|true","p5-13|g04|bot|220|true"],"draft_hero":"h5-1|held_ringborke|0|bot|basaltschild||260|true|basaltschild","boss_lane":"","undo":0}],"buildings":[7500.0,6000.0,0.0,0.0,7500.0,6000.0,9000.0,9000.0,12000.0,7500.0,6000.0,7500.0,6000.0,7500.0,6000.0,9000.0,9000.0,12000.0],"boss":{"next":1,"settled":0,"claim":""},"boss_log":[],"announcements":[],"settlement":null,"combat":{"round":12,"steps":1200,"elapsed":59.99999999999873,"finished":false,"end_reason":"","destroyed":[],"grotto":"none|-1|-1|true","grotto_boss":"","grotto_boss_hp":0.0,"events":39,"mobile":[0,43,0]},"units":[{"id":1,"kind":"tower","team":0,"lane":"top","zone":"lane","slot":-1,"uid":"","def":"blau_top_inner","alive":false,"hp":0.0,"max_hp":7500.0,"shield":0.0,"x":-24.931251525878906,"y":4.5293378829956055,"facing":0.0,"progress":0.0,"target":-1,"hits":13,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":2,"kind":"tower","team":0,"lane":"top","zone":"lane","slot":-1,"uid":"","def":"blau_top_outer","alive":false,"hp":0.0,"max_hp":6000.0,"shield":0.0,"x":-24.921451568603516,"y":-12.715348243713379,"facing":0.0,"progress":0.0,"target":-1,"hits":11,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":3,"kind":"tower","team":0,"lane":"bot","zone":"lane","slot":-1,"uid":"","def":"blau_bot_inner","alive":false,"hp":0.0,"max_hp":7500.0,"shield":0.0,"x":-4.349228858947754,"y":31.034507751464844,"facing":0.0,"progress":0.0,"target":-1,"hits":14,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":4,"kind":"tower","team":0,"lane":"bot","zone":"lane","slot":-1,"uid":"","def":"blau_bot_outer","alive":false,"hp":0.0,"max_hp":6000.0,"shield":0.0,"x":11.117134094238281,"y":28.989334106445313,"facing":0.0,"progress":0.0,"target":-1,"hits":12,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":5,"kind":"tower","team":0,"lane":"base","zone":"lane","slot":-1,"uid":"","def":"blau_base_1","alive":false,"hp":0.0,"max_hp":9000.0,"shield":0.0,"x":-29.476999282836914,"y":24.023000717163086,"facing":0.0,"progress":0.0,"target":-1,"hits":29,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":6,"kind":"tower","team":0,"lane":"base","zone":"lane","slot":-1,"uid":"","def":"blau_base_2","alive":false,"hp":0.0,"max_hp":9000.0,"shield":0.0,"x":-24.023000717163086,"y":29.476999282836914,"facing":0.0,"progress":0.0,"target":-1,"hits":29,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":7,"kind":"core","team":0,"lane":"base","zone":"lane","slot":-1,"uid":"","def":"blau_ancient","alive":true,"hp":3412.749247500012,"max_hp":12000.0,"shield":0.0,"x":-30.0,"y":30.0,"facing":0.0,"progress":0.0,"target":-1,"hits":0,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":8,"kind":"tower","team":1,"lane":"top","zone":"lane","slot":-1,"uid":"","def":"rot_top_inner","alive":true,"hp":7500.0,"max_hp":7500.0,"shield":0.0,"x":4.5293378829956055,"y":-24.931251525878906,"facing":0.0,"progress":0.0,"target":-1,"hits":0,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":9,"kind":"tower","team":1,"lane":"top","zone":"lane","slot":-1,"uid":"","def":"rot_top_outer","alive":true,"hp":6000.0,"max_hp":6000.0,"shield":0.0,"x":-12.715348243713379,"y":-24.921451568603516,"facing":0.0,"progress":0.0,"target":-1,"hits":0,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":10,"kind":"tower","team":1,"lane":"mid","zone":"lane","slot":-1,"uid":"","def":"rot_mid_inner","alive":true,"hp":7500.0,"max_hp":7500.0,"shield":0.0,"x":17.012392044067383,"y":-11.427590370178223,"facing":0.0,"progress":0.0,"target":-1,"hits":0,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":11,"kind":"tower","team":1,"lane":"mid","zone":"lane","slot":-1,"uid":"","def":"rot_mid_outer","alive":true,"hp":6000.0,"max_hp":6000.0,"shield":0.0,"x":8.990991592407227,"y":-3.8433847427368164,"facing":0.0,"progress":0.0,"target":-1,"hits":0,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":12,"kind":"tower","team":1,"lane":"bot","zone":"lane","slot":-1,"uid":"","def":"rot_bot_inner","alive":true,"hp":7500.0,"max_hp":7500.0,"shield":0.0,"x":31.034507751464844,"y":-4.349228858947754,"facing":0.0,"progress":0.0,"target":-1,"hits":0,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":13,"kind":"tower","team":1,"lane":"bot","zone":"lane","slot":-1,"uid":"","def":"rot_bot_outer","alive":true,"hp":6000.0,"max_hp":6000.0,"shield":0.0,"x":28.989334106445313,"y":11.117134094238281,"facing":0.0,"progress":0.0,"target":-1,"hits":0,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":14,"kind":"tower","team":1,"lane":"base","zone":"lane","slot":-1,"uid":"","def":"rot_base_1","alive":true,"hp":9000.0,"max_hp":9000.0,"shield":0.0,"x":24.023000717163086,"y":-29.476999282836914,"facing":0.0,"progress":0.0,"target":-1,"hits":0,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":15,"kind":"tower","team":1,"lane":"base","zone":"lane","slot":-1,"uid":"","def":"rot_base_2","alive":true,"hp":9000.0,"max_hp":9000.0,"shield":0.0,"x":29.476999282836914,"y":-24.023000717163086,"facing":0.0,"progress":0.0,"target":-1,"hits":0,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":16,"kind":"core","team":1,"lane":"base","zone":"lane","slot":-1,"uid":"","def":"rot_ancient","alive":true,"hp":12000.0,"max_hp":12000.0,"shield":0.0,"x":30.0,"y":-30.0,"facing":0.0,"progress":0.0,"target":-1,"hits":0,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":17,"kind":"monster","team":0,"lane":"top","zone":"lane","slot":-1,"uid":"","def":"e01","alive":false,"hp":0.0,"max_hp":215.23499999999999,"shield":0.0,"x":-26.304168701171875,"y":-25.820642471313477,"facing":2.612455198219413,"progress":47.95042410789136,"target":-1,"hits":4,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":18,"kind":"monster","team":0,"lane":"top","zone":"lane","slot":-1,"uid":"","def":"e02","alive":false,"hp":0.0,"max_hp":573.9599999999999,"shield":0.0,"x":-26.842317581176758,"y":-24.90056610107422,"facing":-0.5291374553703804,"progress":46.989285013441986,"target":-1,"hits":2,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":19,"kind":"monster","team":0,"lane":"top","zone":"lane","slot":-1,"uid":"","def":"e05","alive":false,"hp":0.0,"max_hp":1147.9199999999998,"shield":0.0,"x":-25.98493194580078,"y":-22.66061019897461,"facing":2.916731184047972,"progress":46.10098289237506,"target":-1,"hits":3,"reached":false,"dormant":false,"effects":[],"dots":[["burn",12.0,1.9000000000000035,0.8999999999999996,0]]},{"id":20,"kind":"monster","team":0,"lane":"top","zone":"lane","slot":-1,"uid":"","def":"e04","alive":false,"hp":0.0,"max_hp":310.895,"shield":0.0,"x":-29.37579917907715,"y":-21.55205535888672,"facing":2.496573173658464,"progress":43.245321393013,"target":-1,"hits":10,"reached":false,"dormant":false,"effects":[],"dots":[["burn",12.0,2.6000000000000014,0.5999999999999996,0]]},{"id":21,"kind":"monster","team":0,"lane":"top","zone":"lane","slot":-1,"uid":"","def":"e03","alive":false,"hp":0.0,"max_hp":358.72499999999997,"shield":0.0,"x":-26.816944122314453,"y":-23.43813705444336,"facing":2.9329534616555413,"progress":46.01459400070632,"target":-1,"hits":4,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":22,"kind":"monster","team":0,"lane":"top","zone":"lane","slot":-1,"uid":"","def":"e06","alive":false,"hp":0.0,"max_hp":454.38499999999993,"shield":0.0,"x":-27.045089721679688,"y":-22.362102508544922,"facing":-0.3233890018655059,"progress":45.23854773554706,"target":-1,"hits":7,"reached":false,"dormant":false,"effects":[],"dots":[["burn",12.0,2.8500000000000005,0.8499999999999999,0]]},{"id":23,"kind":"monster","team":0,"lane":"mid","zone":"lane","slot":-1,"uid":"","def":"e01","alive":false,"hp":0.0,"max_hp":215.23499999999999,"shield":0.0,"x":-1.0886784791946411,"y":-0.9374778866767883,"facing":2.908659270435372,"progress":30.486564864015325,"target":-1,"hits":3,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":24,"kind":"monster","team":0,"lane":"mid","zone":"lane","slot":-1,"uid":"","def":"e02","alive":false,"hp":0.0,"max_hp":573.9599999999999,"shield":0.0,"x":-1.2310298681259155,"y":-0.05175668001174927,"facing":2.4591393372279327,"progress":29.754723521536825,"target":-1,"hits":2,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":25,"kind":"monster","team":0,"lane":"mid","zone":"lane","slot":-1,"uid":"","def":"e05","alive":false,"hp":0.0,"max_hp":1147.9199999999998,"shield":0.0,"x":-1.9142742156982422,"y":0.7920008897781372,"facing":-0.08412322520871802,"progress":28.802971742319457,"target":-1,"hits":3,"reached":false,"dormant":false,"effects":[["root_grasp","movement_slow",0.3,2.8500000000000005],["root_grasp_attack","attack_slow",0.1,2.8500000000000005]],"dots":[]},{"id":26,"kind":"monster","team":0,"lane":"mid","zone":"lane","slot":-1,"uid":"","def":"e04","alive":false,"hp":0.0,"max_hp":310.895,"shield":0.0,"x":-4.761737823486328,"y":3.1138880252838135,"facing":2.370484785479765,"progress":25.05404969119482,"target":-1,"hits":10,"reached":false,"dormant":false,"effects":[["root_grasp","movement_slow",0.3,2.750000000000001],["root_grasp_attack","attack_slow",0.1,2.750000000000001]],"dots":[]},{"id":27,"kind":"monster","team":0,"lane":"mid","zone":"lane","slot":-1,"uid":"","def":"e03","alive":false,"hp":0.0,"max_hp":358.72499999999997,"shield":0.0,"x":-2.8622844219207764,"y":1.3499213457107544,"facing":-1.0384847569599231,"progress":27.74179550983677,"target":-1,"hits":6,"reached":false,"dormant":false,"effects":[["root_grasp","movement_slow",0.3,2.95],["root_grasp_attack","attack_slow",0.1,2.95]],"dots":[]},{"id":28,"kind":"monster","team":0,"lane":"mid","zone":"lane","slot":-1,"uid":"","def":"e06","alive":false,"hp":0.0,"max_hp":454.38499999999993,"shield":0.0,"x":-1.4484220743179321,"y":2.5026755332946777,"facing":0.6406987041390185,"progress":27.770341804889803,"target":-1,"hits":6,"reached":false,"dormant":false,"effects":[],"dots":[["seed_burn",10.0,4.0,0.6999999999999994,1]]},{"id":29,"kind":"monster","team":0,"lane":"bot","zone":"lane","slot":-1,"uid":"","def":"e01","alive":false,"hp":0.0,"max_hp":215.23499999999999,"shield":0.0,"x":23.637039184570313,"y":24.307321548461914,"facing":2.1439958092350895,"progress":48.04230826573466,"target":-1,"hits":4,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":30,"kind":"monster","team":0,"lane":"bot","zone":"lane","slot":-1,"uid":"","def":"e02","alive":false,"hp":0.0,"max_hp":573.9599999999999,"shield":0.0,"x":22.719209671020508,"y":24.900657653808594,"facing":-0.9975968443547039,"progress":47.110543179557254,"target":-1,"hits":2,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":31,"kind":"monster","team":0,"lane":"bot","zone":"lane","slot":-1,"uid":"","def":"e05","alive":false,"hp":0.0,"max_hp":1147.9199999999998,"shield":0.0,"x":20.434743881225586,"y":24.927480697631836,"facing":-2.498285128378203,"progress":41.91880421571122,"target":-1,"hits":4,"reached":false,"dormant":false,"effects":[],"dots":[["burn",12.0,2.95,0.9499999999999993,0]]},{"id":32,"kind":"monster","team":0,"lane":"bot","zone":"lane","slot":-1,"uid":"","def":"e04","alive":false,"hp":0.0,"max_hp":310.895,"shield":0.0,"x":18.35611343383789,"y":25.4041748046875,"facing":0.2866772238634168,"progress":40.18641846625217,"target":-1,"hits":11,"reached":false,"dormant":false,"effects":[],"dots":[["burn",12.0,2.6000000000000014,0.5999999999999996,0]]},{"id":33,"kind":"monster","team":0,"lane":"bot","zone":"lane","slot":-1,"uid":"","def":"e03","alive":false,"hp":0.0,"max_hp":358.72499999999997,"shield":0.0,"x":21.506908416748047,"y":24.631826400756836,"facing":1.875599351385134,"progress":45.95063607736404,"target":-1,"hits":4,"reached":false,"dormant":false,"effects":[],"dots":[["burn",12.0,2.9000000000000004,0.8999999999999999,0]]},{"id":34,"kind":"monster","team":0,"lane":"bot","zone":"lane","slot":-1,"uid":"","def":"e06","alive":false,"hp":0.0,"max_hp":454.38499999999993,"shield":0.0,"x":20.838037490844727,"y":26.789047241210938,"facing":2.2512512465821692,"progress":42.76718132076546,"target":-1,"hits":8,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":35,"kind":"monster","team":1,"lane":"top","zone":"lane","slot":-1,"uid":"","def":"e01","alive":false,"hp":0.0,"max_hp":215.23499999999999,"shield":0.0,"x":-27.775493621826172,"y":-22.6494083404541,"facing":-0.3691118342091332,"progress":52.00592422795163,"target":-1,"hits":6,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":36,"kind":"monster","team":1,"lane":"top","zone":"lane","slot":-1,"uid":"","def":"e02","alive":true,"hp":573.9599999999999,"max_hp":573.9599999999999,"shield":0.0,"x":-30.14463233947754,"y":28.122257232666016,"facing":-0.05691106420799326,"progress":96.82083296775818,"target":7,"hits":25,"reached":true,"dormant":false,"effects":[],"dots":[]},{"id":37,"kind":"monster","team":1,"lane":"top","zone":"lane","slot":-1,"uid":"","def":"e05","alive":true,"hp":1147.9199999999998,"max_hp":1147.9199999999998,"shield":0.0,"x":-29.410964965820313,"y":27.363433837890625,"facing":-1.6679541019685267,"progress":96.82083296775818,"target":7,"hits":18,"reached":true,"dormant":false,"effects":[],"dots":[]},{"id":38,"kind":"monster","team":1,"lane":"top","zone":"lane","slot":-1,"uid":"","def":"e04","alive":true,"hp":310.895,"max_hp":310.895,"shield":0.0,"x":-28.94053077697754,"y":23.23711585998535,"facing":0.32773850678055544,"progress":96.82083296775818,"target":7,"hits":36,"reached":true,"dormant":false,"effects":[],"dots":[]},{"id":39,"kind":"monster","team":1,"lane":"top","zone":"lane","slot":-1,"uid":"","def":"e03","alive":true,"hp":358.72499999999997,"max_hp":358.72499999999997,"shield":0.0,"x":-29.319904327392578,"y":25.77908706665039,"facing":-2.4686371686890882,"progress":96.82083296775818,"target":7,"hits":30,"reached":true,"dormant":false,"effects":[["hearth_warmth","damage",0.15,4.0]],"dots":[]},{"id":40,"kind":"monster","team":1,"lane":"top","zone":"lane","slot":-1,"uid":"","def":"e06","alive":true,"hp":454.38499999999993,"max_hp":454.38499999999993,"shield":0.0,"x":-28.39301300048828,"y":25.175783157348633,"facing":0.7530072613765263,"progress":96.82083296775818,"target":7,"hits":26,"reached":true,"dormant":false,"effects":[["hearth_warmth","damage",0.15,4.0]],"dots":[]},{"id":41,"kind":"monster","team":1,"lane":"mid","zone":"lane","slot":-1,"uid":"","def":"e01","alive":false,"hp":0.0,"max_hp":215.23499999999999,"shield":0.0,"x":-2.213693141937256,"y":-0.20595164597034454,"facing":0.4821813966192478,"progress":31.98370058792963,"target":-1,"hits":4,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":42,"kind":"monster","team":1,"lane":"mid","zone":"lane","slot":-1,"uid":"","def":"e02","alive":false,"hp":0.0,"max_hp":573.9599999999999,"shield":0.0,"x":-24.02959632873535,"y":27.49149513244629,"facing":-0.5541722148170951,"progress":61.16015148162842,"target":-1,"hits":20,"reached":true,"dormant":false,"effects":[],"dots":[]},{"id":43,"kind":"monster","team":1,"lane":"mid","zone":"lane","slot":-1,"uid":"","def":"e05","alive":true,"hp":1147.9199999999998,"max_hp":1147.9199999999998,"shield":0.0,"x":-28.703964233398438,"y":30.7584285736084,"facing":-0.35827710563469484,"progress":61.16015148162842,"target":7,"hits":32,"reached":true,"dormant":false,"effects":[],"dots":[]},{"id":44,"kind":"monster","team":1,"lane":"mid","zone":"lane","slot":-1,"uid":"","def":"e04","alive":true,"hp":310.895,"max_hp":310.895,"shield":0.0,"x":-26.167423248291016,"y":24.088584899902344,"facing":-1.4450689634848215,"progress":61.16015148162842,"target":7,"hits":42,"reached":true,"dormant":false,"effects":[],"dots":[]},{"id":45,"kind":"monster","team":1,"lane":"mid","zone":"lane","slot":-1,"uid":"","def":"e03","alive":true,"hp":358.72499999999997,"max_hp":358.72499999999997,"shield":0.0,"x":-26.79988670349121,"y":27.032381057739258,"facing":0.921074458432819,"progress":61.16015148162842,"target":7,"hits":42,"reached":true,"dormant":false,"effects":[],"dots":[]},{"id":46,"kind":"monster","team":1,"lane":"mid","zone":"lane","slot":-1,"uid":"","def":"e06","alive":true,"hp":454.38499999999993,"max_hp":454.38499999999993,"shield":0.0,"x":-25.701457977294922,"y":27.063552856445313,"facing":1.6769379793172141,"progress":61.16015148162842,"target":7,"hits":39,"reached":true,"dormant":false,"effects":[["hearth_warmth","damage",0.15,4.0]],"dots":[]},{"id":47,"kind":"monster","team":1,"lane":"bot","zone":"lane","slot":-1,"uid":"","def":"e01","alive":false,"hp":0.0,"max_hp":215.23499999999999,"shield":0.0,"x":22.16941261291504,"y":25.349939346313477,"facing":-1.0045779307582583,"progress":50.82654462805949,"target":-1,"hits":5,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":48,"kind":"monster","team":1,"lane":"bot","zone":"lane","slot":-1,"uid":"","def":"e02","alive":true,"hp":573.9599999999999,"max_hp":573.9599999999999,"shield":0.0,"x":-28.108123779296875,"y":30.015352249145508,"facing":-1.5164532647838915,"progress":96.8208339214325,"target":7,"hits":27,"reached":true,"dormant":false,"effects":[],"dots":[]},{"id":49,"kind":"monster","team":1,"lane":"bot","zone":"lane","slot":-1,"uid":"","def":"e05","alive":true,"hp":1147.9199999999998,"max_hp":1147.9199999999998,"shield":0.0,"x":-27.290422439575195,"y":29.847009658813477,"facing":-0.006753315219699657,"progress":96.8208339214325,"target":7,"hits":19,"reached":true,"dormant":false,"effects":[],"dots":[]},{"id":50,"kind":"monster","team":1,"lane":"bot","zone":"lane","slot":-1,"uid":"","def":"e04","alive":true,"hp":310.895,"max_hp":310.895,"shield":0.0,"x":-23.565427780151367,"y":27.914684295654297,"facing":-0.8586978463989855,"progress":96.8208339214325,"target":7,"hits":32,"reached":true,"dormant":false,"effects":[],"dots":[]},{"id":51,"kind":"monster","team":1,"lane":"bot","zone":"lane","slot":-1,"uid":"","def":"e03","alive":true,"hp":358.72499999999997,"max_hp":358.72499999999997,"shield":0.0,"x":-26.11033058166504,"y":28.424293518066406,"facing":-1.1565636125870662,"progress":96.8208339214325,"target":7,"hits":31,"reached":true,"dormant":false,"effects":[["hearth_warmth","damage",0.15,4.0]],"dots":[]},{"id":52,"kind":"monster","team":1,"lane":"bot","zone":"lane","slot":-1,"uid":"","def":"e06","alive":true,"hp":454.38499999999993,"max_hp":454.38499999999993,"shield":0.0,"x":-25.244800567626953,"y":29.76553726196289,"facing":1.0954627482212007,"progress":96.8208339214325,"target":7,"hits":26,"reached":true,"dormant":false,"effects":[],"dots":[]},{"id":53,"kind":"troop","team":0,"lane":"bot","zone":"lane","slot":2,"uid":"p2-2","def":"w05","alive":false,"hp":0.0,"max_hp":230.0,"shield":0.0,"x":18.044818878173828,"y":24.349151611328125,"facing":-2.8549154297263764,"progress":39.760321919751995,"target":-1,"hits":9,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":54,"kind":"troop","team":1,"lane":"top","zone":"lane","slot":3,"uid":"p3-3","def":"g04","alive":true,"hp":1650.0,"max_hp":1650.0,"shield":0.0,"x":-31.55017852783203,"y":27.807283401489258,"facing":-1.1367403789521595,"progress":96.82083296775818,"target":7,"hits":29,"reached":true,"dormant":false,"effects":[],"dots":[]},{"id":55,"kind":"troop","team":1,"lane":"top","zone":"lane","slot":3,"uid":"p3-7","def":"g04","alive":true,"hp":1650.0,"max_hp":1650.0,"shield":0.0,"x":-29.65804672241211,"y":29.0261173248291,"facing":-0.8857869497716706,"progress":96.82083296775818,"target":7,"hits":29,"reached":true,"dormant":false,"effects":[],"dots":[]},{"id":56,"kind":"troop","team":1,"lane":"top","zone":"lane","slot":3,"uid":"p3-11","def":"g04","alive":true,"hp":1650.0,"max_hp":1650.0,"shield":0.0,"x":-30.591480255126953,"y":27.363079071044922,"facing":-1.089132649240035,"progress":96.82083296775818,"target":7,"hits":29,"reached":true,"dormant":false,"effects":[],"dots":[]},{"id":57,"kind":"troop","team":1,"lane":"top","zone":"lane","slot":3,"uid":"p3-14","def":"g04","alive":true,"hp":1650.0,"max_hp":1650.0,"shield":0.0,"x":-29.17594337463379,"y":28.270872116088867,"facing":0.5319417397763887,"progress":96.82083296775818,"target":7,"hits":30,"reached":true,"dormant":false,"effects":[],"dots":[]},{"id":58,"kind":"troop","team":1,"lane":"top","zone":"lane","slot":3,"uid":"p3-5","def":"g02","alive":false,"hp":0.0,"max_hp":690.0,"shield":0.0,"x":-26.59674835205078,"y":3.904137134552002,"facing":0.4641711691623916,"progress":78.86129136323929,"target":-1,"hits":23,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":59,"kind":"troop","team":1,"lane":"top","zone":"lane","slot":3,"uid":"p3-10","def":"g02","alive":false,"hp":0.0,"max_hp":690.0,"shield":0.0,"x":-25.254154205322266,"y":3.6930034160614014,"facing":0.11315719066235237,"progress":78.76755815129339,"target":-1,"hits":20,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":60,"kind":"troop","team":1,"lane":"top","zone":"lane","slot":3,"uid":"p3-8","def":"g08","alive":true,"hp":820.0,"max_hp":820.0,"shield":0.0,"x":-28.11039924621582,"y":23.99005699157715,"facing":1.9293605987195865,"progress":96.82083296775818,"target":7,"hits":27,"reached":true,"dormant":false,"effects":[],"dots":[]},{"id":61,"kind":"troop","team":1,"lane":"top","zone":"lane","slot":3,"uid":"p3-4","def":"g06","alive":true,"hp":640.0,"max_hp":640.0,"shield":0.0,"x":-26.485397338867188,"y":23.03745460510254,"facing":-2.8314694821495348,"progress":96.82083296775818,"target":7,"hits":28,"reached":true,"dormant":false,"effects":[],"dots":[]},{"id":62,"kind":"troop","team":1,"lane":"top","zone":"lane","slot":3,"uid":"p3-9","def":"g06","alive":true,"hp":640.0,"max_hp":640.0,"shield":0.0,"x":-29.3768367767334,"y":22.22735595703125,"facing":-2.7336642029643974,"progress":96.82083296775818,"target":7,"hits":28,"reached":true,"dormant":false,"effects":[],"dots":[]},{"id":63,"kind":"troop","team":1,"lane":"top","zone":"lane","slot":3,"uid":"p3-12","def":"g06","alive":true,"hp":640.0,"max_hp":640.0,"shield":0.0,"x":-28.2027645111084,"y":22.41217613220215,"facing":2.4777639766230983,"progress":96.82083296775818,"target":7,"hits":27,"reached":true,"dormant":false,"effects":[],"dots":[]},{"id":64,"kind":"hero","team":1,"lane":"top","zone":"lane","slot":3,"uid":"h3-1","def":"w10","alive":true,"hp":1300.0,"max_hp":1300.0,"shield":0.0,"x":-29.142005920410156,"y":24.370187759399414,"facing":-2.960139620480635,"progress":96.82083296775818,"target":7,"hits":27,"reached":true,"dormant":false,"effects":[["hearth_warmth","damage",0.15,4.0]],"dots":[]},{"id":65,"kind":"troop","team":1,"lane":"top","zone":"lane","slot":3,"uid":"p3-6","def":"g10","alive":true,"hp":1080.0,"max_hp":1080.0,"shield":0.0,"x":-27.154142379760742,"y":25.54224395751953,"facing":-2.0880324263861714,"progress":96.82083296775818,"target":7,"hits":27,"reached":true,"dormant":false,"effects":[["hearth_warmth","damage",0.15,4.0]],"dots":[]},{"id":66,"kind":"troop","team":1,"lane":"top","zone":"lane","slot":3,"uid":"p3-13","def":"g10","alive":true,"hp":1080.0,"max_hp":1080.0,"shield":0.0,"x":-30.159826278686523,"y":24.785795211791992,"facing":-1.1857267479788964,"progress":96.82083296775818,"target":7,"hits":23,"reached":true,"dormant":false,"effects":[["hearth_warmth","damage",0.15,4.0]],"dots":[]},{"id":67,"kind":"hero","team":1,"lane":"mid","zone":"lane","slot":4,"uid":"h4-1","def":"w04","alive":false,"hp":0.0,"max_hp":2200.0,"shield":0.0,"x":-28.164493560791016,"y":23.05375099182129,"facing":-0.575676571426794,"progress":61.16015148162842,"target":-1,"hits":24,"reached":true,"dormant":false,"effects":[],"dots":[]},{"id":68,"kind":"troop","team":1,"lane":"mid","zone":"lane","slot":4,"uid":"p4-3","def":"w04","alive":true,"hp":1560.0,"max_hp":1560.0,"shield":0.0,"x":-28.479576110839844,"y":27.758481979370117,"facing":-2.250355625423741,"progress":61.160152435302734,"target":7,"hits":41,"reached":true,"dormant":false,"effects":[],"dots":[]},{"id":69,"kind":"troop","team":1,"lane":"mid","zone":"lane","slot":4,"uid":"p4-6","def":"w04","alive":true,"hp":1560.0,"max_hp":1560.0,"shield":0.0,"x":-29.345043182373047,"y":29.936086654663086,"facing":0.0780826827080778,"progress":61.160152435302734,"target":7,"hits":40,"reached":true,"dormant":false,"effects":[],"dots":[]},{"id":70,"kind":"troop","team":1,"lane":"mid","zone":"lane","slot":4,"uid":"p4-10","def":"w04","alive":false,"hp":0.0,"max_hp":1560.0,"shield":0.0,"x":-23.24155616760254,"y":28.258874893188477,"facing":0.7621465405869854,"progress":61.16015148162842,"target":-1,"hits":18,"reached":true,"dormant":false,"effects":[],"dots":[]},{"id":71,"kind":"troop","team":1,"lane":"mid","zone":"lane","slot":4,"uid":"p4-12","def":"w04","alive":true,"hp":1560.0,"max_hp":1560.0,"shield":0.0,"x":-30.900876998901367,"y":28.78981590270996,"facing":-0.8418561348224695,"progress":61.16015148162842,"target":7,"hits":39,"reached":true,"dormant":false,"effects":[],"dots":[]},{"id":72,"kind":"troop","team":1,"lane":"mid","zone":"lane","slot":4,"uid":"p4-4","def":"w02","alive":false,"hp":0.0,"max_hp":800.0,"shield":0.0,"x":-27.05379295349121,"y":23.101573944091797,"facing":2.2817056999784633,"progress":61.16015148162842,"target":-1,"hits":26,"reached":true,"dormant":false,"effects":[],"dots":[]},{"id":73,"kind":"troop","team":1,"lane":"mid","zone":"lane","slot":4,"uid":"p4-9","def":"w02","alive":false,"hp":0.0,"max_hp":800.0,"shield":0.0,"x":-22.22947883605957,"y":27.66292953491211,"facing":1.113700630591941,"progress":61.16015148162842,"target":-1,"hits":23,"reached":true,"dormant":false,"effects":[],"dots":[]},{"id":74,"kind":"troop","team":1,"lane":"mid","zone":"lane","slot":4,"uid":"p4-13","def":"w02","alive":false,"hp":0.0,"max_hp":800.0,"shield":0.0,"x":-21.60465431213379,"y":28.5682315826416,"facing":0.6078643324809162,"progress":61.16015148162842,"target":-1,"hits":32,"reached":true,"dormant":false,"effects":[],"dots":[]},{"id":75,"kind":"troop","team":1,"lane":"mid","zone":"lane","slot":4,"uid":"p4-7","def":"w08","alive":true,"hp":940.0,"max_hp":940.0,"shield":0.0,"x":-26.19533920288086,"y":26.080854415893555,"facing":2.358719737349857,"progress":61.16015148162842,"target":7,"hits":38,"reached":true,"dormant":false,"effects":[["hearth_warmth","damage",0.15,4.0]],"dots":[]},{"id":76,"kind":"troop","team":1,"lane":"mid","zone":"lane","slot":4,"uid":"p4-5","def":"w06","alive":true,"hp":630.0,"max_hp":630.0,"shield":0.0,"x":-25.166339874267578,"y":24.534879684448242,"facing":-0.7441957150521579,"progress":61.16015148162842,"target":7,"hits":37,"reached":true,"dormant":false,"effects":[],"dots":[]},{"id":77,"kind":"troop","team":1,"lane":"mid","zone":"lane","slot":4,"uid":"p4-11","def":"w06","alive":true,"hp":630.0,"max_hp":630.0,"shield":0.0,"x":-24.4118709564209,"y":25.32876205444336,"facing":-0.8355948683449367,"progress":61.16015148162842,"target":7,"hits":38,"reached":true,"dormant":false,"effects":[],"dots":[]},{"id":78,"kind":"troop","team":1,"lane":"mid","zone":"lane","slot":4,"uid":"p4-14","def":"w06","alive":true,"hp":630.0,"max_hp":630.0,"shield":0.0,"x":-23.761802673339844,"y":26.21204376220703,"facing":0.6376036467564525,"progress":61.16015148162842,"target":7,"hits":38,"reached":true,"dormant":false,"effects":[],"dots":[]},{"id":79,"kind":"troop","team":1,"lane":"mid","zone":"lane","slot":4,"uid":"p4-8","def":"w10","alive":true,"hp":1000.0,"max_hp":1000.0,"shield":0.0,"x":-27.852855682373047,"y":26.717952728271484,"facing":-1.8586514800840135,"progress":61.16015148162842,"target":7,"hits":35,"reached":true,"dormant":false,"effects":[["hearth_warmth","damage",0.15,4.0]],"dots":[]},{"id":80,"kind":"hero","team":1,"lane":"bot","zone":"lane","slot":5,"uid":"h5-1","def":"w04","alive":true,"hp":2550.0,"max_hp":2550.0,"shield":0.0,"x":-27.882322311401367,"y":28.319318771362305,"facing":2.427919704674834,"progress":96.8208339214325,"target":7,"hits":32,"reached":true,"dormant":false,"effects":[],"dots":[]},{"id":81,"kind":"troop","team":1,"lane":"bot","zone":"lane","slot":5,"uid":"p5-2","def":"g04","alive":true,"hp":1650.0,"max_hp":1650.0,"shield":0.0,"x":-28.57322120666504,"y":29.142183303833008,"facing":-2.1390303185411614,"progress":96.8208339214325,"target":7,"hits":29,"reached":true,"dormant":false,"effects":[],"dots":[]},{"id":82,"kind":"troop","team":1,"lane":"bot","zone":"lane","slot":5,"uid":"p5-6","def":"g04","alive":true,"hp":1650.0,"max_hp":1650.0,"shield":0.0,"x":-27.44528579711914,"y":30.831262588500977,"facing":-1.6491823131052001,"progress":96.8208339214325,"target":7,"hits":30,"reached":true,"dormant":false,"effects":[],"dots":[]},{"id":83,"kind":"troop","team":1,"lane":"bot","zone":"lane","slot":5,"uid":"p5-10","def":"g04","alive":true,"hp":1650.0,"max_hp":1650.0,"shield":0.0,"x":-27.93562126159668,"y":31.73906898498535,"facing":-0.5144732510622272,"progress":96.8208339214325,"target":7,"hits":29,"reached":true,"dormant":false,"effects":[],"dots":[]},{"id":84,"kind":"troop","team":1,"lane":"bot","zone":"lane","slot":5,"uid":"p5-13","def":"g04","alive":true,"hp":1650.0,"max_hp":1650.0,"shield":0.0,"x":-27.485042572021484,"y":29.01812744140625,"facing":1.4309947179971696,"progress":96.8208339214325,"target":7,"hits":32,"reached":true,"dormant":false,"effects":[],"dots":[]},{"id":85,"kind":"troop","team":1,"lane":"bot","zone":"lane","slot":5,"uid":"p5-3","def":"g02","alive":false,"hp":0.0,"max_hp":690.0,"shield":0.0,"x":11.759172439575195,"y":27.48834228515625,"facing":-2.3420920000513483,"progress":61.43354204893112,"target":-1,"hits":17,"reached":false,"dormant":false,"effects":[["hearth_warmth","damage",0.15,2.8000000000000043]],"dots":[]},{"id":86,"kind":"troop","team":1,"lane":"bot","zone":"lane","slot":5,"uid":"p5-8","def":"g02","alive":false,"hp":0.0,"max_hp":690.0,"shield":0.0,"x":11.745038986206055,"y":28.764211654663086,"facing":-1.0217057151811901,"progress":61.43354204893112,"target":-1,"hits":9,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":87,"kind":"troop","team":1,"lane":"bot","zone":"lane","slot":5,"uid":"p5-11","def":"g02","alive":false,"hp":0.0,"max_hp":690.0,"shield":0.0,"x":-2.927293300628662,"y":30.984548568725586,"facing":0.23844464920323244,"progress":78.86129215478897,"target":-1,"hits":18,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":88,"kind":"troop","team":1,"lane":"bot","zone":"lane","slot":5,"uid":"p5-5","def":"g08","alive":true,"hp":820.0,"max_hp":820.0,"shield":0.0,"x":-24.381301879882813,"y":27.1575870513916,"facing":2.419537436697465,"progress":96.8208339214325,"target":7,"hits":26,"reached":true,"dormant":false,"effects":[["hearth_warmth","damage",0.15,4.0]],"dots":[]},{"id":89,"kind":"troop","team":1,"lane":"bot","zone":"lane","slot":5,"uid":"p5-4","def":"g06","alive":true,"hp":640.0,"max_hp":640.0,"shield":0.0,"x":-22.732868194580078,"y":27.1958065032959,"facing":2.2828948071908077,"progress":96.8208339214325,"target":7,"hits":27,"reached":true,"dormant":false,"effects":[],"dots":[]},{"id":90,"kind":"troop","team":1,"lane":"bot","zone":"lane","slot":5,"uid":"p5-9","def":"g06","alive":true,"hp":640.0,"max_hp":640.0,"shield":0.0,"x":-22.413267135620117,"y":28.256011962890625,"facing":0.29019956607313296,"progress":96.8208339214325,"target":7,"hits":27,"reached":true,"dormant":false,"effects":[],"dots":[]},{"id":91,"kind":"troop","team":1,"lane":"bot","zone":"lane","slot":5,"uid":"p5-12","def":"g06","alive":true,"hp":640.0,"max_hp":640.0,"shield":0.0,"x":-22.22258949279785,"y":29.74030876159668,"facing":-1.4648869555194666,"progress":96.8208339214325,"target":7,"hits":27,"reached":true,"dormant":false,"effects":[],"dots":[]},{"id":92,"kind":"troop","team":1,"lane":"bot","zone":"lane","slot":5,"uid":"p5-7","def":"g10","alive":true,"hp":1080.0,"max_hp":1080.0,"shield":0.0,"x":-25.102882385253906,"y":27.98606300354004,"facing":0.9084841230924541,"progress":96.8208339214325,"target":7,"hits":25,"reached":true,"dormant":false,"effects":[["hearth_warmth","damage",0.15,4.0]],"dots":[]}]},{"label":"settled","phase":2,"round":12,"winner":1,"end_note":"Ancient von Blau zerstört.","players":[{"gold":82,"draft_gold":70,"ready":true,"earned":12,"spent":150,"next_seq":2,"roster":[],"hero":"","bookings":["c0-1|ch_schutz|top|150|13"],"new_bookings":["c0-1|ch_schutz|top|150"],"draft_roster":[],"draft_hero":"","boss_lane":"","undo":0},{"gold":60,"draft_gold":40,"ready":true,"earned":20,"spent":180,"next_seq":2,"roster":[],"hero":"","bookings":["c1-1|ch_belagerung|mid|180|13"],"new_bookings":["c1-1|ch_belagerung|mid|180"],"draft_roster":[],"draft_hero":"","boss_lane":"","undo":0},{"gold":22,"draft_gold":10,"ready":true,"earned":12,"spent":210,"next_seq":3,"roster":["p2-2|w05|bot|60"],"hero":"","bookings":["c2-1|ch_druck|bot|150|13"],"new_bookings":["c2-1|ch_druck|bot|150"],"draft_roster":["p2-2|w05|bot|60|true"],"draft_hero":"","boss_lane":"","undo":0},{"gold":3550,"draft_gold":3030,"ready":true,"earned":520,"spent":0,"next_seq":15,"roster":["p3-3|g04|top|220","p3-4|g06|top|205","p3-5|g02|top|135","p3-6|g10|top|255","p3-7|g04|top|220","p3-8|g08|top|285","p3-9|g06|top|205","p3-10|g02|top|135","p3-11|g04|top|220","p3-12|g06|top|205","p3-13|g10|top|255","p3-14|g04|top|220"],"hero":"h3-1|held_quellgeflecht|406|top|quellamulett||260|false|","bookings":["c3-2|ch_schutz|top|150|13"],"new_bookings":["c3-2|ch_schutz|top|150"],"draft_roster":["p3-3|g04|top|220|true","p3-4|g06|top|205|true","p3-5|g02|top|135|true","p3-6|g10|top|255|true","p3-7|g04|top|220|true","p3-8|g08|top|285|true","p3-9|g06|top|205|true","p3-10|g02|top|135|true","p3-11|g04|top|220|true","p3-12|g06|top|205|true","p3-13|g10|top|255|true","p3-14|g04|top|220|true"],"draft_hero":"h3-1|held_quellgeflecht|0|top|quellamulett||260|true|quellamulett","boss_lane":"","undo":0},{"gold":3600,"draft_gold":3080,"ready":true,"earned":520,"spent":0,"next_seq":15,"roster":["p4-3|w04|mid|230","p4-4|w02|mid|150","p4-5|w06|mid|195","p4-6|w04|mid|230","p4-7|w08|mid|295","p4-8|w10|mid|270","p4-9|w02|mid|150","p4-10|w04|mid|230","p4-11|w06|mid|195","p4-12|w04|mid|230","p4-13|w02|mid|150","p4-14|w06|mid|195"],"hero":"h4-1|held_ringborke|256|mid|glutklinge||260|false|","bookings":["c4-2|ch_belagerung|mid|180|13"],"new_bookings":["c4-2|ch_belagerung|mid|180"],"draft_roster":["p4-3|w04|mid|230|true","p4-4|w02|mid|150|true","p4-5|w06|mid|195|true","p4-6|w04|mid|230|true","p4-7|w08|mid|295|true","p4-8|w10|mid|270|true","p4-9|w02|mid|150|true","p4-10|w04|mid|230|true","p4-11|w06|mid|195|true","p4-12|w04|mid|230|true","p4-13|w02|mid|150|true","p4-14|w06|mid|195|true"],"draft_hero":"h4-1|held_ringborke|0|mid|glutklinge||260|true|glutklinge","boss_lane":"","undo":0},{"gold":3860,"draft_gold":3340,"ready":true,"earned":520,"spent":0,"next_seq":14,"roster":["p5-2|g04|bot|220","p5-3|g02|bot|135","p5-4|g06|bot|205","p5-5|g08|bot|285","p5-6|g04|bot|220","p5-7|g10|bot|255","p5-8|g02|bot|135","p5-9|g06|bot|205","p5-10|g04|bot|220","p5-11|g02|bot|135","p5-12|g06|bot|205","p5-13|g04|bot|220"],"hero":"h5-1|held_ringborke|421|bot|basaltschild||260|false|","bookings":[],"new_bookings":[],"draft_roster":["p5-2|g04|bot|220|true","p5-3|g02|bot|135|true","p5-4|g06|bot|205|true","p5-5|g08|bot|285|true","p5-6|g04|bot|220|true","p5-7|g10|bot|255|true","p5-8|g02|bot|135|true","p5-9|g06|bot|205|true","p5-10|g04|bot|220|true","p5-11|g02|bot|135|true","p5-12|g06|bot|205|true","p5-13|g04|bot|220|true"],"draft_hero":"h5-1|held_ringborke|0|bot|basaltschild||260|true|basaltschild","boss_lane":"","undo":0}],"buildings":[0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,7500.0,6000.0,7500.0,6000.0,7500.0,6000.0,9000.0,9000.0,12000.0],"boss":{"next":1,"settled":12,"claim":""},"boss_log":[],"announcements":[],"settlement":{"round":12,"gains":[12,20,12,520,520,520],"income":114,"lost":["blau_top_outer","blau_bot_outer","blau_top_inner","blau_bot_inner","blau_base_1","blau_base_2","blau_ancient"],"end_reason":"core","combat_time":61.84999999999862,"boss":"none","lane_kills":{"mid":8,"bot":7,"top":7},"xp":{"h4-1":256,"h5-1":421,"h3-1":406}},"combat":{"round":12,"steps":1237,"elapsed":61.84999999999862,"finished":true,"end_reason":"core","destroyed":[0],"grotto":"none|-1|-1|true","grotto_boss":"","grotto_boss_hp":0.0,"events":40,"mobile":[0,43,0]},"events":[[1,139,6.949999999999983,0,"mid","lane","monster",23,"e01",9,"",24,["h4-1"]],[2,167,8.349999999999984,0,"mid","lane","monster",24,"e02",17,"",24,["h4-1"]],[3,167,8.349999999999984,1,"mid","lane","monster",41,"e01",9,"",24,[]],[4,212,10.600000000000016,0,"mid","lane","monster",25,"e05",29,"",24,["h4-1"]],[5,232,11.60000000000003,0,"bot","lane","monster",29,"e01",9,"",24,["h5-1"]],[6,235,11.750000000000032,0,"top","lane","monster",17,"e01",9,"",24,["h3-1"]],[7,239,11.950000000000035,0,"mid","lane","monster",27,"e03",14,"",24,["h4-1"]],[8,260,13.00000000000005,0,"mid","lane","monster",28,"e06",17,"",24,["h4-1"]],[9,266,13.300000000000054,0,"bot","lane","monster",30,"e02",17,"",24,["h5-1"]],[10,268,13.400000000000055,0,"top","lane","monster",18,"e02",17,"",24,["h3-1"]],[11,271,13.550000000000058,1,"bot","lane","monster",47,"e01",9,"",24,[]],[12,291,14.550000000000072,0,"bot","lane","monster",33,"e03",14,"",24,["h5-1"]],[13,295,14.750000000000075,0,"top","lane","monster",21,"e03",14,"",24,["h3-1"]],[14,295,14.750000000000075,0,"mid","lane","monster",26,"e04",14,"",24,["h4-1"]],[15,318,15.900000000000091,1,"top","lane","monster",35,"e01",9,"",24,[]],[16,333,16.6500000000001,0,"top","lane","monster",19,"e05",29,"",24,["h3-1"]],[17,354,17.700000000000117,0,"bot","lane","monster",31,"e05",29,"",24,["h5-1"]],[18,359,17.95000000000012,0,"top","lane","monster",22,"e06",17,"",24,["h3-1"]],[19,376,18.800000000000132,0,"bot","lane","monster",34,"e06",17,"",24,["h5-1"]],[20,391,19.550000000000143,0,"top","lane","monster",20,"e04",14,"",24,["h3-1"]],[21,401,20.05000000000015,0,"bot","lane","troop",53,"w05",0,"",15,["h5-1"]],[22,407,20.350000000000154,0,"bot","lane","monster",32,"e04",14,"",24,["h5-1"]],[23,504,25.200000000000223,1,"bot","lane","troop",86,"g02",0,"",15,[]],[24,614,30.7000000000003,0,"top","lane","tower",2,"blau_top_outer",150,"blau_top_outer",60,["h3-1"]],[25,624,31.20000000000031,1,"bot","lane","troop",85,"g02",0,"",15,[]],[26,627,31.35000000000031,0,"bot","lane","tower",4,"blau_bot_outer",150,"blau_bot_outer",60,["h5-1"]],[27,686,34.30000000000019,1,"mid","lane","troop",70,"w04",0,"",15,[]],[28,746,37.30000000000002,1,"mid","lane","monster",42,"e02",17,"",24,[]],[29,807,40.349999999999845,1,"mid","lane","hero",67,"w04",0,"",15,[]],[30,815,40.74999999999982,1,"top","lane","troop",59,"g02",0,"",15,[]],[31,833,41.64999999999977,1,"bot","lane","troop",87,"g02",0,"",15,[]],[32,866,43.29999999999968,1,"mid","lane","troop",73,"w02",0,"",15,[]],[33,935,46.74999999999948,1,"top","lane","troop",58,"g02",0,"",15,[]],[34,942,47.09999999999946,0,"top","lane","tower",1,"blau_top_inner",210,"blau_top_inner",60,["h3-1"]],[35,947,47.34999999999945,1,"mid","lane","troop",72,"w02",0,"",15,[]],[36,981,49.04999999999935,0,"bot","lane","tower",3,"blau_bot_inner",210,"blau_bot_inner",60,["h5-1"]],[37,986,49.299999999999336,1,"mid","lane","troop",74,"w02",0,"",15,[]],[38,1016,50.79999999999925,0,"base","lane","tower",5,"blau_base_1",270,"blau_base_1",60,[]],[39,1016,50.79999999999925,0,"base","lane","tower",6,"blau_base_2",270,"blau_base_2",60,[]],[40,1237,61.84999999999862,0,"base","lane","core",7,"blau_ancient",0,"blau_ancient",60,["h3-1","h5-1"]]]}],"results":[["begin",-1,"",true,""]]},"ancient_destruction":{"title":"Ancient-Zerstörung beendet die Partie","snapshots":[{"label":"over","phase":2,"round":12,"winner":0,"end_note":"Ancient von Rot zerstört.","players":[{"gold":5380,"draft_gold":5180,"ready":true,"earned":200,"spent":0,"next_seq":15,"roster":["p0-3|g02|top|135","p0-4|g06|top|205","p0-5|g04|top|220","p0-6|g08|top|285","p0-7|g02|top|135","p0-8|g06|top|205","p0-9|g02|top|135","p0-10|g04|top|220","p0-11|g10|top|255","p0-12|g02|top|135","p0-13|g06|top|205","p0-14|g08|top|285"],"hero":"h0-1|held_funkenlanze|316|top|glutklinge||260|false|","bookings":["c0-2|ch_belagerung|top|180|13"],"new_bookings":["c0-2|ch_belagerung|top|180"],"draft_roster":["p0-3|g02|top|135|true","p0-4|g06|top|205|true","p0-5|g04|top|220|true","p0-6|g08|top|285|true","p0-7|g02|top|135|true","p0-8|g06|top|205|true","p0-9|g02|top|135|true","p0-10|g04|top|220|true","p0-11|g10|top|255|true","p0-12|g02|top|135|true","p0-13|g06|top|205|true","p0-14|g08|top|285|true"],"draft_hero":"h0-1|held_funkenlanze|0|top|glutklinge||260|true|glutklinge","boss_lane":"","undo":0},{"gold":5135,"draft_gold":4935,"ready":true,"earned":200,"spent":0,"next_seq":15,"roster":["p1-3|w06|mid|195","p1-4|w04|mid|230","p1-5|w08|mid|295","p1-6|w06|mid|195","p1-7|w02|mid|150","p1-8|w10|mid|270","p1-9|w06|mid|195","p1-10|w04|mid|230","p1-11|w06|mid|195","p1-12|w04|mid|230","p1-13|w08|mid|295","p1-14|w06|mid|195"],"hero":"h1-1|held_funkenlanze|361|mid|funkenfokus||260|false|","bookings":["c1-2|ch_druck|mid|150|13"],"new_bookings":["c1-2|ch_druck|mid|150"],"draft_roster":["p1-3|w06|mid|195|true","p1-4|w04|mid|230|true","p1-5|w08|mid|295|true","p1-6|w06|mid|195|true","p1-7|w02|mid|150|true","p1-8|w10|mid|270|true","p1-9|w06|mid|195|true","p1-10|w04|mid|230|true","p1-11|w06|mid|195|true","p1-12|w04|mid|230|true","p1-13|w08|mid|295|true","p1-14|w06|mid|195|true"],"draft_hero":"h1-1|held_funkenlanze|0|mid|funkenfokus||260|true|funkenfokus","boss_lane":"","undo":0},{"gold":5230,"draft_gold":5030,"ready":true,"earned":200,"spent":0,"next_seq":15,"roster":["p2-3|g04|bot|220","p2-4|g06|bot|205","p2-5|g02|bot|135","p2-6|g10|bot|255","p2-7|g04|bot|220","p2-8|g08|bot|285","p2-9|g06|bot|205","p2-10|g02|bot|135","p2-11|g04|bot|220","p2-12|g06|bot|205","p2-13|g10|bot|255","p2-14|g04|bot|220"],"hero":"h2-1|held_quellgeflecht|316|bot|quellamulett||260|false|","bookings":["c2-2|ch_schutz|bot|150|13"],"new_bookings":["c2-2|ch_schutz|bot|150"],"draft_roster":["p2-3|g04|bot|220|true","p2-4|g06|bot|205|true","p2-5|g02|bot|135|true","p2-6|g10|bot|255|true","p2-7|g04|bot|220|true","p2-8|g08|bot|285|true","p2-9|g06|bot|205|true","p2-10|g02|bot|135|true","p2-11|g04|bot|220|true","p2-12|g06|bot|205|true","p2-13|g10|bot|255|true","p2-14|g04|bot|220|true"],"draft_hero":"h2-1|held_quellgeflecht|0|bot|quellamulett||260|true|quellamulett","boss_lane":"","undo":0},{"gold":52,"draft_gold":40,"ready":true,"earned":12,"spent":180,"next_seq":2,"roster":[],"hero":"","bookings":["c3-1|ch_belagerung|top|180|13"],"new_bookings":["c3-1|ch_belagerung|top|180"],"draft_roster":[],"draft_hero":"","boss_lane":"","undo":0},{"gold":60,"draft_gold":40,"ready":true,"earned":20,"spent":180,"next_seq":4,"roster":["p4-1|g03|mid|70","p4-2|g01|mid|45","p4-3|g05|mid|65"],"hero":"","bookings":[],"new_bookings":[],"draft_roster":["p4-1|g03|mid|70|true","p4-2|g01|mid|45|true","p4-3|g05|mid|65|true"],"draft_hero":"","boss_lane":"","undo":0},{"gold":82,"draft_gold":70,"ready":true,"earned":12,"spent":150,"next_seq":2,"roster":[],"hero":"","bookings":["c5-1|ch_schutz|bot|150|13"],"new_bookings":["c5-1|ch_schutz|bot|150"],"draft_roster":[],"draft_hero":"","boss_lane":"","undo":0}],"buildings":[7500.0,6000.0,7500.0,6000.0,7500.0,6000.0,9000.0,9000.0,12000.0,0.0,0.0,1494.1892999999934,0.0,7500.0,0.0,0.0,0.0,0.0],"boss":{"next":1,"settled":12,"claim":""},"boss_log":[],"announcements":[],"settlement":{"round":12,"gains":[200,200,200,12,20,12],"income":114,"lost":["rot_mid_outer","rot_bot_outer","rot_ancient"],"end_reason":"core","combat_time":36.500000000000064,"boss":"none","lane_kills":{"mid":8,"bot":7,"top":7},"xp":{"h1-1":361,"h2-1":316,"h0-1":316}},"combat":{"round":12,"steps":730,"elapsed":36.500000000000064,"finished":true,"end_reason":"core","destroyed":[1],"grotto":"none|-1|-1|true","grotto_boss":"","grotto_boss_hp":0.0,"events":30,"mobile":[51,0,0]},"events":[[1,139,6.949999999999983,1,"mid","lane","monster",39,"e01",9,"",24,["h1-1"]],[2,155,7.7499999999999805,0,"mid","lane","monster",21,"e01",9,"",24,[]],[3,162,8.09999999999998,1,"mid","lane","monster",40,"e02",17,"",24,["h1-1"]],[4,190,9.5,1,"mid","lane","troop",91,"g01",0,"",15,["h1-1"]],[5,204,10.20000000000001,1,"mid","lane","troop",90,"g03",0,"",15,["h1-1"]],[6,225,11.250000000000025,1,"bot","lane","monster",45,"e01",9,"",24,["h2-1"]],[7,232,11.60000000000003,1,"top","lane","monster",33,"e01",9,"",24,["h0-1"]],[8,232,11.60000000000003,1,"mid","lane","monster",41,"e05",29,"",24,["h1-1"]],[9,259,12.950000000000049,1,"mid","lane","monster",43,"e03",14,"",24,["h1-1"]],[10,263,13.150000000000052,1,"bot","lane","monster",46,"e02",17,"",24,["h2-1"]],[11,267,13.350000000000055,1,"top","lane","monster",34,"e02",17,"",24,["h0-1"]],[12,281,14.050000000000065,1,"mid","lane","monster",44,"e06",17,"",24,["h1-1"]],[13,291,14.550000000000072,1,"bot","lane","monster",49,"e03",14,"",24,["h2-1"]],[14,292,14.600000000000072,1,"top","lane","monster",37,"e03",14,"",24,["h0-1"]],[15,295,14.750000000000075,0,"top","lane","monster",15,"e01",9,"",24,[]],[16,313,15.650000000000087,1,"mid","lane","troop",92,"g05",0,"",15,["h1-1"]],[17,319,15.950000000000092,0,"bot","lane","monster",27,"e01",9,"",24,[]],[18,333,16.6500000000001,1,"top","lane","monster",35,"e05",29,"",24,["h0-1"]],[19,334,16.700000000000102,1,"bot","lane","monster",47,"e05",29,"",24,["h2-1"]],[20,335,16.750000000000103,1,"mid","lane","monster",42,"e04",14,"",24,["h1-1"]],[21,342,17.100000000000108,0,"mid","lane","troop",67,"w02",0,"",15,[]],[22,358,17.90000000000012,1,"top","lane","monster",38,"e06",17,"",24,["h0-1"]],[23,364,18.200000000000124,1,"bot","lane","monster",50,"e06",17,"",24,["h2-1"]],[24,391,19.550000000000143,1,"top","lane","monster",36,"e04",14,"",24,["h0-1"]],[25,395,19.750000000000146,1,"bot","lane","monster",48,"e04",14,"",24,["h2-1"]],[26,442,22.10000000000018,0,"mid","lane","monster",22,"e02",17,"",24,[]],[27,496,24.800000000000217,0,"bot","lane","troop",82,"g02",0,"",15,[]],[28,504,25.200000000000223,1,"mid","lane","tower",11,"rot_mid_outer",150,"rot_mid_outer",60,["h1-1"]],[29,629,31.450000000000312,1,"bot","lane","tower",13,"rot_bot_outer",150,"rot_bot_outer",60,["h2-1"]],[30,730,36.500000000000064,1,"base","lane","core",14,"rot_ancient",0,"rot_ancient",60,["h0-1"]]]}],"results":[["begin",-1,"",true,""]]},"high_wave_21":{"title":"Hohe Welle über 20: normale Welle, stärkere Monster","snapshots":[{"label":"spawned","phase":1,"round":21,"winner":-2,"end_note":"","players":[{"gold":935,"draft_gold":935,"ready":true,"earned":0,"spent":0,"next_seq":15,"roster":["p0-3|w06|top|195","p0-4|w04|top|230","p0-5|w08|top|295","p0-6|w06|top|195","p0-7|w02|top|150","p0-8|w10|top|270","p0-9|w06|top|195","p0-10|w04|top|230","p0-11|w06|top|195","p0-12|w04|top|230","p0-13|w08|top|295","p0-14|w06|top|195"],"hero":"h0-1|held_funkenlanze|0|top|funkenfokus||260|false|","bookings":["c0-2|ch_druck|top|150|22"],"new_bookings":["c0-2|ch_druck|top|150"],"draft_roster":["p0-3|w06|top|195|true","p0-4|w04|top|230|true","p0-5|w08|top|295|true","p0-6|w06|top|195|true","p0-7|w02|top|150|true","p0-8|w10|top|270|true","p0-9|w06|top|195|true","p0-10|w04|top|230|true","p0-11|w06|top|195|true","p0-12|w04|top|230|true","p0-13|w08|top|295|true","p0-14|w06|top|195|true"],"draft_hero":"h0-1|held_funkenlanze|0|top|funkenfokus||260|true|funkenfokus","boss_lane":"","undo":0},{"gold":1030,"draft_gold":1030,"ready":true,"earned":0,"spent":0,"next_seq":15,"roster":["p1-3|g04|mid|220","p1-4|g06|mid|205","p1-5|g02|mid|135","p1-6|g10|mid|255","p1-7|g04|mid|220","p1-8|g08|mid|285","p1-9|g06|mid|205","p1-10|g02|mid|135","p1-11|g04|mid|220","p1-12|g06|mid|205","p1-13|g10|mid|255","p1-14|g04|mid|220"],"hero":"h1-1|held_quellgeflecht|0|mid|quellamulett||260|false|","bookings":["c1-2|ch_schutz|mid|150|22"],"new_bookings":["c1-2|ch_schutz|mid|150"],"draft_roster":["p1-3|g04|mid|220|true","p1-4|g06|mid|205|true","p1-5|g02|mid|135|true","p1-6|g10|mid|255|true","p1-7|g04|mid|220|true","p1-8|g08|mid|285|true","p1-9|g06|mid|205|true","p1-10|g02|mid|135|true","p1-11|g04|mid|220|true","p1-12|g06|mid|205|true","p1-13|g10|mid|255|true","p1-14|g04|mid|220|true"],"draft_hero":"h1-1|held_quellgeflecht|0|mid|quellamulett||260|true|quellamulett","boss_lane":"","undo":0},{"gold":1080,"draft_gold":1080,"ready":true,"earned":0,"spent":0,"next_seq":15,"roster":["p2-3|w04|bot|230","p2-4|w02|bot|150","p2-5|w06|bot|195","p2-6|w04|bot|230","p2-7|w08|bot|295","p2-8|w10|bot|270","p2-9|w02|bot|150","p2-10|w04|bot|230","p2-11|w06|bot|195","p2-12|w04|bot|230","p2-13|w02|bot|150","p2-14|w06|bot|195"],"hero":"h2-1|held_ringborke|0|bot|glutklinge||260|false|","bookings":["c2-2|ch_belagerung|bot|180|22"],"new_bookings":["c2-2|ch_belagerung|bot|180"],"draft_roster":["p2-3|w04|bot|230|true","p2-4|w02|bot|150|true","p2-5|w06|bot|195|true","p2-6|w04|bot|230|true","p2-7|w08|bot|295|true","p2-8|w10|bot|270|true","p2-9|w02|bot|150|true","p2-10|w04|bot|230|true","p2-11|w06|bot|195|true","p2-12|w04|bot|230|true","p2-13|w02|bot|150|true","p2-14|w06|bot|195|true"],"draft_hero":"h2-1|held_ringborke|0|bot|glutklinge||260|true|glutklinge","boss_lane":"","undo":0},{"gold":1340,"draft_gold":1340,"ready":true,"earned":0,"spent":0,"next_seq":14,"roster":["p3-2|g04|top|220","p3-3|g02|top|135","p3-4|g06|top|205","p3-5|g08|top|285","p3-6|g04|top|220","p3-7|g10|top|255","p3-8|g02|top|135","p3-9|g06|top|205","p3-10|g04|top|220","p3-11|g02|top|135","p3-12|g06|top|205","p3-13|g04|top|220"],"hero":"h3-1|held_ringborke|0|top|basaltschild||260|false|","bookings":[],"new_bookings":[],"draft_roster":["p3-2|g04|top|220|true","p3-3|g02|top|135|true","p3-4|g06|top|205|true","p3-5|g08|top|285|true","p3-6|g04|top|220|true","p3-7|g10|top|255|true","p3-8|g02|top|135|true","p3-9|g06|top|205|true","p3-10|g04|top|220|true","p3-11|g02|top|135|true","p3-12|g06|top|205|true","p3-13|g04|top|220|true"],"draft_hero":"h3-1|held_ringborke|0|top|basaltschild||260|true|basaltschild","boss_lane":"","undo":0},{"gold":1110,"draft_gold":1110,"ready":true,"earned":0,"spent":0,"next_seq":15,"roster":["p4-3|w04|mid|230","p4-4|w06|mid|195","p4-5|w02|mid|150","p4-6|w04|mid|230","p4-7|w08|mid|295","p4-8|w10|mid|270","p4-9|w06|mid|195","p4-10|w04|mid|230","p4-11|w02|mid|150","p4-12|w04|mid|230","p4-13|w06|mid|195","p4-14|w02|mid|150"],"hero":"h4-1|held_ringborke|0|mid|basaltschild||260|false|","bookings":["c4-2|ch_schutz|mid|150|22"],"new_bookings":["c4-2|ch_schutz|mid|150"],"draft_roster":["p4-3|w04|mid|230|true","p4-4|w06|mid|195|true","p4-5|w02|mid|150|true","p4-6|w04|mid|230|true","p4-7|w08|mid|295|true","p4-8|w10|mid|270|true","p4-9|w06|mid|195|true","p4-10|w04|mid|230|true","p4-11|w02|mid|150|true","p4-12|w04|mid|230|true","p4-13|w06|mid|195|true","p4-14|w02|mid|150|true"],"draft_hero":"h4-1|held_ringborke|0|mid|basaltschild||260|true|basaltschild","boss_lane":"","undo":0},{"gold":1180,"draft_gold":1180,"ready":true,"earned":0,"spent":0,"next_seq":15,"roster":["p5-3|g02|bot|135","p5-4|g06|bot|205","p5-5|g04|bot|220","p5-6|g08|bot|285","p5-7|g02|bot|135","p5-8|g06|bot|205","p5-9|g02|bot|135","p5-10|g04|bot|220","p5-11|g10|bot|255","p5-12|g02|bot|135","p5-13|g06|bot|205","p5-14|g08|bot|285"],"hero":"h5-1|held_funkenlanze|0|bot|glutklinge||260|false|","bookings":["c5-2|ch_belagerung|bot|180|22"],"new_bookings":["c5-2|ch_belagerung|bot|180"],"draft_roster":["p5-3|g02|bot|135|true","p5-4|g06|bot|205|true","p5-5|g04|bot|220|true","p5-6|g08|bot|285|true","p5-7|g02|bot|135|true","p5-8|g06|bot|205|true","p5-9|g02|bot|135|true","p5-10|g04|bot|220|true","p5-11|g10|bot|255|true","p5-12|g02|bot|135|true","p5-13|g06|bot|205|true","p5-14|g08|bot|285|true"],"draft_hero":"h5-1|held_funkenlanze|0|bot|glutklinge||260|true|glutklinge","boss_lane":"","undo":0}],"buildings":[7500.0,6000.0,7500.0,6000.0,7500.0,6000.0,9000.0,9000.0,12000.0,7500.0,6000.0,7500.0,6000.0,7500.0,6000.0,9000.0,9000.0,12000.0],"boss":{"next":1,"settled":0,"claim":""},"boss_log":[],"announcements":[],"settlement":null,"combat":{"round":21,"steps":0,"elapsed":0.0,"finished":false,"end_reason":"","destroyed":[],"grotto":"none|-1|-1|true","grotto_boss":"","grotto_boss_hp":0.0,"events":0,"mobile":[60,60,0]},"units":[{"id":1,"kind":"tower","team":0,"lane":"top","zone":"lane","slot":-1,"uid":"","def":"blau_top_inner","alive":true,"hp":7500.0,"max_hp":7500.0,"shield":0.0,"x":-24.931251525878906,"y":4.5293378829956055,"facing":0.0,"progress":0.0,"target":-1,"hits":0,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":2,"kind":"tower","team":0,"lane":"top","zone":"lane","slot":-1,"uid":"","def":"blau_top_outer","alive":true,"hp":6000.0,"max_hp":6000.0,"shield":0.0,"x":-24.921451568603516,"y":-12.715348243713379,"facing":0.0,"progress":0.0,"target":-1,"hits":0,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":3,"kind":"tower","team":0,"lane":"mid","zone":"lane","slot":-1,"uid":"","def":"blau_mid_inner","alive":true,"hp":7500.0,"max_hp":7500.0,"shield":0.0,"x":-11.427590370178223,"y":17.012392044067383,"facing":0.0,"progress":0.0,"target":-1,"hits":0,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":4,"kind":"tower","team":0,"lane":"mid","zone":"lane","slot":-1,"uid":"","def":"blau_mid_outer","alive":true,"hp":6000.0,"max_hp":6000.0,"shield":0.0,"x":-3.8433847427368164,"y":8.990991592407227,"facing":0.0,"progress":0.0,"target":-1,"hits":0,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":5,"kind":"tower","team":0,"lane":"bot","zone":"lane","slot":-1,"uid":"","def":"blau_bot_inner","alive":true,"hp":7500.0,"max_hp":7500.0,"shield":0.0,"x":-4.349228858947754,"y":31.034507751464844,"facing":0.0,"progress":0.0,"target":-1,"hits":0,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":6,"kind":"tower","team":0,"lane":"bot","zone":"lane","slot":-1,"uid":"","def":"blau_bot_outer","alive":true,"hp":6000.0,"max_hp":6000.0,"shield":0.0,"x":11.117134094238281,"y":28.989334106445313,"facing":0.0,"progress":0.0,"target":-1,"hits":0,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":7,"kind":"tower","team":0,"lane":"base","zone":"lane","slot":-1,"uid":"","def":"blau_base_1","alive":true,"hp":9000.0,"max_hp":9000.0,"shield":0.0,"x":-29.476999282836914,"y":24.023000717163086,"facing":0.0,"progress":0.0,"target":-1,"hits":0,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":8,"kind":"tower","team":0,"lane":"base","zone":"lane","slot":-1,"uid":"","def":"blau_base_2","alive":true,"hp":9000.0,"max_hp":9000.0,"shield":0.0,"x":-24.023000717163086,"y":29.476999282836914,"facing":0.0,"progress":0.0,"target":-1,"hits":0,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":9,"kind":"core","team":0,"lane":"base","zone":"lane","slot":-1,"uid":"","def":"blau_ancient","alive":true,"hp":12000.0,"max_hp":12000.0,"shield":0.0,"x":-30.0,"y":30.0,"facing":0.0,"progress":0.0,"target":-1,"hits":0,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":10,"kind":"tower","team":1,"lane":"top","zone":"lane","slot":-1,"uid":"","def":"rot_top_inner","alive":true,"hp":7500.0,"max_hp":7500.0,"shield":0.0,"x":4.5293378829956055,"y":-24.931251525878906,"facing":0.0,"progress":0.0,"target":-1,"hits":0,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":11,"kind":"tower","team":1,"lane":"top","zone":"lane","slot":-1,"uid":"","def":"rot_top_outer","alive":true,"hp":6000.0,"max_hp":6000.0,"shield":0.0,"x":-12.715348243713379,"y":-24.921451568603516,"facing":0.0,"progress":0.0,"target":-1,"hits":0,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":12,"kind":"tower","team":1,"lane":"mid","zone":"lane","slot":-1,"uid":"","def":"rot_mid_inner","alive":true,"hp":7500.0,"max_hp":7500.0,"shield":0.0,"x":17.012392044067383,"y":-11.427590370178223,"facing":0.0,"progress":0.0,"target":-1,"hits":0,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":13,"kind":"tower","team":1,"lane":"mid","zone":"lane","slot":-1,"uid":"","def":"rot_mid_outer","alive":true,"hp":6000.0,"max_hp":6000.0,"shield":0.0,"x":8.990991592407227,"y":-3.8433847427368164,"facing":0.0,"progress":0.0,"target":-1,"hits":0,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":14,"kind":"tower","team":1,"lane":"bot","zone":"lane","slot":-1,"uid":"","def":"rot_bot_inner","alive":true,"hp":7500.0,"max_hp":7500.0,"shield":0.0,"x":31.034507751464844,"y":-4.349228858947754,"facing":0.0,"progress":0.0,"target":-1,"hits":0,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":15,"kind":"tower","team":1,"lane":"bot","zone":"lane","slot":-1,"uid":"","def":"rot_bot_outer","alive":true,"hp":6000.0,"max_hp":6000.0,"shield":0.0,"x":28.989334106445313,"y":11.117134094238281,"facing":0.0,"progress":0.0,"target":-1,"hits":0,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":16,"kind":"tower","team":1,"lane":"base","zone":"lane","slot":-1,"uid":"","def":"rot_base_1","alive":true,"hp":9000.0,"max_hp":9000.0,"shield":0.0,"x":24.023000717163086,"y":-29.476999282836914,"facing":0.0,"progress":0.0,"target":-1,"hits":0,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":17,"kind":"tower","team":1,"lane":"base","zone":"lane","slot":-1,"uid":"","def":"rot_base_2","alive":true,"hp":9000.0,"max_hp":9000.0,"shield":0.0,"x":29.476999282836914,"y":-24.023000717163086,"facing":0.0,"progress":0.0,"target":-1,"hits":0,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":18,"kind":"core","team":1,"lane":"base","zone":"lane","slot":-1,"uid":"","def":"rot_ancient","alive":true,"hp":12000.0,"max_hp":12000.0,"shield":0.0,"x":30.0,"y":-30.0,"facing":0.0,"progress":0.0,"target":-1,"hits":0,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":19,"kind":"monster","team":0,"lane":"top","zone":"lane","slot":-1,"uid":"","def":"e05","alive":true,"hp":1824.0000000000002,"max_hp":1824.0000000000002,"shield":0.0,"x":-28.243892669677734,"y":10.502157211303711,"facing":-2.864119239296395,"progress":11.0,"target":-1,"hits":0,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":20,"kind":"monster","team":0,"lane":"top","zone":"lane","slot":-1,"uid":"","def":"e01","alive":true,"hp":342.0,"max_hp":342.0,"shield":0.0,"x":-26.993616104125977,"y":10.146052360534668,"facing":-2.864119239296395,"progress":11.0,"target":-1,"hits":0,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":21,"kind":"monster","team":0,"lane":"top","zone":"lane","slot":-1,"uid":"","def":"e02","alive":true,"hp":912.0000000000001,"max_hp":912.0000000000001,"shield":0.0,"x":-25.74333953857422,"y":9.789947509765625,"facing":-2.864119239296395,"progress":11.0,"target":-1,"hits":0,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":22,"kind":"monster","team":0,"lane":"top","zone":"lane","slot":-1,"uid":"","def":"e03","alive":true,"hp":570.0,"max_hp":570.0,"shield":0.0,"x":-27.921968460083008,"y":11.702203750610352,"facing":-2.9843745641096318,"progress":9.6,"target":-1,"hits":0,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":23,"kind":"monster","team":0,"lane":"top","zone":"lane","slot":-1,"uid":"","def":"e06","alive":true,"hp":722.0,"max_hp":722.0,"shield":0.0,"x":-26.638002395629883,"y":11.498661041259766,"facing":-2.9843745641096318,"progress":9.6,"target":-1,"hits":0,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":24,"kind":"monster","team":0,"lane":"top","zone":"lane","slot":-1,"uid":"","def":"e04","alive":true,"hp":494.00000000000006,"max_hp":494.00000000000006,"shield":0.0,"x":-25.354036331176758,"y":11.29511833190918,"facing":-2.9843745641096318,"progress":9.6,"target":-1,"hits":0,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":25,"kind":"monster","team":0,"lane":"top","zone":"lane","slot":-1,"uid":"","def":"e03","alive":true,"hp":570.0,"max_hp":570.0,"shield":0.0,"x":-27.702768325805664,"y":13.08493709564209,"facing":-2.9843745641096318,"progress":8.2,"target":-1,"hits":0,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":26,"kind":"monster","team":0,"lane":"mid","zone":"lane","slot":-1,"uid":"","def":"e05","alive":true,"hp":1824.0000000000002,"max_hp":1824.0000000000002,"shield":0.0,"x":-14.408708572387695,"y":13.32747745513916,"facing":2.3870002372622334,"progress":11.0,"target":-1,"hits":0,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":27,"kind":"monster","team":0,"lane":"mid","zone":"lane","slot":-1,"uid":"","def":"e01","alive":true,"hp":342.0,"max_hp":342.0,"shield":0.0,"x":-13.461592674255371,"y":14.21796703338623,"facing":2.3870002372622334,"progress":11.0,"target":-1,"hits":0,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":28,"kind":"monster","team":0,"lane":"mid","zone":"lane","slot":-1,"uid":"","def":"e02","alive":true,"hp":912.0000000000001,"max_hp":912.0000000000001,"shield":0.0,"x":-12.514476776123047,"y":15.1084566116333,"facing":2.3870002372622334,"progress":11.0,"target":-1,"hits":0,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":29,"kind":"monster","team":0,"lane":"mid","zone":"lane","slot":-1,"uid":"","def":"e03","alive":true,"hp":570.0,"max_hp":570.0,"shield":0.0,"x":-15.366670608520508,"y":14.327392578125,"facing":2.3752783515087157,"progress":9.6,"target":-1,"hits":0,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":30,"kind":"monster","team":0,"lane":"mid","zone":"lane","slot":-1,"uid":"","def":"e06","alive":true,"hp":722.0,"max_hp":722.0,"shield":0.0,"x":-14.430057525634766,"y":15.228922843933105,"facing":2.3752783515087157,"progress":9.6,"target":-1,"hits":0,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":31,"kind":"monster","team":0,"lane":"mid","zone":"lane","slot":-1,"uid":"","def":"e04","alive":true,"hp":494.00000000000006,"max_hp":494.00000000000006,"shield":0.0,"x":-13.493444442749023,"y":16.13045310974121,"facing":2.3752783515087157,"progress":9.6,"target":-1,"hits":0,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":32,"kind":"monster","team":0,"lane":"mid","zone":"lane","slot":-1,"uid":"","def":"e03","alive":true,"hp":570.0,"max_hp":570.0,"shield":0.0,"x":-16.32254409790039,"y":15.30062484741211,"facing":2.347786769279204,"progress":8.2,"target":-1,"hits":0,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":33,"kind":"monster","team":0,"lane":"bot","zone":"lane","slot":-1,"uid":"","def":"e05","alive":true,"hp":1824.0000000000002,"max_hp":1824.0000000000002,"shield":0.0,"x":-9.842267036437988,"y":25.94097137451172,"facing":1.4313591016628469,"progress":11.0,"target":-1,"hits":0,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":34,"kind":"monster","team":0,"lane":"bot","zone":"lane","slot":-1,"uid":"","def":"e01","alive":true,"hp":342.0,"max_hp":342.0,"shield":0.0,"x":-10.022948265075684,"y":27.22835350036621,"facing":1.4313591016628469,"progress":11.0,"target":-1,"hits":0,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":35,"kind":"monster","team":0,"lane":"bot","zone":"lane","slot":-1,"uid":"","def":"e02","alive":true,"hp":912.0000000000001,"max_hp":912.0000000000001,"shield":0.0,"x":-10.203629493713379,"y":28.515735626220703,"facing":1.4313591016628469,"progress":11.0,"target":-1,"hits":0,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":36,"kind":"monster","team":0,"lane":"bot","zone":"lane","slot":-1,"uid":"","def":"e03","alive":true,"hp":570.0,"max_hp":570.0,"shield":0.0,"x":-11.322441101074219,"y":25.77979278564453,"facing":1.5004101357551378,"progress":9.6,"target":-1,"hits":0,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":37,"kind":"monster","team":0,"lane":"bot","zone":"lane","slot":-1,"uid":"","def":"e06","alive":true,"hp":722.0,"max_hp":722.0,"shield":0.0,"x":-11.413867950439453,"y":27.076574325561523,"facing":1.5004101357551378,"progress":9.6,"target":-1,"hits":0,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":38,"kind":"monster","team":0,"lane":"bot","zone":"lane","slot":-1,"uid":"","def":"e04","alive":true,"hp":494.00000000000006,"max_hp":494.00000000000006,"shield":0.0,"x":-11.505294799804688,"y":28.373355865478516,"facing":1.5004101357551378,"progress":9.6,"target":-1,"hits":0,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":39,"kind":"monster","team":0,"lane":"bot","zone":"lane","slot":-1,"uid":"","def":"e03","alive":true,"hp":570.0,"max_hp":570.0,"shield":0.0,"x":-12.82339096069336,"y":25.702985763549805,"facing":1.5802071320513056,"progress":8.2,"target":-1,"hits":0,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":40,"kind":"monster","team":1,"lane":"top","zone":"lane","slot":-1,"uid":"","def":"e05","alive":true,"hp":1824.0000000000002,"max_hp":1824.0000000000002,"shield":0.0,"x":10.502157211303711,"y":-28.243892669677734,"facing":-1.8482697410882951,"progress":11.0,"target":-1,"hits":0,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":41,"kind":"monster","team":1,"lane":"top","zone":"lane","slot":-1,"uid":"","def":"e01","alive":true,"hp":342.0,"max_hp":342.0,"shield":0.0,"x":10.146052360534668,"y":-26.993616104125977,"facing":-1.8482697410882951,"progress":11.0,"target":-1,"hits":0,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":42,"kind":"monster","team":1,"lane":"top","zone":"lane","slot":-1,"uid":"","def":"e02","alive":true,"hp":912.0000000000001,"max_hp":912.0000000000001,"shield":0.0,"x":9.789947509765625,"y":-25.74333953857422,"facing":-1.8482697410882951,"progress":11.0,"target":-1,"hits":0,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":43,"kind":"monster","team":1,"lane":"top","zone":"lane","slot":-1,"uid":"","def":"e03","alive":true,"hp":570.0,"max_hp":570.0,"shield":0.0,"x":11.702203750610352,"y":-27.921968460083008,"facing":-1.7280144162750581,"progress":9.6,"target":-1,"hits":0,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":44,"kind":"monster","team":1,"lane":"top","zone":"lane","slot":-1,"uid":"","def":"e06","alive":true,"hp":722.0,"max_hp":722.0,"shield":0.0,"x":11.498661041259766,"y":-26.638002395629883,"facing":-1.7280144162750581,"progress":9.6,"target":-1,"hits":0,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":45,"kind":"monster","team":1,"lane":"top","zone":"lane","slot":-1,"uid":"","def":"e04","alive":true,"hp":494.00000000000006,"max_hp":494.00000000000006,"shield":0.0,"x":11.29511833190918,"y":-25.354036331176758,"facing":-1.7280144162750581,"progress":9.6,"target":-1,"hits":0,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":46,"kind":"monster","team":1,"lane":"top","zone":"lane","slot":-1,"uid":"","def":"e03","alive":true,"hp":570.0,"max_hp":570.0,"shield":0.0,"x":13.08493709564209,"y":-27.702768325805664,"facing":-1.7280144162750581,"progress":8.2,"target":-1,"hits":0,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":47,"kind":"monster","team":1,"lane":"mid","zone":"lane","slot":-1,"uid":"","def":"e05","alive":true,"hp":1824.0000000000002,"max_hp":1824.0000000000002,"shield":0.0,"x":13.32747745513916,"y":-14.408708572387695,"facing":-0.816203910467337,"progress":11.0,"target":-1,"hits":0,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":48,"kind":"monster","team":1,"lane":"mid","zone":"lane","slot":-1,"uid":"","def":"e01","alive":true,"hp":342.0,"max_hp":342.0,"shield":0.0,"x":14.21796703338623,"y":-13.461592674255371,"facing":-0.816203910467337,"progress":11.0,"target":-1,"hits":0,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":49,"kind":"monster","team":1,"lane":"mid","zone":"lane","slot":-1,"uid":"","def":"e02","alive":true,"hp":912.0000000000001,"max_hp":912.0000000000001,"shield":0.0,"x":15.1084566116333,"y":-12.514476776123047,"facing":-0.816203910467337,"progress":11.0,"target":-1,"hits":0,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":50,"kind":"monster","team":1,"lane":"mid","zone":"lane","slot":-1,"uid":"","def":"e03","alive":true,"hp":570.0,"max_hp":570.0,"shield":0.0,"x":14.327392578125,"y":-15.366670608520508,"facing":-0.804482024713819,"progress":9.6,"target":-1,"hits":0,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":51,"kind":"monster","team":1,"lane":"mid","zone":"lane","slot":-1,"uid":"","def":"e06","alive":true,"hp":722.0,"max_hp":722.0,"shield":0.0,"x":15.228922843933105,"y":-14.430057525634766,"facing":-0.804482024713819,"progress":9.6,"target":-1,"hits":0,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":52,"kind":"monster","team":1,"lane":"mid","zone":"lane","slot":-1,"uid":"","def":"e04","alive":true,"hp":494.00000000000006,"max_hp":494.00000000000006,"shield":0.0,"x":16.13045310974121,"y":-13.493444442749023,"facing":-0.804482024713819,"progress":9.6,"target":-1,"hits":0,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":53,"kind":"monster","team":1,"lane":"mid","zone":"lane","slot":-1,"uid":"","def":"e03","alive":true,"hp":570.0,"max_hp":570.0,"shield":0.0,"x":15.30062484741211,"y":-16.32254409790039,"facing":-0.7769904424843075,"progress":8.2,"target":-1,"hits":0,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":54,"kind":"monster","team":1,"lane":"bot","zone":"lane","slot":-1,"uid":"","def":"e05","alive":true,"hp":1824.0000000000002,"max_hp":1824.0000000000002,"shield":0.0,"x":25.94097137451172,"y":-9.842267036437988,"facing":0.13943722513204979,"progress":11.0,"target":-1,"hits":0,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":55,"kind":"monster","team":1,"lane":"bot","zone":"lane","slot":-1,"uid":"","def":"e01","alive":true,"hp":342.0,"max_hp":342.0,"shield":0.0,"x":27.22835350036621,"y":-10.022948265075684,"facing":0.13943722513204979,"progress":11.0,"target":-1,"hits":0,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":56,"kind":"monster","team":1,"lane":"bot","zone":"lane","slot":-1,"uid":"","def":"e02","alive":true,"hp":912.0000000000001,"max_hp":912.0000000000001,"shield":0.0,"x":28.515735626220703,"y":-10.203629493713379,"facing":0.13943722513204979,"progress":11.0,"target":-1,"hits":0,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":57,"kind":"monster","team":1,"lane":"bot","zone":"lane","slot":-1,"uid":"","def":"e03","alive":true,"hp":570.0,"max_hp":570.0,"shield":0.0,"x":25.77979278564453,"y":-11.322441101074219,"facing":0.07038619103975874,"progress":9.6,"target":-1,"hits":0,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":58,"kind":"monster","team":1,"lane":"bot","zone":"lane","slot":-1,"uid":"","def":"e06","alive":true,"hp":722.0,"max_hp":722.0,"shield":0.0,"x":27.076574325561523,"y":-11.413867950439453,"facing":0.07038619103975874,"progress":9.6,"target":-1,"hits":0,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":59,"kind":"monster","team":1,"lane":"bot","zone":"lane","slot":-1,"uid":"","def":"e04","alive":true,"hp":494.00000000000006,"max_hp":494.00000000000006,"shield":0.0,"x":28.373355865478516,"y":-11.505294799804688,"facing":0.07038619103975874,"progress":9.6,"target":-1,"hits":0,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":60,"kind":"monster","team":1,"lane":"bot","zone":"lane","slot":-1,"uid":"","def":"e03","alive":true,"hp":570.0,"max_hp":570.0,"shield":0.0,"x":25.702985763549805,"y":-12.82339096069336,"facing":-0.009410805256408956,"progress":8.2,"target":-1,"hits":0,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":61,"kind":"troop","team":0,"lane":"top","zone":"lane","slot":0,"uid":"p0-4","def":"w04","alive":true,"hp":1560.0,"max_hp":1560.0,"shield":0.0,"x":-28.204208374023438,"y":13.871247291564941,"facing":3.1367842018723553,"progress":7.2,"target":-1,"hits":0,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":62,"kind":"troop","team":0,"lane":"top","zone":"lane","slot":0,"uid":"p0-10","def":"w04","alive":true,"hp":1560.0,"max_hp":1560.0,"shield":0.0,"x":-27.004222869873047,"y":13.877017974853516,"facing":3.1367842018723553,"progress":7.2,"target":-1,"hits":0,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":63,"kind":"troop","team":0,"lane":"top","zone":"lane","slot":0,"uid":"p0-12","def":"w04","alive":true,"hp":1560.0,"max_hp":1560.0,"shield":0.0,"x":-25.804237365722656,"y":13.882787704467773,"facing":3.1367842018723553,"progress":7.2,"target":-1,"hits":0,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":64,"kind":"troop","team":0,"lane":"top","zone":"lane","slot":0,"uid":"p0-7","def":"w02","alive":true,"hp":800.0,"max_hp":800.0,"shield":0.0,"x":-24.604251861572266,"y":13.888558387756348,"facing":3.1367842018723553,"progress":7.2,"target":-1,"hits":0,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":65,"kind":"troop","team":0,"lane":"top","zone":"lane","slot":0,"uid":"p0-5","def":"w08","alive":true,"hp":940.0,"max_hp":940.0,"shield":0.0,"x":-28.275205612182617,"y":15.179800033569336,"facing":3.032574735520727,"progress":5.7,"target":-1,"hits":0,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":66,"kind":"troop","team":0,"lane":"top","zone":"lane","slot":0,"uid":"p0-13","def":"w08","alive":true,"hp":940.0,"max_hp":940.0,"shield":0.0,"x":-27.08232879638672,"y":15.310362815856934,"facing":3.032574735520727,"progress":5.7,"target":-1,"hits":0,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":67,"kind":"hero","team":0,"lane":"top","zone":"lane","slot":0,"uid":"h0-1","def":"g05","alive":true,"hp":950.0,"max_hp":950.0,"shield":0.0,"x":-25.889453887939453,"y":15.440924644470215,"facing":3.032574735520727,"progress":5.7,"target":-1,"hits":0,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":68,"kind":"troop","team":0,"lane":"top","zone":"lane","slot":0,"uid":"p0-3","def":"w06","alive":true,"hp":630.0,"max_hp":630.0,"shield":0.0,"x":-24.696577072143555,"y":15.571487426757813,"facing":3.032574735520727,"progress":5.7,"target":-1,"hits":0,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":69,"kind":"troop","team":0,"lane":"top","zone":"lane","slot":0,"uid":"p0-6","def":"w06","alive":true,"hp":630.0,"max_hp":630.0,"shield":0.0,"x":-28.459529876708984,"y":16.555438995361328,"facing":2.9706865018772874,"progress":4.2,"target":-1,"hits":0,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":70,"kind":"troop","team":0,"lane":"top","zone":"lane","slot":0,"uid":"p0-9","def":"w06","alive":true,"hp":630.0,"max_hp":630.0,"shield":0.0,"x":-27.277013778686523,"y":16.75952911376953,"facing":2.9706865018772874,"progress":4.2,"target":-1,"hits":0,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":71,"kind":"troop","team":0,"lane":"top","zone":"lane","slot":0,"uid":"p0-11","def":"w06","alive":true,"hp":630.0,"max_hp":630.0,"shield":0.0,"x":-26.09449577331543,"y":16.963619232177734,"facing":2.9706865018772874,"progress":4.2,"target":-1,"hits":0,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":72,"kind":"troop","team":0,"lane":"top","zone":"lane","slot":0,"uid":"p0-14","def":"w06","alive":true,"hp":630.0,"max_hp":630.0,"shield":0.0,"x":-24.91197967529297,"y":17.167709350585938,"facing":2.9706865018772874,"progress":4.2,"target":-1,"hits":0,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":73,"kind":"troop","team":0,"lane":"top","zone":"lane","slot":0,"uid":"p0-8","def":"w10","alive":true,"hp":1000.0,"max_hp":1000.0,"shield":0.0,"x":-28.717323303222656,"y":18.004432678222656,"facing":2.9550143493540855,"progress":2.7,"target":-1,"hits":0,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":74,"kind":"troop","team":0,"lane":"mid","zone":"lane","slot":1,"uid":"p1-3","def":"g04","alive":true,"hp":1650.0,"max_hp":1650.0,"shield":0.0,"x":-17.386140823364258,"y":15.645247459411621,"facing":2.347786769279204,"progress":7.2,"target":-1,"hits":0,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":75,"kind":"troop","team":0,"lane":"mid","zone":"lane","slot":1,"uid":"p1-7","def":"g04","alive":true,"hp":1650.0,"max_hp":1650.0,"shield":0.0,"x":-16.544776916503906,"y":16.500879287719727,"facing":2.347786769279204,"progress":7.2,"target":-1,"hits":0,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":76,"kind":"troop","team":0,"lane":"mid","zone":"lane","slot":1,"uid":"p1-11","def":"g04","alive":true,"hp":1650.0,"max_hp":1650.0,"shield":0.0,"x":-15.703412055969238,"y":17.35651206970215,"facing":2.347786769279204,"progress":7.2,"target":-1,"hits":0,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":77,"kind":"troop","team":0,"lane":"mid","zone":"lane","slot":1,"uid":"p1-14","def":"g04","alive":true,"hp":1650.0,"max_hp":1650.0,"shield":0.0,"x":-14.862048149108887,"y":18.21214485168457,"facing":2.347786769279204,"progress":7.2,"target":-1,"hits":0,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":78,"kind":"troop","team":0,"lane":"mid","zone":"lane","slot":1,"uid":"p1-5","def":"g02","alive":true,"hp":690.0,"max_hp":690.0,"shield":0.0,"x":-18.432058334350586,"y":16.60871696472168,"facing":2.3046223302823,"progress":5.7,"target":-1,"hits":0,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":79,"kind":"troop","team":0,"lane":"mid","zone":"lane","slot":1,"uid":"p1-10","def":"g02","alive":true,"hp":690.0,"max_hp":690.0,"shield":0.0,"x":-17.628398895263672,"y":17.499858856201172,"facing":2.3046223302823,"progress":5.7,"target":-1,"hits":0,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":80,"kind":"troop","team":0,"lane":"mid","zone":"lane","slot":1,"uid":"p1-8","def":"g08","alive":true,"hp":820.0,"max_hp":820.0,"shield":0.0,"x":-16.82474136352539,"y":18.39099884033203,"facing":2.3046223302823,"progress":5.7,"target":-1,"hits":0,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":81,"kind":"troop","team":0,"lane":"mid","zone":"lane","slot":1,"uid":"p1-4","def":"g06","alive":true,"hp":640.0,"max_hp":640.0,"shield":0.0,"x":-16.021081924438477,"y":19.282140731811523,"facing":2.3046223302823,"progress":5.7,"target":-1,"hits":0,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":82,"kind":"troop","team":0,"lane":"mid","zone":"lane","slot":1,"uid":"p1-9","def":"g06","alive":true,"hp":640.0,"max_hp":640.0,"shield":0.0,"x":-19.51742935180664,"y":17.549461364746094,"facing":2.2693727388192086,"progress":4.2,"target":-1,"hits":0,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":83,"kind":"troop","team":0,"lane":"mid","zone":"lane","slot":1,"uid":"p1-12","def":"g06","alive":true,"hp":640.0,"max_hp":640.0,"shield":0.0,"x":-18.745676040649414,"y":18.46837043762207,"facing":2.2693727388192086,"progress":4.2,"target":-1,"hits":0,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":84,"kind":"hero","team":0,"lane":"mid","zone":"lane","slot":1,"uid":"h1-1","def":"w10","alive":true,"hp":1300.0,"max_hp":1300.0,"shield":0.0,"x":-17.973920822143555,"y":19.38728141784668,"facing":2.2693727388192086,"progress":4.2,"target":-1,"hits":0,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":85,"kind":"troop","team":0,"lane":"mid","zone":"lane","slot":1,"uid":"p1-6","def":"g10","alive":true,"hp":1080.0,"max_hp":1080.0,"shield":0.0,"x":-17.202167510986328,"y":20.306190490722656,"facing":2.2693727388192086,"progress":4.2,"target":-1,"hits":0,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":86,"kind":"troop","team":0,"lane":"mid","zone":"lane","slot":1,"uid":"p1-13","def":"g10","alive":true,"hp":1080.0,"max_hp":1080.0,"shield":0.0,"x":-20.651277542114258,"y":18.48939323425293,"facing":2.25427556049323,"progress":2.7,"target":-1,"hits":0,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":87,"kind":"hero","team":0,"lane":"bot","zone":"lane","slot":2,"uid":"h2-1","def":"w04","alive":true,"hp":2200.0,"max_hp":2200.0,"shield":0.0,"x":-13.828052520751953,"y":25.212417602539063,"facing":1.5802071320513056,"progress":7.2,"target":-1,"hits":0,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":88,"kind":"troop","team":0,"lane":"bot","zone":"lane","slot":2,"uid":"p2-3","def":"w04","alive":true,"hp":1560.0,"max_hp":1560.0,"shield":0.0,"x":-13.816760063171387,"y":26.412364959716797,"facing":1.5802071320513056,"progress":7.2,"target":-1,"hits":0,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":89,"kind":"troop","team":0,"lane":"bot","zone":"lane","slot":2,"uid":"p2-6","def":"w04","alive":true,"hp":1560.0,"max_hp":1560.0,"shield":0.0,"x":-13.805466651916504,"y":27.61231231689453,"facing":1.5802071320513056,"progress":7.2,"target":-1,"hits":0,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":90,"kind":"troop","team":0,"lane":"bot","zone":"lane","slot":2,"uid":"p2-10","def":"w04","alive":true,"hp":1560.0,"max_hp":1560.0,"shield":0.0,"x":-13.794174194335938,"y":28.812259674072266,"facing":1.5802071320513056,"progress":7.2,"target":-1,"hits":0,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":91,"kind":"troop","team":0,"lane":"bot","zone":"lane","slot":2,"uid":"p2-12","def":"w04","alive":true,"hp":1560.0,"max_hp":1560.0,"shield":0.0,"x":-15.38626766204834,"y":25.26462745666504,"facing":1.6131242713551097,"progress":5.7,"target":-1,"hits":0,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":92,"kind":"troop","team":0,"lane":"bot","zone":"lane","slot":2,"uid":"p2-4","def":"w02","alive":true,"hp":800.0,"max_hp":800.0,"shield":0.0,"x":-15.335489273071289,"y":26.463552474975586,"facing":1.6131242713551097,"progress":5.7,"target":-1,"hits":0,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":93,"kind":"troop","team":0,"lane":"bot","zone":"lane","slot":2,"uid":"p2-9","def":"w02","alive":true,"hp":800.0,"max_hp":800.0,"shield":0.0,"x":-15.284711837768555,"y":27.662477493286133,"facing":1.6131242713551097,"progress":5.7,"target":-1,"hits":0,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":94,"kind":"troop","team":0,"lane":"bot","zone":"lane","slot":2,"uid":"p2-13","def":"w02","alive":true,"hp":800.0,"max_hp":800.0,"shield":0.0,"x":-15.233933448791504,"y":28.86140251159668,"facing":1.6131242713551097,"progress":5.7,"target":-1,"hits":0,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":95,"kind":"troop","team":0,"lane":"bot","zone":"lane","slot":2,"uid":"p2-7","def":"w08","alive":true,"hp":940.0,"max_hp":940.0,"shield":0.0,"x":-16.917787551879883,"y":25.346899032592773,"facing":1.631896672658701,"progress":4.2,"target":-1,"hits":0,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":96,"kind":"troop","team":0,"lane":"bot","zone":"lane","slot":2,"uid":"p2-5","def":"w06","alive":true,"hp":630.0,"max_hp":630.0,"shield":0.0,"x":-16.844512939453125,"y":26.544658660888672,"facing":1.631896672658701,"progress":4.2,"target":-1,"hits":0,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":97,"kind":"troop","team":0,"lane":"bot","zone":"lane","slot":2,"uid":"p2-11","def":"w06","alive":true,"hp":630.0,"max_hp":630.0,"shield":0.0,"x":-16.771236419677734,"y":27.742420196533203,"facing":1.631896672658701,"progress":4.2,"target":-1,"hits":0,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":98,"kind":"troop","team":0,"lane":"bot","zone":"lane","slot":2,"uid":"p2-14","def":"w06","alive":true,"hp":630.0,"max_hp":630.0,"shield":0.0,"x":-16.697961807250977,"y":28.9401798248291,"facing":1.631896672658701,"progress":4.2,"target":-1,"hits":0,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":99,"kind":"troop","team":0,"lane":"bot","zone":"lane","slot":2,"uid":"p2-8","def":"w10","alive":true,"hp":1000.0,"max_hp":1000.0,"shield":0.0,"x":-18.423198699951172,"y":25.442331314086914,"facing":1.6365833636006222,"progress":2.7,"target":-1,"hits":0,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":100,"kind":"hero","team":1,"lane":"top","zone":"lane","slot":3,"uid":"h3-1","def":"w04","alive":true,"hp":2550.0,"max_hp":2550.0,"shield":0.0,"x":13.871247291564941,"y":-28.204208374023438,"facing":-1.5659878750774585,"progress":7.2,"target":-1,"hits":0,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":101,"kind":"troop","team":1,"lane":"top","zone":"lane","slot":3,"uid":"p3-2","def":"g04","alive":true,"hp":1650.0,"max_hp":1650.0,"shield":0.0,"x":13.877017974853516,"y":-27.004222869873047,"facing":-1.5659878750774585,"progress":7.2,"target":-1,"hits":0,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":102,"kind":"troop","team":1,"lane":"top","zone":"lane","slot":3,"uid":"p3-6","def":"g04","alive":true,"hp":1650.0,"max_hp":1650.0,"shield":0.0,"x":13.882787704467773,"y":-25.804237365722656,"facing":-1.5659878750774585,"progress":7.2,"target":-1,"hits":0,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":103,"kind":"troop","team":1,"lane":"top","zone":"lane","slot":3,"uid":"p3-10","def":"g04","alive":true,"hp":1650.0,"max_hp":1650.0,"shield":0.0,"x":13.888558387756348,"y":-24.604251861572266,"facing":-1.5659878750774585,"progress":7.2,"target":-1,"hits":0,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":104,"kind":"troop","team":1,"lane":"top","zone":"lane","slot":3,"uid":"p3-13","def":"g04","alive":true,"hp":1650.0,"max_hp":1650.0,"shield":0.0,"x":15.179800033569336,"y":-28.275205612182617,"facing":-1.4617784087258303,"progress":5.7,"target":-1,"hits":0,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":105,"kind":"troop","team":1,"lane":"top","zone":"lane","slot":3,"uid":"p3-3","def":"g02","alive":true,"hp":690.0,"max_hp":690.0,"shield":0.0,"x":15.310362815856934,"y":-27.08232879638672,"facing":-1.4617784087258303,"progress":5.7,"target":-1,"hits":0,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":106,"kind":"troop","team":1,"lane":"top","zone":"lane","slot":3,"uid":"p3-8","def":"g02","alive":true,"hp":690.0,"max_hp":690.0,"shield":0.0,"x":15.440924644470215,"y":-25.889453887939453,"facing":-1.4617784087258303,"progress":5.7,"target":-1,"hits":0,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":107,"kind":"troop","team":1,"lane":"top","zone":"lane","slot":3,"uid":"p3-11","def":"g02","alive":true,"hp":690.0,"max_hp":690.0,"shield":0.0,"x":15.571487426757813,"y":-24.696577072143555,"facing":-1.4617784087258303,"progress":5.7,"target":-1,"hits":0,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":108,"kind":"troop","team":1,"lane":"top","zone":"lane","slot":3,"uid":"p3-5","def":"g08","alive":true,"hp":820.0,"max_hp":820.0,"shield":0.0,"x":16.555438995361328,"y":-28.459529876708984,"facing":-1.3998901750823909,"progress":4.2,"target":-1,"hits":0,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":109,"kind":"troop","team":1,"lane":"top","zone":"lane","slot":3,"uid":"p3-4","def":"g06","alive":true,"hp":640.0,"max_hp":640.0,"shield":0.0,"x":16.75952911376953,"y":-27.277013778686523,"facing":-1.3998901750823909,"progress":4.2,"target":-1,"hits":0,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":110,"kind":"troop","team":1,"lane":"top","zone":"lane","slot":3,"uid":"p3-9","def":"g06","alive":true,"hp":640.0,"max_hp":640.0,"shield":0.0,"x":16.963619232177734,"y":-26.09449577331543,"facing":-1.3998901750823909,"progress":4.2,"target":-1,"hits":0,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":111,"kind":"troop","team":1,"lane":"top","zone":"lane","slot":3,"uid":"p3-12","def":"g06","alive":true,"hp":640.0,"max_hp":640.0,"shield":0.0,"x":17.167709350585938,"y":-24.91197967529297,"facing":-1.3998901750823909,"progress":4.2,"target":-1,"hits":0,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":112,"kind":"troop","team":1,"lane":"top","zone":"lane","slot":3,"uid":"p3-7","def":"g10","alive":true,"hp":1080.0,"max_hp":1080.0,"shield":0.0,"x":18.004432678222656,"y":-28.717323303222656,"facing":-1.3842180225591887,"progress":2.7,"target":-1,"hits":0,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":113,"kind":"hero","team":1,"lane":"mid","zone":"lane","slot":4,"uid":"h4-1","def":"w04","alive":true,"hp":2550.0,"max_hp":2550.0,"shield":0.0,"x":15.645247459411621,"y":-17.386140823364258,"facing":-0.7769904424843075,"progress":7.2,"target":-1,"hits":0,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":114,"kind":"troop","team":1,"lane":"mid","zone":"lane","slot":4,"uid":"p4-3","def":"w04","alive":true,"hp":1560.0,"max_hp":1560.0,"shield":0.0,"x":16.500879287719727,"y":-16.544776916503906,"facing":-0.7769904424843075,"progress":7.2,"target":-1,"hits":0,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":115,"kind":"troop","team":1,"lane":"mid","zone":"lane","slot":4,"uid":"p4-6","def":"w04","alive":true,"hp":1560.0,"max_hp":1560.0,"shield":0.0,"x":17.35651206970215,"y":-15.703412055969238,"facing":-0.7769904424843075,"progress":7.2,"target":-1,"hits":0,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":116,"kind":"troop","team":1,"lane":"mid","zone":"lane","slot":4,"uid":"p4-10","def":"w04","alive":true,"hp":1560.0,"max_hp":1560.0,"shield":0.0,"x":18.21214485168457,"y":-14.862048149108887,"facing":-0.7769904424843075,"progress":7.2,"target":-1,"hits":0,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":117,"kind":"troop","team":1,"lane":"mid","zone":"lane","slot":4,"uid":"p4-12","def":"w04","alive":true,"hp":1560.0,"max_hp":1560.0,"shield":0.0,"x":16.60871696472168,"y":-18.432058334350586,"facing":-0.7338260034874031,"progress":5.7,"target":-1,"hits":0,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":118,"kind":"troop","team":1,"lane":"mid","zone":"lane","slot":4,"uid":"p4-5","def":"w02","alive":true,"hp":800.0,"max_hp":800.0,"shield":0.0,"x":17.499858856201172,"y":-17.628398895263672,"facing":-0.7338260034874031,"progress":5.7,"target":-1,"hits":0,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":119,"kind":"troop","team":1,"lane":"mid","zone":"lane","slot":4,"uid":"p4-11","def":"w02","alive":true,"hp":800.0,"max_hp":800.0,"shield":0.0,"x":18.39099884033203,"y":-16.82474136352539,"facing":-0.7338260034874031,"progress":5.7,"target":-1,"hits":0,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":120,"kind":"troop","team":1,"lane":"mid","zone":"lane","slot":4,"uid":"p4-14","def":"w02","alive":true,"hp":800.0,"max_hp":800.0,"shield":0.0,"x":19.282140731811523,"y":-16.021081924438477,"facing":-0.7338260034874031,"progress":5.7,"target":-1,"hits":0,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":121,"kind":"troop","team":1,"lane":"mid","zone":"lane","slot":4,"uid":"p4-7","def":"w08","alive":true,"hp":940.0,"max_hp":940.0,"shield":0.0,"x":17.549461364746094,"y":-19.51742935180664,"facing":-0.6985764120243119,"progress":4.2,"target":-1,"hits":0,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":122,"kind":"troop","team":1,"lane":"mid","zone":"lane","slot":4,"uid":"p4-4","def":"w06","alive":true,"hp":630.0,"max_hp":630.0,"shield":0.0,"x":18.46837043762207,"y":-18.745676040649414,"facing":-0.6985764120243119,"progress":4.2,"target":-1,"hits":0,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":123,"kind":"troop","team":1,"lane":"mid","zone":"lane","slot":4,"uid":"p4-9","def":"w06","alive":true,"hp":630.0,"max_hp":630.0,"shield":0.0,"x":19.38728141784668,"y":-17.973920822143555,"facing":-0.6985764120243119,"progress":4.2,"target":-1,"hits":0,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":124,"kind":"troop","team":1,"lane":"mid","zone":"lane","slot":4,"uid":"p4-13","def":"w06","alive":true,"hp":630.0,"max_hp":630.0,"shield":0.0,"x":20.306190490722656,"y":-17.202167510986328,"facing":-0.6985764120243119,"progress":4.2,"target":-1,"hits":0,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":125,"kind":"troop","team":1,"lane":"mid","zone":"lane","slot":4,"uid":"p4-8","def":"w10","alive":true,"hp":1000.0,"max_hp":1000.0,"shield":0.0,"x":18.48939323425293,"y":-20.651277542114258,"facing":-0.683479233698333,"progress":2.7,"target":-1,"hits":0,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":126,"kind":"troop","team":1,"lane":"bot","zone":"lane","slot":5,"uid":"p5-5","def":"g04","alive":true,"hp":1650.0,"max_hp":1650.0,"shield":0.0,"x":25.212417602539063,"y":-13.828052520751953,"facing":-0.009410805256408956,"progress":7.2,"target":-1,"hits":0,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":127,"kind":"troop","team":1,"lane":"bot","zone":"lane","slot":5,"uid":"p5-10","def":"g04","alive":true,"hp":1650.0,"max_hp":1650.0,"shield":0.0,"x":26.412364959716797,"y":-13.816760063171387,"facing":-0.009410805256408956,"progress":7.2,"target":-1,"hits":0,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":128,"kind":"troop","team":1,"lane":"bot","zone":"lane","slot":5,"uid":"p5-3","def":"g02","alive":true,"hp":690.0,"max_hp":690.0,"shield":0.0,"x":27.61231231689453,"y":-13.805466651916504,"facing":-0.009410805256408956,"progress":7.2,"target":-1,"hits":0,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":129,"kind":"troop","team":1,"lane":"bot","zone":"lane","slot":5,"uid":"p5-7","def":"g02","alive":true,"hp":690.0,"max_hp":690.0,"shield":0.0,"x":28.812259674072266,"y":-13.794174194335938,"facing":-0.009410805256408956,"progress":7.2,"target":-1,"hits":0,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":130,"kind":"troop","team":1,"lane":"bot","zone":"lane","slot":5,"uid":"p5-9","def":"g02","alive":true,"hp":690.0,"max_hp":690.0,"shield":0.0,"x":25.26462745666504,"y":-15.38626766204834,"facing":-0.04232794456021306,"progress":5.7,"target":-1,"hits":0,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":131,"kind":"troop","team":1,"lane":"bot","zone":"lane","slot":5,"uid":"p5-12","def":"g02","alive":true,"hp":690.0,"max_hp":690.0,"shield":0.0,"x":26.463552474975586,"y":-15.335489273071289,"facing":-0.04232794456021306,"progress":5.7,"target":-1,"hits":0,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":132,"kind":"troop","team":1,"lane":"bot","zone":"lane","slot":5,"uid":"p5-6","def":"g08","alive":true,"hp":820.0,"max_hp":820.0,"shield":0.0,"x":27.662477493286133,"y":-15.284711837768555,"facing":-0.04232794456021306,"progress":5.7,"target":-1,"hits":0,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":133,"kind":"troop","team":1,"lane":"bot","zone":"lane","slot":5,"uid":"p5-14","def":"g08","alive":true,"hp":820.0,"max_hp":820.0,"shield":0.0,"x":28.86140251159668,"y":-15.233933448791504,"facing":-0.04232794456021306,"progress":5.7,"target":-1,"hits":0,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":134,"kind":"hero","team":1,"lane":"bot","zone":"lane","slot":5,"uid":"h5-1","def":"g05","alive":true,"hp":950.0,"max_hp":950.0,"shield":0.0,"x":25.346899032592773,"y":-16.917787551879883,"facing":-0.06110034586380431,"progress":4.2,"target":-1,"hits":0,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":135,"kind":"troop","team":1,"lane":"bot","zone":"lane","slot":5,"uid":"p5-4","def":"g06","alive":true,"hp":640.0,"max_hp":640.0,"shield":0.0,"x":26.544658660888672,"y":-16.844512939453125,"facing":-0.06110034586380431,"progress":4.2,"target":-1,"hits":0,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":136,"kind":"troop","team":1,"lane":"bot","zone":"lane","slot":5,"uid":"p5-8","def":"g06","alive":true,"hp":640.0,"max_hp":640.0,"shield":0.0,"x":27.742420196533203,"y":-16.771236419677734,"facing":-0.06110034586380431,"progress":4.2,"target":-1,"hits":0,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":137,"kind":"troop","team":1,"lane":"bot","zone":"lane","slot":5,"uid":"p5-13","def":"g06","alive":true,"hp":640.0,"max_hp":640.0,"shield":0.0,"x":28.9401798248291,"y":-16.697961807250977,"facing":-0.06110034586380431,"progress":4.2,"target":-1,"hits":0,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":138,"kind":"troop","team":1,"lane":"bot","zone":"lane","slot":5,"uid":"p5-11","def":"g10","alive":true,"hp":1080.0,"max_hp":1080.0,"shield":0.0,"x":25.442331314086914,"y":-18.423198699951172,"facing":-0.06578703680572556,"progress":2.7,"target":-1,"hits":0,"reached":false,"dormant":false,"effects":[],"dots":[]}],"wave":[["e05",1824.0000000000002,48.00000000000001,36],["e01",342.0,18.000000000000004,11],["e02",912.0000000000001,27.000000000000004,22],["e03",570.0,33.00000000000001,18],["e06",722.0,21.000000000000004,22],["e04",494.00000000000006,36.00000000000001,18],["e03",570.0,33.00000000000001,18]]},{"label":"t20","phase":1,"round":21,"winner":-2,"end_note":"","players":[{"gold":935,"draft_gold":935,"ready":true,"earned":0,"spent":0,"next_seq":15,"roster":["p0-3|w06|top|195","p0-4|w04|top|230","p0-5|w08|top|295","p0-6|w06|top|195","p0-7|w02|top|150","p0-8|w10|top|270","p0-9|w06|top|195","p0-10|w04|top|230","p0-11|w06|top|195","p0-12|w04|top|230","p0-13|w08|top|295","p0-14|w06|top|195"],"hero":"h0-1|held_funkenlanze|0|top|funkenfokus||260|false|","bookings":["c0-2|ch_druck|top|150|22"],"new_bookings":["c0-2|ch_druck|top|150"],"draft_roster":["p0-3|w06|top|195|true","p0-4|w04|top|230|true","p0-5|w08|top|295|true","p0-6|w06|top|195|true","p0-7|w02|top|150|true","p0-8|w10|top|270|true","p0-9|w06|top|195|true","p0-10|w04|top|230|true","p0-11|w06|top|195|true","p0-12|w04|top|230|true","p0-13|w08|top|295|true","p0-14|w06|top|195|true"],"draft_hero":"h0-1|held_funkenlanze|0|top|funkenfokus||260|true|funkenfokus","boss_lane":"","undo":0},{"gold":1030,"draft_gold":1030,"ready":true,"earned":0,"spent":0,"next_seq":15,"roster":["p1-3|g04|mid|220","p1-4|g06|mid|205","p1-5|g02|mid|135","p1-6|g10|mid|255","p1-7|g04|mid|220","p1-8|g08|mid|285","p1-9|g06|mid|205","p1-10|g02|mid|135","p1-11|g04|mid|220","p1-12|g06|mid|205","p1-13|g10|mid|255","p1-14|g04|mid|220"],"hero":"h1-1|held_quellgeflecht|0|mid|quellamulett||260|false|","bookings":["c1-2|ch_schutz|mid|150|22"],"new_bookings":["c1-2|ch_schutz|mid|150"],"draft_roster":["p1-3|g04|mid|220|true","p1-4|g06|mid|205|true","p1-5|g02|mid|135|true","p1-6|g10|mid|255|true","p1-7|g04|mid|220|true","p1-8|g08|mid|285|true","p1-9|g06|mid|205|true","p1-10|g02|mid|135|true","p1-11|g04|mid|220|true","p1-12|g06|mid|205|true","p1-13|g10|mid|255|true","p1-14|g04|mid|220|true"],"draft_hero":"h1-1|held_quellgeflecht|0|mid|quellamulett||260|true|quellamulett","boss_lane":"","undo":0},{"gold":1080,"draft_gold":1080,"ready":true,"earned":0,"spent":0,"next_seq":15,"roster":["p2-3|w04|bot|230","p2-4|w02|bot|150","p2-5|w06|bot|195","p2-6|w04|bot|230","p2-7|w08|bot|295","p2-8|w10|bot|270","p2-9|w02|bot|150","p2-10|w04|bot|230","p2-11|w06|bot|195","p2-12|w04|bot|230","p2-13|w02|bot|150","p2-14|w06|bot|195"],"hero":"h2-1|held_ringborke|0|bot|glutklinge||260|false|","bookings":["c2-2|ch_belagerung|bot|180|22"],"new_bookings":["c2-2|ch_belagerung|bot|180"],"draft_roster":["p2-3|w04|bot|230|true","p2-4|w02|bot|150|true","p2-5|w06|bot|195|true","p2-6|w04|bot|230|true","p2-7|w08|bot|295|true","p2-8|w10|bot|270|true","p2-9|w02|bot|150|true","p2-10|w04|bot|230|true","p2-11|w06|bot|195|true","p2-12|w04|bot|230|true","p2-13|w02|bot|150|true","p2-14|w06|bot|195|true"],"draft_hero":"h2-1|held_ringborke|0|bot|glutklinge||260|true|glutklinge","boss_lane":"","undo":0},{"gold":1340,"draft_gold":1340,"ready":true,"earned":0,"spent":0,"next_seq":14,"roster":["p3-2|g04|top|220","p3-3|g02|top|135","p3-4|g06|top|205","p3-5|g08|top|285","p3-6|g04|top|220","p3-7|g10|top|255","p3-8|g02|top|135","p3-9|g06|top|205","p3-10|g04|top|220","p3-11|g02|top|135","p3-12|g06|top|205","p3-13|g04|top|220"],"hero":"h3-1|held_ringborke|0|top|basaltschild||260|false|","bookings":[],"new_bookings":[],"draft_roster":["p3-2|g04|top|220|true","p3-3|g02|top|135|true","p3-4|g06|top|205|true","p3-5|g08|top|285|true","p3-6|g04|top|220|true","p3-7|g10|top|255|true","p3-8|g02|top|135|true","p3-9|g06|top|205|true","p3-10|g04|top|220|true","p3-11|g02|top|135|true","p3-12|g06|top|205|true","p3-13|g04|top|220|true"],"draft_hero":"h3-1|held_ringborke|0|top|basaltschild||260|true|basaltschild","boss_lane":"","undo":0},{"gold":1110,"draft_gold":1110,"ready":true,"earned":0,"spent":0,"next_seq":15,"roster":["p4-3|w04|mid|230","p4-4|w06|mid|195","p4-5|w02|mid|150","p4-6|w04|mid|230","p4-7|w08|mid|295","p4-8|w10|mid|270","p4-9|w06|mid|195","p4-10|w04|mid|230","p4-11|w02|mid|150","p4-12|w04|mid|230","p4-13|w06|mid|195","p4-14|w02|mid|150"],"hero":"h4-1|held_ringborke|0|mid|basaltschild||260|false|","bookings":["c4-2|ch_schutz|mid|150|22"],"new_bookings":["c4-2|ch_schutz|mid|150"],"draft_roster":["p4-3|w04|mid|230|true","p4-4|w06|mid|195|true","p4-5|w02|mid|150|true","p4-6|w04|mid|230|true","p4-7|w08|mid|295|true","p4-8|w10|mid|270|true","p4-9|w06|mid|195|true","p4-10|w04|mid|230|true","p4-11|w02|mid|150|true","p4-12|w04|mid|230|true","p4-13|w06|mid|195|true","p4-14|w02|mid|150|true"],"draft_hero":"h4-1|held_ringborke|0|mid|basaltschild||260|true|basaltschild","boss_lane":"","undo":0},{"gold":1180,"draft_gold":1180,"ready":true,"earned":0,"spent":0,"next_seq":15,"roster":["p5-3|g02|bot|135","p5-4|g06|bot|205","p5-5|g04|bot|220","p5-6|g08|bot|285","p5-7|g02|bot|135","p5-8|g06|bot|205","p5-9|g02|bot|135","p5-10|g04|bot|220","p5-11|g10|bot|255","p5-12|g02|bot|135","p5-13|g06|bot|205","p5-14|g08|bot|285"],"hero":"h5-1|held_funkenlanze|0|bot|glutklinge||260|false|","bookings":["c5-2|ch_belagerung|bot|180|22"],"new_bookings":["c5-2|ch_belagerung|bot|180"],"draft_roster":["p5-3|g02|bot|135|true","p5-4|g06|bot|205|true","p5-5|g04|bot|220|true","p5-6|g08|bot|285|true","p5-7|g02|bot|135|true","p5-8|g06|bot|205|true","p5-9|g02|bot|135|true","p5-10|g04|bot|220|true","p5-11|g10|bot|255|true","p5-12|g02|bot|135|true","p5-13|g06|bot|205|true","p5-14|g08|bot|285|true"],"draft_hero":"h5-1|held_funkenlanze|0|bot|glutklinge||260|true|glutklinge","boss_lane":"","undo":0}],"buildings":[7500.0,6000.0,7500.0,6000.0,7500.0,6000.0,9000.0,9000.0,12000.0,7500.0,6000.0,7500.0,6000.0,7500.0,6000.0,9000.0,9000.0,12000.0],"boss":{"next":1,"settled":0,"claim":""},"boss_log":[],"announcements":[],"settlement":null,"combat":{"round":21,"steps":400,"elapsed":20.00000000000015,"finished":false,"end_reason":"","destroyed":[],"grotto":"none|-1|-1|true","grotto_boss":"","grotto_boss_hp":0.0,"events":28,"mobile":[47,45,0]},"units":[{"id":1,"kind":"tower","team":0,"lane":"top","zone":"lane","slot":-1,"uid":"","def":"blau_top_inner","alive":true,"hp":7500.0,"max_hp":7500.0,"shield":0.0,"x":-24.931251525878906,"y":4.5293378829956055,"facing":0.0,"progress":0.0,"target":-1,"hits":0,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":2,"kind":"tower","team":0,"lane":"top","zone":"lane","slot":-1,"uid":"","def":"blau_top_outer","alive":true,"hp":6000.0,"max_hp":6000.0,"shield":0.0,"x":-24.921451568603516,"y":-12.715348243713379,"facing":0.0,"progress":0.0,"target":-1,"hits":0,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":3,"kind":"tower","team":0,"lane":"mid","zone":"lane","slot":-1,"uid":"","def":"blau_mid_inner","alive":true,"hp":7500.0,"max_hp":7500.0,"shield":0.0,"x":-11.427590370178223,"y":17.012392044067383,"facing":0.0,"progress":0.0,"target":-1,"hits":0,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":4,"kind":"tower","team":0,"lane":"mid","zone":"lane","slot":-1,"uid":"","def":"blau_mid_outer","alive":true,"hp":6000.0,"max_hp":6000.0,"shield":0.0,"x":-3.8433847427368164,"y":8.990991592407227,"facing":0.0,"progress":0.0,"target":-1,"hits":0,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":5,"kind":"tower","team":0,"lane":"bot","zone":"lane","slot":-1,"uid":"","def":"blau_bot_inner","alive":true,"hp":7500.0,"max_hp":7500.0,"shield":0.0,"x":-4.349228858947754,"y":31.034507751464844,"facing":0.0,"progress":0.0,"target":-1,"hits":0,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":6,"kind":"tower","team":0,"lane":"bot","zone":"lane","slot":-1,"uid":"","def":"blau_bot_outer","alive":true,"hp":6000.0,"max_hp":6000.0,"shield":0.0,"x":11.117134094238281,"y":28.989334106445313,"facing":0.0,"progress":0.0,"target":-1,"hits":0,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":7,"kind":"tower","team":0,"lane":"base","zone":"lane","slot":-1,"uid":"","def":"blau_base_1","alive":true,"hp":9000.0,"max_hp":9000.0,"shield":0.0,"x":-29.476999282836914,"y":24.023000717163086,"facing":0.0,"progress":0.0,"target":-1,"hits":0,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":8,"kind":"tower","team":0,"lane":"base","zone":"lane","slot":-1,"uid":"","def":"blau_base_2","alive":true,"hp":9000.0,"max_hp":9000.0,"shield":0.0,"x":-24.023000717163086,"y":29.476999282836914,"facing":0.0,"progress":0.0,"target":-1,"hits":0,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":9,"kind":"core","team":0,"lane":"base","zone":"lane","slot":-1,"uid":"","def":"blau_ancient","alive":true,"hp":12000.0,"max_hp":12000.0,"shield":0.0,"x":-30.0,"y":30.0,"facing":0.0,"progress":0.0,"target":-1,"hits":0,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":10,"kind":"tower","team":1,"lane":"top","zone":"lane","slot":-1,"uid":"","def":"rot_top_inner","alive":true,"hp":7500.0,"max_hp":7500.0,"shield":0.0,"x":4.5293378829956055,"y":-24.931251525878906,"facing":0.0,"progress":0.0,"target":-1,"hits":0,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":11,"kind":"tower","team":1,"lane":"top","zone":"lane","slot":-1,"uid":"","def":"rot_top_outer","alive":true,"hp":6000.0,"max_hp":6000.0,"shield":0.0,"x":-12.715348243713379,"y":-24.921451568603516,"facing":0.0,"progress":0.0,"target":-1,"hits":0,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":12,"kind":"tower","team":1,"lane":"mid","zone":"lane","slot":-1,"uid":"","def":"rot_mid_inner","alive":true,"hp":7500.0,"max_hp":7500.0,"shield":0.0,"x":17.012392044067383,"y":-11.427590370178223,"facing":0.0,"progress":0.0,"target":-1,"hits":0,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":13,"kind":"tower","team":1,"lane":"mid","zone":"lane","slot":-1,"uid":"","def":"rot_mid_outer","alive":true,"hp":6000.0,"max_hp":6000.0,"shield":0.0,"x":8.990991592407227,"y":-3.8433847427368164,"facing":0.0,"progress":0.0,"target":-1,"hits":0,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":14,"kind":"tower","team":1,"lane":"bot","zone":"lane","slot":-1,"uid":"","def":"rot_bot_inner","alive":true,"hp":7500.0,"max_hp":7500.0,"shield":0.0,"x":31.034507751464844,"y":-4.349228858947754,"facing":0.0,"progress":0.0,"target":-1,"hits":0,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":15,"kind":"tower","team":1,"lane":"bot","zone":"lane","slot":-1,"uid":"","def":"rot_bot_outer","alive":true,"hp":6000.0,"max_hp":6000.0,"shield":0.0,"x":28.989334106445313,"y":11.117134094238281,"facing":0.0,"progress":0.0,"target":-1,"hits":0,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":16,"kind":"tower","team":1,"lane":"base","zone":"lane","slot":-1,"uid":"","def":"rot_base_1","alive":true,"hp":9000.0,"max_hp":9000.0,"shield":0.0,"x":24.023000717163086,"y":-29.476999282836914,"facing":0.0,"progress":0.0,"target":-1,"hits":0,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":17,"kind":"tower","team":1,"lane":"base","zone":"lane","slot":-1,"uid":"","def":"rot_base_2","alive":true,"hp":9000.0,"max_hp":9000.0,"shield":0.0,"x":29.476999282836914,"y":-24.023000717163086,"facing":0.0,"progress":0.0,"target":-1,"hits":0,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":18,"kind":"core","team":1,"lane":"base","zone":"lane","slot":-1,"uid":"","def":"rot_ancient","alive":true,"hp":12000.0,"max_hp":12000.0,"shield":0.0,"x":30.0,"y":-30.0,"facing":0.0,"progress":0.0,"target":-1,"hits":0,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":19,"kind":"monster","team":0,"lane":"top","zone":"lane","slot":-1,"uid":"","def":"e05","alive":true,"hp":1734.6000000000001,"max_hp":1824.0000000000002,"shield":0.0,"x":-25.283510208129883,"y":-23.183652877807617,"facing":0.5370096895063622,"progress":47.01967885311781,"target":40,"hits":3,"reached":false,"dormant":false,"effects":[],"dots":[["burn",12.0,1.1500000000000028,0.14999999999999936,0]]},{"id":20,"kind":"monster","team":0,"lane":"top","zone":"lane","slot":-1,"uid":"","def":"e01","alive":false,"hp":0.0,"max_hp":342.0,"shield":0.0,"x":-25.508886337280273,"y":-25.262741088867188,"facing":-2.0511780141570775,"progress":48.235890086483266,"target":-1,"hits":4,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":21,"kind":"monster","team":0,"lane":"top","zone":"lane","slot":-1,"uid":"","def":"e02","alive":true,"hp":142.01999999999998,"max_hp":912.0000000000001,"shield":0.0,"x":-25.83146858215332,"y":-24.104476928710938,"facing":-2.6245607010982517,"progress":47.33907316639135,"target":42,"hits":8,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":22,"kind":"monster","team":0,"lane":"top","zone":"lane","slot":-1,"uid":"","def":"e03","alive":true,"hp":570.0,"max_hp":570.0,"shield":0.0,"x":-26.834264755249023,"y":-23.35828399658203,"facing":2.943482297578591,"progress":45.94780352522284,"target":105,"hits":9,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":23,"kind":"monster","team":0,"lane":"top","zone":"lane","slot":-1,"uid":"","def":"e06","alive":true,"hp":722.0,"max_hp":722.0,"shield":0.0,"x":-26.949275970458984,"y":-22.265615463256836,"facing":1.2896738100796274,"progress":44.88465553873856,"target":40,"hits":7,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":24,"kind":"monster","team":0,"lane":"top","zone":"lane","slot":-1,"uid":"","def":"e04","alive":true,"hp":494.00000000000006,"max_hp":494.00000000000006,"shield":0.0,"x":-27.00127601623535,"y":-20.641695022583008,"facing":2.995677657950866,"progress":42.980481685819306,"target":40,"hits":11,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":25,"kind":"monster","team":0,"lane":"top","zone":"lane","slot":-1,"uid":"","def":"e03","alive":true,"hp":570.0,"max_hp":570.0,"shield":0.0,"x":-28.063169479370117,"y":-23.265235900878906,"facing":-3.1219739070568195,"progress":45.04617667198181,"target":105,"hits":8,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":26,"kind":"monster","team":0,"lane":"mid","zone":"lane","slot":-1,"uid":"","def":"e05","alive":true,"hp":1776.8000000000002,"max_hp":1824.0000000000002,"shield":0.0,"x":-0.9987305402755737,"y":0.6516907215118408,"facing":0.41987440342191773,"progress":29.442129861288272,"target":118,"hits":10,"reached":false,"dormant":false,"effects":[["hearth_warmth","damage",0.15,2.000000000000007]],"dots":[]},{"id":27,"kind":"monster","team":0,"lane":"mid","zone":"lane","slot":-1,"uid":"","def":"e01","alive":false,"hp":0.0,"max_hp":342.0,"shield":0.0,"x":0.2062474936246872,"y":-0.47823530435562134,"facing":2.45907607205713,"progress":31.062258790159383,"target":-1,"hits":3,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":28,"kind":"monster","team":0,"lane":"mid","zone":"lane","slot":-1,"uid":"","def":"e02","alive":false,"hp":0.0,"max_hp":912.0000000000001,"shield":0.0,"x":0.7177013754844666,"y":0.4603436589241028,"facing":1.8821077385846183,"progress":30.769838129051355,"target":-1,"hits":2,"reached":false,"dormant":false,"effects":[["root_grasp","movement_slow",0.3,3.0],["root_grasp_attack","attack_slow",0.1,3.0]],"dots":[]},{"id":29,"kind":"monster","team":0,"lane":"mid","zone":"lane","slot":-1,"uid":"","def":"e03","alive":true,"hp":508.64,"max_hp":570.0,"shield":0.0,"x":-2.2959046363830566,"y":0.6185722351074219,"facing":3.0522854949556275,"progress":28.64778663126081,"target":113,"hits":13,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":30,"kind":"monster","team":0,"lane":"mid","zone":"lane","slot":-1,"uid":"","def":"e06","alive":true,"hp":722.0,"max_hp":722.0,"shield":0.0,"x":-1.711600422859192,"y":2.5623767375946045,"facing":1.9554628463141885,"progress":27.544379522370352,"target":118,"hits":13,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":31,"kind":"monster","team":0,"lane":"mid","zone":"lane","slot":-1,"uid":"","def":"e04","alive":true,"hp":494.00000000000006,"max_hp":494.00000000000006,"shield":0.0,"x":-1.9653968811035156,"y":4.8330206871032715,"facing":2.5467244862741283,"progress":25.95159986669211,"target":119,"hits":12,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":32,"kind":"monster","team":0,"lane":"mid","zone":"lane","slot":-1,"uid":"","def":"e03","alive":true,"hp":508.64,"max_hp":570.0,"shield":0.0,"x":-2.409573554992676,"y":1.7124660015106201,"facing":-1.9199580851017013,"progress":27.686204384809738,"target":113,"hits":11,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":33,"kind":"monster","team":0,"lane":"bot","zone":"lane","slot":-1,"uid":"","def":"e05","alive":true,"hp":1777.6000000000001,"max_hp":1824.0000000000002,"shield":0.0,"x":24.110353469848633,"y":25.284866333007813,"facing":2.2752903910371143,"progress":47.61284535920972,"target":131,"hits":4,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":34,"kind":"monster","team":0,"lane":"bot","zone":"lane","slot":-1,"uid":"","def":"e01","alive":false,"hp":0.0,"max_hp":342.0,"shield":0.0,"x":25.859790802001953,"y":25.53399085998535,"facing":1.3895266436961482,"progress":48.71113131851269,"target":-1,"hits":4,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":35,"kind":"monster","team":0,"lane":"bot","zone":"lane","slot":-1,"uid":"","def":"e02","alive":true,"hp":795.9999999999999,"max_hp":912.0000000000001,"shield":0.0,"x":25.067790985107422,"y":25.36441421508789,"facing":1.4691197050540776,"progress":48.17921865378754,"target":131,"hits":8,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":36,"kind":"monster","team":0,"lane":"bot","zone":"lane","slot":-1,"uid":"","def":"e03","alive":true,"hp":539.84,"max_hp":570.0,"shield":0.0,"x":22.82434844970703,"y":24.620454788208008,"facing":-2.6965995968253513,"progress":47.27372082036881,"target":57,"hits":8,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":37,"kind":"monster","team":0,"lane":"bot","zone":"lane","slot":-1,"uid":"","def":"e06","alive":true,"hp":722.0,"max_hp":722.0,"shield":0.0,"x":21.703678131103516,"y":26.274660110473633,"facing":2.0380373957484057,"progress":43.740627046391396,"target":131,"hits":6,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":38,"kind":"monster","team":0,"lane":"bot","zone":"lane","slot":-1,"uid":"","def":"e04","alive":true,"hp":494.00000000000006,"max_hp":494.00000000000006,"shield":0.0,"x":21.070520401000977,"y":28.26952362060547,"facing":1.1068077699723204,"progress":43.38278042269983,"target":131,"hits":9,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":39,"kind":"monster","team":0,"lane":"bot","zone":"lane","slot":-1,"uid":"","def":"e03","alive":true,"hp":570.0,"max_hp":570.0,"shield":0.0,"x":21.724773406982422,"y":24.65081024169922,"facing":-1.6293439029496979,"progress":46.56351254271094,"target":57,"hits":9,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":40,"kind":"monster","team":1,"lane":"top","zone":"lane","slot":-1,"uid":"","def":"e05","alive":true,"hp":1824.0000000000002,"max_hp":1824.0000000000002,"shield":0.0,"x":-24.45193099975586,"y":-24.277360916137695,"facing":0.7454194762741583,"progress":48.464501411462194,"target":21,"hits":4,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":41,"kind":"monster","team":1,"lane":"top","zone":"lane","slot":-1,"uid":"","def":"e01","alive":false,"hp":0.0,"max_hp":342.0,"shield":0.0,"x":-26.15517807006836,"y":-25.393661499023438,"facing":-1.579195276844603,"progress":49.034055580649785,"target":-1,"hits":4,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":42,"kind":"monster","team":1,"lane":"top","zone":"lane","slot":-1,"uid":"","def":"e02","alive":true,"hp":697.9999999999999,"max_hp":912.0000000000001,"shield":0.0,"x":-25.19258689880371,"y":-25.07915496826172,"facing":-2.5058433275087157,"progress":48.52772111120304,"target":21,"hits":6,"reached":false,"dormant":false,"effects":[["hearth_warmth","damage",0.15,2.000000000000007]],"dots":[]},{"id":43,"kind":"monster","team":1,"lane":"top","zone":"lane","slot":-1,"uid":"","def":"e03","alive":true,"hp":570.0,"max_hp":570.0,"shield":0.0,"x":-23.95405387878418,"y":-26.523176193237305,"facing":-0.15041338663590192,"progress":46.58000979402972,"target":61,"hits":9,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":44,"kind":"monster","team":1,"lane":"top","zone":"lane","slot":-1,"uid":"","def":"e06","alive":true,"hp":722.0,"max_hp":722.0,"shield":0.0,"x":-22.48834228515625,"y":-26.167173385620117,"facing":0.3824313025500685,"progress":45.850232241979626,"target":21,"hits":7,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":45,"kind":"monster","team":1,"lane":"top","zone":"lane","slot":-1,"uid":"","def":"e04","alive":true,"hp":494.00000000000006,"max_hp":494.00000000000006,"shield":0.0,"x":-20.944805145263672,"y":-26.96967315673828,"facing":-1.602325763460625,"progress":43.72290621351966,"target":21,"hits":10,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":46,"kind":"monster","team":1,"lane":"top","zone":"lane","slot":-1,"uid":"","def":"e03","alive":true,"hp":570.0,"max_hp":570.0,"shield":0.0,"x":-23.90227699279785,"y":-27.652938842773438,"facing":-2.014822578526973,"progress":45.71319728770696,"target":61,"hits":8,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":47,"kind":"monster","team":1,"lane":"mid","zone":"lane","slot":-1,"uid":"","def":"e05","alive":true,"hp":1693.6,"max_hp":1824.0000000000002,"shield":0.0,"x":0.30242034792900085,"y":-0.02056261897087097,"facing":0.8874326673181843,"progress":30.350265106456128,"target":76,"hits":10,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":48,"kind":"monster","team":1,"lane":"mid","zone":"lane","slot":-1,"uid":"","def":"e01","alive":false,"hp":0.0,"max_hp":342.0,"shield":0.0,"x":-0.42639848589897156,"y":0.1575809121131897,"facing":-0.8719270222716092,"progress":30.991216241263334,"target":-1,"hits":3,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":49,"kind":"monster","team":1,"lane":"mid","zone":"lane","slot":-1,"uid":"","def":"e02","alive":false,"hp":0.0,"max_hp":912.0000000000001,"shield":0.0,"x":-0.00732382433488965,"y":0.8962339162826538,"facing":-0.8253269830770681,"progress":31.224838558461354,"target":-1,"hits":3,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":50,"kind":"monster","team":1,"lane":"mid","zone":"lane","slot":-1,"uid":"","def":"e03","alive":true,"hp":570.0,"max_hp":570.0,"shield":0.0,"x":0.8965543508529663,"y":-1.9002572298049927,"facing":0.5539625310307651,"progress":28.619708413095346,"target":26,"hits":14,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":51,"kind":"monster","team":1,"lane":"mid","zone":"lane","slot":-1,"uid":"","def":"e06","alive":true,"hp":722.0,"max_hp":722.0,"shield":0.0,"x":2.7278833389282227,"y":-2.0092461109161377,"facing":0.6175458804050661,"progress":27.21534137900342,"target":77,"hits":12,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":52,"kind":"monster","team":1,"lane":"mid","zone":"lane","slot":-1,"uid":"","def":"e04","alive":true,"hp":494.00000000000006,"max_hp":494.00000000000006,"shield":0.0,"x":4.073406219482422,"y":-2.341445207595825,"facing":-0.1148596983886491,"progress":26.006603211982615,"target":77,"hits":15,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":53,"kind":"monster","team":1,"lane":"mid","zone":"lane","slot":-1,"uid":"","def":"e03","alive":true,"hp":570.0,"max_hp":570.0,"shield":0.0,"x":0.35482698678970337,"y":-2.5599117279052734,"facing":-0.5794083378063754,"progress":28.556558365935032,"target":26,"hits":13,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":54,"kind":"monster","team":1,"lane":"bot","zone":"lane","slot":-1,"uid":"","def":"e05","alive":true,"hp":1824.0000000000002,"max_hp":1824.0000000000002,"shield":0.0,"x":25.648794174194336,"y":23.126113891601563,"facing":-2.8745118099329203,"progress":46.72362748001899,"target":88,"hits":5,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":55,"kind":"monster","team":1,"lane":"bot","zone":"lane","slot":-1,"uid":"","def":"e01","alive":false,"hp":0.0,"max_hp":342.0,"shield":0.0,"x":25.155879974365234,"y":25.840042114257813,"facing":-0.055653234968061925,"progress":48.94362494325162,"target":-1,"hits":4,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":56,"kind":"monster","team":1,"lane":"bot","zone":"lane","slot":-1,"uid":"","def":"e02","alive":true,"hp":909.8000000000001,"max_hp":912.0000000000001,"shield":0.0,"x":26.3362979888916,"y":23.950153350830078,"facing":1.93553114105931,"progress":47.1984378303084,"target":88,"hits":7,"reached":false,"dormant":false,"effects":[["hearth_warmth","damage",0.15,2.000000000000007]],"dots":[]},{"id":57,"kind":"monster","team":1,"lane":"bot","zone":"lane","slot":-1,"uid":"","def":"e03","alive":true,"hp":298.84,"max_hp":570.0,"shield":0.0,"x":24.628225326538086,"y":23.506189346313477,"facing":-1.21704893684158,"progress":47.71402576885533,"target":92,"hits":8,"reached":false,"dormant":false,"effects":[["hearth_warmth","damage",0.15,2.000000000000007],["root_grasp","movement_slow",0.3,2.9000000000000004],["root_grasp_attack","attack_slow",0.1,2.9000000000000004]],"dots":[["seed_burn",10.0,4.0,1.0,1]]},{"id":58,"kind":"monster","team":1,"lane":"bot","zone":"lane","slot":-1,"uid":"","def":"e06","alive":true,"hp":722.0,"max_hp":722.0,"shield":0.0,"x":26.325328826904297,"y":21.530715942382813,"facing":2.619375026404757,"progress":43.67009591127638,"target":88,"hits":7,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":59,"kind":"monster","team":1,"lane":"bot","zone":"lane","slot":-1,"uid":"","def":"e04","alive":true,"hp":494.00000000000006,"max_hp":494.00000000000006,"shield":0.0,"x":28.319917678833008,"y":20.869340896606445,"facing":0.7119479059716346,"progress":43.36367209682034,"target":88,"hits":9,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":60,"kind":"monster","team":1,"lane":"bot","zone":"lane","slot":-1,"uid":"","def":"e03","alive":true,"hp":553.64,"max_hp":570.0,"shield":0.0,"x":24.570741653442383,"y":22.25619125366211,"facing":-2.0190497705634844,"progress":46.93952348896281,"target":92,"hits":9,"reached":false,"dormant":false,"effects":[["hearth_warmth","damage",0.15,2.000000000000007]],"dots":[]},{"id":61,"kind":"troop","team":0,"lane":"top","zone":"lane","slot":0,"uid":"p0-4","def":"w04","alive":false,"hp":0.0,"max_hp":1560.0,"shield":0.0,"x":-26.517112731933594,"y":-25.497575759887695,"facing":2.8903770650977294,"progress":47.5787772016731,"target":-1,"hits":9,"reached":false,"dormant":false,"effects":[],"dots":[["burn",12.0,2.0000000000000036,0.9999999999999997,0]]},{"id":62,"kind":"troop","team":0,"lane":"top","zone":"lane","slot":0,"uid":"p0-10","def":"w04","alive":true,"hp":1499.1999999999998,"max_hp":1560.0,"shield":0.0,"x":-26.869930267333984,"y":-24.45649528503418,"facing":-1.9778848388605959,"progress":47.255018152865894,"target":105,"hits":8,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":63,"kind":"troop","team":0,"lane":"top","zone":"lane","slot":0,"uid":"p0-12","def":"w04","alive":false,"hp":0.0,"max_hp":1560.0,"shield":0.0,"x":-24.795499801635742,"y":-24.347536087036133,"facing":1.9467996786989081,"progress":48.142716690993105,"target":-1,"hits":4,"reached":false,"dormant":false,"effects":[],"dots":[["burn",12.0,2.6500000000000012,0.7499999999999994,0]]},{"id":64,"kind":"troop","team":0,"lane":"top","zone":"lane","slot":0,"uid":"p0-7","def":"w02","alive":false,"hp":0.0,"max_hp":800.0,"shield":0.0,"x":-24.818099975585938,"y":-25.415416717529297,"facing":3.1163233081835755,"progress":48.84454802147157,"target":-1,"hits":2,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":65,"kind":"troop","team":0,"lane":"top","zone":"lane","slot":0,"uid":"p0-5","def":"w08","alive":true,"hp":940.0,"max_hp":940.0,"shield":0.0,"x":-29.22440528869629,"y":-22.201385498046875,"facing":2.3742419288797416,"progress":43.71501409566062,"target":105,"hits":7,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":66,"kind":"troop","team":0,"lane":"top","zone":"lane","slot":0,"uid":"p0-13","def":"w08","alive":true,"hp":940.0,"max_hp":940.0,"shield":0.0,"x":-28.044008255004883,"y":-22.252931594848633,"facing":-3.073318871190689,"progress":44.33774458334184,"target":105,"hits":7,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":67,"kind":"hero","team":0,"lane":"top","zone":"lane","slot":0,"uid":"h0-1","def":"g05","alive":true,"hp":950.0,"max_hp":950.0,"shield":0.0,"x":-27.888681411743164,"y":-20.05471420288086,"facing":1.9772627599430772,"progress":42.22664161713877,"target":40,"hits":8,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":68,"kind":"troop","team":0,"lane":"top","zone":"lane","slot":0,"uid":"p0-3","def":"w06","alive":true,"hp":630.0,"max_hp":630.0,"shield":0.0,"x":-26.584840774536133,"y":-19.663774490356445,"facing":2.724555493536157,"progress":42.10660145523024,"target":40,"hits":7,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":69,"kind":"troop","team":0,"lane":"top","zone":"lane","slot":0,"uid":"p0-6","def":"w06","alive":true,"hp":630.0,"max_hp":630.0,"shield":0.0,"x":-30.07871437072754,"y":-21.300844192504883,"facing":-2.0049469115059226,"progress":43.00564285811116,"target":105,"hits":7,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":70,"kind":"troop","team":0,"lane":"top","zone":"lane","slot":0,"uid":"p0-9","def":"w06","alive":true,"hp":630.0,"max_hp":630.0,"shield":0.0,"x":-28.828332901000977,"y":-20.068788528442383,"facing":-1.5924827617889492,"progress":42.05447016623295,"target":105,"hits":7,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":71,"kind":"troop","team":0,"lane":"top","zone":"lane","slot":0,"uid":"p0-11","def":"w06","alive":true,"hp":630.0,"max_hp":630.0,"shield":0.0,"x":-27.5052547454834,"y":-19.10503578186035,"facing":-0.04654956230334177,"progress":41.23245884716554,"target":40,"hits":6,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":72,"kind":"troop","team":0,"lane":"top","zone":"lane","slot":0,"uid":"p0-14","def":"w06","alive":true,"hp":630.0,"max_hp":630.0,"shield":0.0,"x":-26.511430740356445,"y":-18.64583969116211,"facing":0.13752933975580087,"progress":40.82466154138258,"target":40,"hits":7,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":73,"kind":"troop","team":0,"lane":"top","zone":"lane","slot":0,"uid":"p0-8","def":"w10","alive":true,"hp":1000.0,"max_hp":1000.0,"shield":0.0,"x":-28.01921272277832,"y":-21.34503173828125,"facing":1.3387964104162926,"progress":43.55818006892897,"target":105,"hits":5,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":74,"kind":"troop","team":0,"lane":"mid","zone":"lane","slot":1,"uid":"p1-3","def":"g04","alive":false,"hp":0.0,"max_hp":1650.0,"shield":0.0,"x":-1.267238974571228,"y":-1.2969367504119873,"facing":3.0356781914552555,"progress":30.58411772972787,"target":-1,"hits":9,"reached":false,"dormant":false,"effects":[["hearth_warmth","damage",0.15,0.6000000000000059]],"dots":[]},{"id":75,"kind":"troop","team":0,"lane":"mid","zone":"lane","slot":1,"uid":"p1-7","def":"g04","alive":false,"hp":0.0,"max_hp":1650.0,"shield":0.0,"x":-0.23193839192390442,"y":-0.38285014033317566,"facing":-3.0942591904945993,"progress":30.682716646616566,"target":-1,"hits":7,"reached":false,"dormant":false,"effects":[["root_grasp","movement_slow",0.3,3.0],["root_grasp_attack","attack_slow",0.1,3.0]],"dots":[["seed_burn",10.0,2.9500000000000037,0.8999999999999992,1]]},{"id":76,"kind":"troop","team":0,"lane":"mid","zone":"lane","slot":1,"uid":"p1-11","def":"g04","alive":true,"hp":1542.7199999999998,"max_hp":1650.0,"shield":0.0,"x":0.05883084982633591,"y":1.2845872640609741,"facing":-1.793661550937761,"progress":29.708844585926265,"target":119,"hits":11,"reached":false,"dormant":false,"effects":[["hearth_warmth","damage",0.15,2.000000000000007]],"dots":[]},{"id":77,"kind":"troop","team":0,"lane":"mid","zone":"lane","slot":1,"uid":"p1-14","def":"g04","alive":true,"hp":40.86999999999995,"max_hp":1650.0,"shield":0.0,"x":1.1314016580581665,"y":1.5276068449020386,"facing":1.347923453971854,"progress":30.282344638412603,"target":119,"hits":12,"reached":false,"dormant":false,"effects":[["hearth_warmth","damage",0.15,2.000000000000007],["root_grasp","movement_slow",0.3,1.500000000000003],["root_grasp_attack","attack_slow",0.1,1.500000000000003]],"dots":[["seed_burn",10.0,0.5000000000000058,0.4499999999999986,1]]},{"id":78,"kind":"troop","team":0,"lane":"mid","zone":"lane","slot":1,"uid":"p1-5","def":"g02","alive":false,"hp":0.0,"max_hp":690.0,"shield":0.0,"x":-1.4471461772918701,"y":-0.3527525067329407,"facing":-2.721728167294961,"progress":29.818159495080295,"target":-1,"hits":12,"reached":false,"dormant":false,"effects":[["root_grasp","movement_slow",0.3,0.7500000000000024],["root_grasp_attack","attack_slow",0.1,0.7500000000000024],["hearth_warmth","damage",0.15,2.2000000000000064]],"dots":[]},{"id":79,"kind":"troop","team":0,"lane":"mid","zone":"lane","slot":1,"uid":"p1-10","def":"g02","alive":false,"hp":0.0,"max_hp":690.0,"shield":0.0,"x":0.01403797511011362,"y":0.5099493861198425,"facing":2.9499065939199225,"progress":30.225963756665745,"target":-1,"hits":9,"reached":false,"dormant":false,"effects":[["root_grasp","movement_slow",0.3,0.8000000000000025],["root_grasp_attack","attack_slow",0.1,0.8000000000000025]],"dots":[["seed_burn",10.0,4.0,1.0,1]]},{"id":80,"kind":"troop","team":0,"lane":"mid","zone":"lane","slot":1,"uid":"p1-8","def":"g08","alive":true,"hp":820.0,"max_hp":820.0,"shield":0.0,"x":-3.1984200477600098,"y":2.7422497272491455,"facing":-1.730654794691235,"progress":26.428353648694035,"target":113,"hits":10,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":81,"kind":"troop","team":0,"lane":"mid","zone":"lane","slot":1,"uid":"p1-4","def":"g06","alive":true,"hp":640.0,"max_hp":640.0,"shield":0.0,"x":-2.564549684524536,"y":5.755524635314941,"facing":-0.5729910086137856,"progress":24.85030064263585,"target":119,"hits":12,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":82,"kind":"troop","team":0,"lane":"mid","zone":"lane","slot":1,"uid":"p1-9","def":"g06","alive":true,"hp":640.0,"max_hp":640.0,"shield":0.0,"x":-5.464199066162109,"y":2.940836191177368,"facing":-1.68202167224129,"progress":24.73963919692111,"target":113,"hits":12,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":83,"kind":"troop","team":0,"lane":"mid","zone":"lane","slot":1,"uid":"p1-12","def":"g06","alive":true,"hp":640.0,"max_hp":640.0,"shield":0.0,"x":-4.836726665496826,"y":4.286793231964111,"facing":0.08604869639826539,"progress":24.158320063845146,"target":113,"hits":12,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":84,"kind":"hero","team":0,"lane":"mid","zone":"lane","slot":1,"uid":"h1-1","def":"w10","alive":true,"hp":1300.0,"max_hp":1300.0,"shield":0.0,"x":-2.360701084136963,"y":3.452115297317505,"facing":-0.0322200788918319,"progress":26.467964482320873,"target":118,"hits":9,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":85,"kind":"troop","team":0,"lane":"mid","zone":"lane","slot":1,"uid":"p1-6","def":"g10","alive":true,"hp":1080.0,"max_hp":1080.0,"shield":0.0,"x":-1.271512746810913,"y":3.596280813217163,"facing":1.4225876335198069,"progress":27.08650529811239,"target":119,"hits":11,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":86,"kind":"troop","team":0,"lane":"mid","zone":"lane","slot":1,"uid":"p1-13","def":"g10","alive":true,"hp":1080.0,"max_hp":1080.0,"shield":0.0,"x":-3.659642219543457,"y":1.7452226877212524,"facing":-2.702836168293288,"progress":26.803246258631088,"target":113,"hits":10,"reached":false,"dormant":false,"effects":[["hearth_warmth","damage",0.15,2.000000000000007]],"dots":[]},{"id":87,"kind":"hero","team":0,"lane":"bot","zone":"lane","slot":2,"uid":"h2-1","def":"w04","alive":false,"hp":0.0,"max_hp":2200.0,"shield":0.0,"x":25.66211700439453,"y":23.862245559692383,"facing":2.2078162384446207,"progress":49.65560783213687,"target":-1,"hits":4,"reached":false,"dormant":false,"effects":[],"dots":[["burn",12.0,2.750000000000001,0.4999999999999993,0]]},{"id":88,"kind":"troop","team":0,"lane":"bot","zone":"lane","slot":2,"uid":"p2-3","def":"w04","alive":true,"hp":292.5699999999997,"max_hp":1560.0,"shield":0.0,"x":25.687305450439453,"y":24.50977897644043,"facing":2.5092465932357784,"progress":49.25092369276327,"target":131,"hits":9,"reached":false,"dormant":false,"effects":[],"dots":[["burn",12.0,2.9000000000000004,0.7499999999999978,0]]},{"id":89,"kind":"troop","team":0,"lane":"bot","zone":"lane","slot":2,"uid":"p2-6","def":"w04","alive":true,"hp":1536.8,"max_hp":1560.0,"shield":0.0,"x":25.879493713378906,"y":26.002731323242188,"facing":0.9076410492158257,"progress":48.22770246814032,"target":128,"hits":8,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":90,"kind":"troop","team":0,"lane":"bot","zone":"lane","slot":2,"uid":"p2-10","def":"w04","alive":true,"hp":1560.0,"max_hp":1560.0,"shield":0.0,"x":25.503507614135742,"y":27.07339859008789,"facing":0.9010953656144626,"progress":47.17206101994995,"target":128,"hits":8,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":91,"kind":"troop","team":0,"lane":"bot","zone":"lane","slot":2,"uid":"p2-12","def":"w04","alive":false,"hp":0.0,"max_hp":1560.0,"shield":0.0,"x":24.835290908813477,"y":23.821012496948242,"facing":-2.4608111478248644,"progress":49.05745262674192,"target":-1,"hits":5,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":92,"kind":"troop","team":0,"lane":"bot","zone":"lane","slot":2,"uid":"p2-4","def":"w02","alive":true,"hp":221.01099999999963,"max_hp":800.0,"shield":0.0,"x":23.56589698791504,"y":23.538711547851563,"facing":-2.4206630855959386,"progress":48.4104163646698,"target":57,"hits":9,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":93,"kind":"troop","team":0,"lane":"bot","zone":"lane","slot":2,"uid":"p2-9","def":"w02","alive":true,"hp":686.9499999999998,"max_hp":800.0,"shield":0.0,"x":24.260868072509766,"y":24.315088272094727,"facing":2.486911261666083,"progress":48.4104163646698,"target":131,"hits":5,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":94,"kind":"troop","team":0,"lane":"bot","zone":"lane","slot":2,"uid":"p2-13","def":"w02","alive":true,"hp":800.0,"max_hp":800.0,"shield":0.0,"x":24.64499855041504,"y":26.393924713134766,"facing":-2.2404972879753307,"progress":47.18237574315539,"target":128,"hits":6,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":95,"kind":"troop","team":0,"lane":"bot","zone":"lane","slot":2,"uid":"p2-7","def":"w08","alive":true,"hp":940.0,"max_hp":940.0,"shield":0.0,"x":20.45791244506836,"y":24.024477005004883,"facing":-3.124803186564609,"progress":41.60263800621033,"target":57,"hits":8,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":96,"kind":"troop","team":0,"lane":"bot","zone":"lane","slot":2,"uid":"p2-5","def":"w06","alive":true,"hp":630.0,"max_hp":630.0,"shield":0.0,"x":19.1519832611084,"y":25.731464385986328,"facing":-2.685165135732435,"progress":41.05450798394545,"target":57,"hits":8,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":97,"kind":"troop","team":0,"lane":"bot","zone":"lane","slot":2,"uid":"p2-11","def":"w06","alive":true,"hp":630.0,"max_hp":630.0,"shield":0.0,"x":19.635112762451172,"y":26.716928482055664,"facing":0.45642751785735797,"progress":41.62320684940016,"target":57,"hits":6,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":98,"kind":"troop","team":0,"lane":"bot","zone":"lane","slot":2,"uid":"p2-14","def":"w06","alive":true,"hp":630.0,"max_hp":630.0,"shield":0.0,"x":20.104930877685547,"y":27.7857723236084,"facing":-2.0347848836174727,"progress":42.566554151811935,"target":128,"hits":6,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":99,"kind":"troop","team":0,"lane":"bot","zone":"lane","slot":2,"uid":"p2-8","def":"w10","alive":true,"hp":1000.0,"max_hp":1000.0,"shield":0.0,"x":20.475522994995117,"y":25.120147705078125,"facing":0.016789467025184027,"progress":41.811910237700225,"target":57,"hits":6,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":100,"kind":"hero","team":1,"lane":"top","zone":"lane","slot":3,"uid":"h3-1","def":"w04","alive":true,"hp":2273.499999999999,"max_hp":2550.0,"shield":0.0,"x":-27.0815486907959,"y":-26.208295822143555,"facing":-0.9592993525353349,"progress":49.21045604975718,"target":61,"hits":9,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":101,"kind":"troop","team":1,"lane":"top","zone":"lane","slot":3,"uid":"p3-2","def":"g04","alive":true,"hp":1525.08,"max_hp":1650.0,"shield":0.0,"x":-25.305763244628906,"y":-26.178930282592773,"facing":0.9325188074482352,"progress":47.752989392190955,"target":61,"hits":8,"reached":false,"dormant":false,"effects":[["hearth_warmth","damage",0.15,2.000000000000007]],"dots":[]},{"id":102,"kind":"troop","team":1,"lane":"top","zone":"lane","slot":3,"uid":"p3-6","def":"g04","alive":false,"hp":0.0,"max_hp":1650.0,"shield":0.0,"x":-26.171186447143555,"y":-24.3249568939209,"facing":-2.028896477025026,"progress":49.73960946261476,"target":-1,"hits":6,"reached":false,"dormant":false,"effects":[],"dots":[["seed_burn",10.0,3.0000000000000036,0.3999999999999993,1]]},{"id":103,"kind":"troop","team":1,"lane":"top","zone":"lane","slot":3,"uid":"p3-10","def":"g04","alive":false,"hp":0.0,"max_hp":1650.0,"shield":0.0,"x":-25.262046813964844,"y":-23.41229820251465,"facing":-0.599462822789241,"progress":49.63991915503229,"target":-1,"hits":3,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":104,"kind":"troop","team":1,"lane":"top","zone":"lane","slot":3,"uid":"p3-13","def":"g04","alive":true,"hp":1565.04,"max_hp":1650.0,"shield":0.0,"x":-26.18292236328125,"y":-26.842689514160156,"facing":2.88995334295928,"progress":47.78519551842292,"target":61,"hits":7,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":105,"kind":"troop","team":1,"lane":"top","zone":"lane","slot":3,"uid":"p3-3","def":"g02","alive":true,"hp":33.39999999999991,"max_hp":690.0,"shield":0.0,"x":-26.217397689819336,"y":-25.467161178588867,"facing":-1.9391162189423723,"progress":49.033716009194606,"target":61,"hits":7,"reached":false,"dormant":false,"effects":[["hearth_warmth","damage",0.15,2.000000000000007]],"dots":[]},{"id":106,"kind":"troop","team":1,"lane":"top","zone":"lane","slot":3,"uid":"p3-8","def":"g02","alive":false,"hp":0.0,"max_hp":690.0,"shield":0.0,"x":-24.256298065185547,"y":-23.203128814697266,"facing":0.17187229247605856,"progress":49.01029124185082,"target":-1,"hits":7,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":107,"kind":"troop","team":1,"lane":"top","zone":"lane","slot":3,"uid":"p3-11","def":"g02","alive":false,"hp":0.0,"max_hp":690.0,"shield":0.0,"x":-25.277999877929688,"y":-23.7419490814209,"facing":-0.5045273561689871,"progress":49.43818235144005,"target":-1,"hits":5,"reached":false,"dormant":false,"effects":[],"dots":[["seed_burn",10.0,2.000000000000007,0.9499999999999993,1]]},{"id":108,"kind":"troop","team":1,"lane":"top","zone":"lane","slot":3,"uid":"p3-5","def":"g08","alive":true,"hp":820.0,"max_hp":820.0,"shield":0.0,"x":-22.73340606689453,"y":-28.72504425048828,"facing":-0.8637512211971569,"progress":44.4233711511436,"target":61,"hits":6,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":109,"kind":"troop","team":1,"lane":"top","zone":"lane","slot":3,"uid":"p3-4","def":"g06","alive":true,"hp":640.0,"max_hp":640.0,"shield":0.0,"x":-21.05518341064453,"y":-28.98330307006836,"facing":-2.6811120965496893,"progress":42.985877647992226,"target":61,"hits":6,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":110,"kind":"troop","team":1,"lane":"top","zone":"lane","slot":3,"uid":"p3-9","def":"g06","alive":true,"hp":640.0,"max_hp":640.0,"shield":0.0,"x":-20.561044692993164,"y":-28.00054931640625,"facing":1.7815333231756163,"progress":42.75969980107221,"target":61,"hits":7,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":111,"kind":"troop","team":1,"lane":"top","zone":"lane","slot":3,"uid":"p3-12","def":"g06","alive":true,"hp":640.0,"max_hp":640.0,"shield":0.0,"x":-19.891965866088867,"y":-26.65105438232422,"facing":1.2751610758113605,"progress":42.34373768794155,"target":21,"hits":7,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":112,"kind":"troop","team":1,"lane":"top","zone":"lane","slot":3,"uid":"p3-7","def":"g10","alive":true,"hp":1080.0,"max_hp":1080.0,"shield":0.0,"x":-22.907114028930664,"y":-27.18431854248047,"facing":1.509230395056963,"progress":45.39140185539212,"target":61,"hits":5,"reached":false,"dormant":false,"effects":[["hearth_warmth","damage",0.15,2.000000000000007]],"dots":[]},{"id":113,"kind":"hero","team":1,"lane":"mid","zone":"lane","slot":4,"uid":"h4-1","def":"w04","alive":true,"hp":1035.9,"max_hp":2550.0,"shield":0.0,"x":-2.077450752258301,"y":-0.7439736723899841,"facing":-0.1589734959640725,"progress":31.50428747671767,"target":29,"hits":13,"reached":false,"dormant":false,"effects":[],"dots":[["burn",12.0,2.400000000000002,0.39999999999999963,0]]},{"id":114,"kind":"troop","team":1,"lane":"mid","zone":"lane","slot":4,"uid":"p4-3","def":"w04","alive":false,"hp":0.0,"max_hp":1560.0,"shield":0.0,"x":-0.8652145862579346,"y":-0.3461950421333313,"facing":-1.660982004926859,"progress":30.939051320100525,"target":-1,"hits":5,"reached":false,"dormant":false,"effects":[],"dots":[["burn",12.0,0.9500000000000026,0.9499999999999993,0]]},{"id":115,"kind":"troop","team":1,"lane":"mid","zone":"lane","slot":4,"uid":"p4-6","def":"w04","alive":false,"hp":0.0,"max_hp":1560.0,"shield":0.0,"x":-0.11376038193702698,"y":0.40206480026245117,"facing":-0.5181905873329883,"progress":30.946710339491876,"target":-1,"hits":10,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":116,"kind":"troop","team":1,"lane":"mid","zone":"lane","slot":4,"uid":"p4-10","def":"w04","alive":false,"hp":0.0,"max_hp":1560.0,"shield":0.0,"x":0.7265796065330505,"y":1.372330904006958,"facing":-0.3480406824275032,"progress":31.050551580014357,"target":-1,"hits":10,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":117,"kind":"troop","team":1,"lane":"mid","zone":"lane","slot":4,"uid":"p4-12","def":"w04","alive":true,"hp":1536.8,"max_hp":1560.0,"shield":0.0,"x":-1.062774658203125,"y":-0.9627045392990112,"facing":-0.145980315993101,"progress":30.63743875545596,"target":26,"hits":12,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":118,"kind":"troop","team":1,"lane":"mid","zone":"lane","slot":4,"uid":"p4-5","def":"w02","alive":true,"hp":536.7999999999997,"max_hp":800.0,"shield":0.0,"x":-0.5467419028282166,"y":-0.5297960638999939,"facing":-0.04323700024353479,"progress":30.58493898804697,"target":26,"hits":11,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":119,"kind":"troop","team":1,"lane":"mid","zone":"lane","slot":4,"uid":"p4-11","def":"w02","alive":true,"hp":378.82499999999976,"max_hp":800.0,"shield":0.0,"x":1.2299256324768066,"y":0.5227210521697998,"facing":1.0985773470238875,"progress":30.100307985743136,"target":77,"hits":10,"reached":false,"dormant":false,"effects":[],"dots":[["burn",12.0,0.35000000000000225,0.349999999999999,0]]},{"id":120,"kind":"troop","team":1,"lane":"mid","zone":"lane","slot":4,"uid":"p4-14","def":"w02","alive":true,"hp":800.0,"max_hp":800.0,"shield":0.0,"x":2.147413730621338,"y":1.1059503555297852,"facing":1.0046323691618297,"progress":29.88356710171407,"target":77,"hits":13,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":121,"kind":"troop","team":1,"lane":"mid","zone":"lane","slot":4,"uid":"p4-7","def":"w08","alive":true,"hp":940.0,"max_hp":940.0,"shield":0.0,"x":2.126304864883423,"y":-2.858224630355835,"facing":-2.7426097144603934,"progress":27.078040383186398,"target":77,"hits":12,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":122,"kind":"troop","team":1,"lane":"mid","zone":"lane","slot":4,"uid":"p4-4","def":"w06","alive":true,"hp":630.0,"max_hp":630.0,"shield":0.0,"x":3.290201425552368,"y":-4.021749019622803,"facing":-2.139080961103555,"progress":25.43004688895309,"target":77,"hits":10,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":123,"kind":"troop","team":1,"lane":"mid","zone":"lane","slot":4,"uid":"p4-9","def":"w06","alive":true,"hp":630.0,"max_hp":630.0,"shield":0.0,"x":4.218615531921387,"y":-3.431809902191162,"facing":1.2759687073853228,"progress":25.177325356174116,"target":77,"hits":11,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":124,"kind":"troop","team":1,"lane":"mid","zone":"lane","slot":4,"uid":"p4-13","def":"w06","alive":true,"hp":630.0,"max_hp":630.0,"shield":0.0,"x":5.192545413970947,"y":-2.558967113494873,"facing":1.5902773237273424,"progress":25.042044321848675,"target":77,"hits":11,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":125,"kind":"troop","team":1,"lane":"mid","zone":"lane","slot":4,"uid":"p4-8","def":"w10","alive":true,"hp":1000.0,"max_hp":1000.0,"shield":0.0,"x":1.1430784463882446,"y":-3.292203664779663,"facing":-0.49221418004265355,"progress":27.480734618888672,"target":26,"hits":11,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":126,"kind":"troop","team":1,"lane":"bot","zone":"lane","slot":5,"uid":"p5-5","def":"g04","alive":false,"hp":0.0,"max_hp":1650.0,"shield":0.0,"x":23.932415008544922,"y":25.649744033813477,"facing":-1.0480854006089828,"progress":49.60033455304198,"target":-1,"hits":2,"reached":false,"dormant":false,"effects":[["root_grasp","movement_slow",0.3,1.8000000000000034],["root_grasp_attack","attack_slow",0.1,1.8000000000000034]],"dots":[]},{"id":127,"kind":"troop","team":1,"lane":"bot","zone":"lane","slot":5,"uid":"p5-10","def":"g04","alive":false,"hp":0.0,"max_hp":1650.0,"shield":0.0,"x":24.109678268432617,"y":24.323076248168945,"facing":-0.631265236126433,"progress":48.481152914375556,"target":-1,"hits":7,"reached":false,"dormant":false,"effects":[["root_grasp","movement_slow",0.3,1.0000000000000027],["root_grasp_attack","attack_slow",0.1,1.0000000000000027]],"dots":[["seed_burn",10.0,1.0500000000000063,0.999999999999999,1]]},{"id":128,"kind":"troop","team":1,"lane":"bot","zone":"lane","slot":5,"uid":"p5-3","def":"g02","alive":false,"hp":0.0,"max_hp":690.0,"shield":0.0,"x":25.735816955566406,"y":25.71809196472168,"facing":-0.8379237372246074,"progress":48.328394722404695,"target":-1,"hits":9,"reached":false,"dormant":false,"effects":[["root_grasp","movement_slow",0.3,2.6000000000000014],["root_grasp_attack","attack_slow",0.1,2.6000000000000014]],"dots":[]},{"id":129,"kind":"troop","team":1,"lane":"bot","zone":"lane","slot":5,"uid":"p5-7","def":"g02","alive":true,"hp":690.0,"max_hp":690.0,"shield":0.0,"x":26.540748596191406,"y":25.004955291748047,"facing":0.19270075866238556,"progress":47.29722328308704,"target":88,"hits":7,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":130,"kind":"troop","team":1,"lane":"bot","zone":"lane","slot":5,"uid":"p5-9","def":"g02","alive":false,"hp":0.0,"max_hp":690.0,"shield":0.0,"x":24.7377872467041,"y":25.306814193725586,"facing":-0.5705311611010139,"progress":48.81400485072034,"target":-1,"hits":5,"reached":false,"dormant":false,"effects":[["root_grasp","movement_slow",0.3,2.700000000000001],["root_grasp_attack","attack_slow",0.1,2.700000000000001]],"dots":[["seed_burn",10.0,3.6000000000000014,0.5999999999999996,1]]},{"id":131,"kind":"troop","team":1,"lane":"bot","zone":"lane","slot":5,"uid":"p5-12","def":"g02","alive":true,"hp":460.3,"max_hp":690.0,"shield":0.0,"x":25.25707244873047,"y":24.481956481933594,"facing":-0.9086527024852681,"progress":47.87703061375637,"target":88,"hits":9,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":132,"kind":"troop","team":1,"lane":"bot","zone":"lane","slot":5,"uid":"p5-6","def":"g08","alive":true,"hp":820.0,"max_hp":820.0,"shield":0.0,"x":26.577404022216797,"y":19.641386032104492,"facing":-1.9389498321096441,"progress":41.640583800976486,"target":92,"hits":6,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":133,"kind":"troop","team":1,"lane":"bot","zone":"lane","slot":5,"uid":"p5-14","def":"g08","alive":true,"hp":820.0,"max_hp":820.0,"shield":0.0,"x":27.60527801513672,"y":20.03312110900879,"facing":2.545808105966734,"progress":42.35032907786197,"target":88,"hits":6,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":134,"kind":"hero","team":1,"lane":"bot","zone":"lane","slot":5,"uid":"h5-1","def":"g05","alive":true,"hp":950.0,"max_hp":950.0,"shield":0.0,"x":24.121566772460938,"y":18.518186569213867,"facing":-2.021932942118079,"progress":40.135781785493116,"target":92,"hits":7,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":135,"kind":"troop","team":1,"lane":"bot","zone":"lane","slot":5,"uid":"p5-4","def":"g06","alive":true,"hp":640.0,"max_hp":640.0,"shield":0.0,"x":26.172739028930664,"y":18.022701263427734,"facing":-1.814619366399213,"progress":40.01127890379969,"target":92,"hits":8,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":136,"kind":"troop","team":1,"lane":"bot","zone":"lane","slot":5,"uid":"p5-8","def":"g06","alive":true,"hp":640.0,"max_hp":640.0,"shield":0.0,"x":27.240432739257813,"y":18.287294387817383,"facing":1.3269732871905804,"progress":40.45428047578205,"target":92,"hits":6,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":137,"kind":"troop","team":1,"lane":"bot","zone":"lane","slot":5,"uid":"p5-13","def":"g06","alive":true,"hp":640.0,"max_hp":640.0,"shield":0.0,"x":28.303524017333984,"y":18.760019302368164,"facing":-0.5076799792207686,"progress":41.11329584177656,"target":88,"hits":6,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":138,"kind":"troop","team":1,"lane":"bot","zone":"lane","slot":5,"uid":"p5-11","def":"g10","alive":true,"hp":1080.0,"max_hp":1080.0,"shield":0.0,"x":25.088973999023438,"y":20.130643844604492,"facing":-2.866143935692043,"progress":41.60263800621033,"target":92,"hits":5,"reached":false,"dormant":false,"effects":[["hearth_warmth","damage",0.15,2.000000000000007]],"dots":[]}]},{"label":"settled","phase":0,"round":22,"winner":-2,"end_note":"","players":[{"gold":1400,"draft_gold":1400,"ready":true,"earned":465,"spent":0,"next_seq":15,"roster":["p0-3|w06|top|195","p0-4|w04|top|230","p0-5|w08|top|295","p0-6|w06|top|195","p0-7|w02|top|150","p0-8|w10|top|270","p0-9|w06|top|195","p0-10|w04|top|230","p0-11|w06|top|195","p0-12|w04|top|230","p0-13|w08|top|295","p0-14|w06|top|195"],"hero":"h0-1|held_funkenlanze|592|top|funkenfokus||260|false|","bookings":["c0-2|ch_druck|top|150|22"],"new_bookings":[],"draft_roster":["p0-3|w06|top|195|false","p0-4|w04|top|230|false","p0-5|w08|top|295|false","p0-6|w06|top|195|false","p0-7|w02|top|150|false","p0-8|w10|top|270|false","p0-9|w06|top|195|false","p0-10|w04|top|230|false","p0-11|w06|top|195|false","p0-12|w04|top|230|false","p0-13|w08|top|295|false","p0-14|w06|top|195|false"],"draft_hero":"h0-1|held_funkenlanze|592|top|funkenfokus||260|false|","boss_lane":"","undo":0},{"gold":1495,"draft_gold":1495,"ready":true,"earned":465,"spent":0,"next_seq":15,"roster":["p1-3|g04|mid|220","p1-4|g06|mid|205","p1-5|g02|mid|135","p1-6|g10|mid|255","p1-7|g04|mid|220","p1-8|g08|mid|285","p1-9|g06|mid|205","p1-10|g02|mid|135","p1-11|g04|mid|220","p1-12|g06|mid|205","p1-13|g10|mid|255","p1-14|g04|mid|220"],"hero":"h1-1|held_quellgeflecht|712|mid|quellamulett||260|false|","bookings":["c1-2|ch_schutz|mid|150|22"],"new_bookings":[],"draft_roster":["p1-3|g04|mid|220|false","p1-4|g06|mid|205|false","p1-5|g02|mid|135|false","p1-6|g10|mid|255|false","p1-7|g04|mid|220|false","p1-8|g08|mid|285|false","p1-9|g06|mid|205|false","p1-10|g02|mid|135|false","p1-11|g04|mid|220|false","p1-12|g06|mid|205|false","p1-13|g10|mid|255|false","p1-14|g04|mid|220|false"],"draft_hero":"h1-1|held_quellgeflecht|712|mid|quellamulett||260|false|","boss_lane":"","undo":0},{"gold":1545,"draft_gold":1545,"ready":true,"earned":465,"spent":0,"next_seq":15,"roster":["p2-3|w04|bot|230","p2-4|w02|bot|150","p2-5|w06|bot|195","p2-6|w04|bot|230","p2-7|w08|bot|295","p2-8|w10|bot|270","p2-9|w02|bot|150","p2-10|w04|bot|230","p2-11|w06|bot|195","p2-12|w04|bot|230","p2-13|w02|bot|150","p2-14|w06|bot|195"],"hero":"h2-1|held_ringborke|214|bot|glutklinge||260|false|","bookings":["c2-2|ch_belagerung|bot|180|22"],"new_bookings":[],"draft_roster":["p2-3|w04|bot|230|false","p2-4|w02|bot|150|false","p2-5|w06|bot|195|false","p2-6|w04|bot|230|false","p2-7|w08|bot|295|false","p2-8|w10|bot|270|false","p2-9|w02|bot|150|false","p2-10|w04|bot|230|false","p2-11|w06|bot|195|false","p2-12|w04|bot|230|false","p2-13|w02|bot|150|false","p2-14|w06|bot|195|false"],"draft_hero":"h2-1|held_ringborke|214|bot|glutklinge||260|false|","boss_lane":"","undo":0},{"gold":1635,"draft_gold":1635,"ready":true,"earned":295,"spent":0,"next_seq":14,"roster":["p3-2|g04|top|220","p3-3|g02|top|135","p3-4|g06|top|205","p3-5|g08|top|285","p3-6|g04|top|220","p3-7|g10|top|255","p3-8|g02|top|135","p3-9|g06|top|205","p3-10|g04|top|220","p3-11|g02|top|135","p3-12|g06|top|205","p3-13|g04|top|220"],"hero":"h3-1|held_ringborke|325|top|basaltschild||260|false|","bookings":[],"new_bookings":[],"draft_roster":["p3-2|g04|top|220|false","p3-3|g02|top|135|false","p3-4|g06|top|205|false","p3-5|g08|top|285|false","p3-6|g04|top|220|false","p3-7|g10|top|255|false","p3-8|g02|top|135|false","p3-9|g06|top|205|false","p3-10|g04|top|220|false","p3-11|g02|top|135|false","p3-12|g06|top|205|false","p3-13|g04|top|220|false"],"draft_hero":"h3-1|held_ringborke|325|top|basaltschild||260|false|","boss_lane":"","undo":0},{"gold":1405,"draft_gold":1405,"ready":true,"earned":295,"spent":0,"next_seq":15,"roster":["p4-3|w04|mid|230","p4-4|w06|mid|195","p4-5|w02|mid|150","p4-6|w04|mid|230","p4-7|w08|mid|295","p4-8|w10|mid|270","p4-9|w06|mid|195","p4-10|w04|mid|230","p4-11|w02|mid|150","p4-12|w04|mid|230","p4-13|w06|mid|195","p4-14|w02|mid|150"],"hero":"h4-1|held_ringborke|307|mid|basaltschild||260|false|","bookings":["c4-2|ch_schutz|mid|150|22"],"new_bookings":[],"draft_roster":["p4-3|w04|mid|230|false","p4-4|w06|mid|195|false","p4-5|w02|mid|150|false","p4-6|w04|mid|230|false","p4-7|w08|mid|295|false","p4-8|w10|mid|270|false","p4-9|w06|mid|195|false","p4-10|w04|mid|230|false","p4-11|w02|mid|150|false","p4-12|w04|mid|230|false","p4-13|w06|mid|195|false","p4-14|w02|mid|150|false"],"draft_hero":"h4-1|held_ringborke|307|mid|basaltschild||260|false|","boss_lane":"","undo":0},{"gold":1475,"draft_gold":1475,"ready":true,"earned":295,"spent":0,"next_seq":15,"roster":["p5-3|g02|bot|135","p5-4|g06|bot|205","p5-5|g04|bot|220","p5-6|g08|bot|285","p5-7|g02|bot|135","p5-8|g06|bot|205","p5-9|g02|bot|135","p5-10|g04|bot|220","p5-11|g10|bot|255","p5-12|g02|bot|135","p5-13|g06|bot|205","p5-14|g08|bot|285"],"hero":"h5-1|held_funkenlanze|499|bot|glutklinge||260|false|","bookings":["c5-2|ch_belagerung|bot|180|22"],"new_bookings":[],"draft_roster":["p5-3|g02|bot|135|false","p5-4|g06|bot|205|false","p5-5|g04|bot|220|false","p5-6|g08|bot|285|false","p5-7|g02|bot|135|false","p5-8|g06|bot|205|false","p5-9|g02|bot|135|false","p5-10|g04|bot|220|false","p5-11|g10|bot|255|false","p5-12|g02|bot|135|false","p5-13|g06|bot|205|false","p5-14|g08|bot|285|false"],"draft_hero":"h5-1|held_funkenlanze|499|bot|glutklinge||260|false|","boss_lane":"","undo":0}],"buildings":[7500.0,6000.0,7500.0,6000.0,7500.0,6000.0,9000.0,9000.0,12000.0,5120.9999999999945,0.0,0.0,0.0,7500.0,3938.1999999999953,2569.862500000001,4614.7750000000005,12000.0],"boss":{"next":1,"settled":21,"claim":""},"boss_log":[],"announcements":["champion|0|0|top|ch_druck|0","champion|0|1|mid|ch_schutz|0","champion|0|2|bot|ch_belagerung|0","champion|1|4|mid|ch_schutz|0","champion|1|5|bot|ch_belagerung|0"],"settlement":{"round":21,"gains":[315,315,315,145,145,145],"income":150,"lost":["rot_mid_outer","rot_top_outer","rot_mid_inner"],"end_reason":"cleared","combat_time":121.79999999999522,"boss":"none","lane_kills":{"mid":14,"bot":14,"top":14},"xp":{"h1-1":712,"h4-1":307,"h5-1":499,"h2-1":214,"h3-1":325,"h0-1":592}},"combat":{"round":21,"steps":2436,"elapsed":121.79999999999522,"finished":true,"end_reason":"cleared","destroyed":[],"grotto":"none|-1|-1|true","grotto_boss":"","grotto_boss_hp":0.0,"events":123,"mobile":[0,0,0]},"events":[[1,139,6.949999999999983,1,"mid","lane","monster",48,"e01",11,"",33,["h1-1"]],[2,145,7.249999999999982,0,"mid","lane","monster",27,"e01",11,"",33,["h4-1"]],[3,180,8.999999999999993,1,"mid","lane","monster",49,"e02",22,"",33,["h1-1"]],[4,186,9.299999999999997,0,"mid","lane","monster",28,"e02",22,"",33,["h4-1"]],[5,234,11.700000000000031,0,"bot","lane","monster",34,"e01",11,"",33,["h5-1"]],[6,234,11.700000000000031,1,"bot","lane","monster",55,"e01",11,"",33,["h2-1"]],[7,237,11.850000000000033,0,"top","lane","monster",20,"e01",11,"",33,["h3-1"]],[8,243,12.150000000000038,1,"mid","lane","troop",114,"w04",0,"",15,["h1-1"]],[9,245,12.250000000000039,1,"top","lane","monster",41,"e01",11,"",33,["h0-1"]],[10,268,13.400000000000055,0,"mid","lane","troop",75,"g04",0,"",15,["h4-1"]],[11,271,13.550000000000058,0,"top","lane","troop",64,"w02",0,"",15,["h3-1"]],[12,289,14.45000000000007,1,"top","lane","troop",103,"g04",0,"",15,["h0-1"]],[13,295,14.750000000000075,1,"bot","lane","troop",126,"g04",0,"",15,["h2-1"]],[14,302,15.10000000000008,0,"bot","lane","hero",87,"w04",0,"",15,["h5-1"]],[15,308,15.400000000000084,0,"mid","lane","troop",74,"g04",0,"",15,["h4-1"]],[16,319,15.950000000000092,0,"top","lane","troop",63,"w04",0,"",15,["h3-1"]],[17,326,16.300000000000097,1,"bot","lane","troop",130,"g02",0,"",15,[]],[18,341,17.050000000000107,1,"mid","lane","troop",116,"w04",0,"",15,["h1-1"]],[19,343,17.15000000000011,1,"mid","lane","troop",115,"w04",0,"",15,["h1-1"]],[20,351,17.550000000000114,1,"top","lane","troop",107,"g02",0,"",15,["h0-1"]],[21,352,17.600000000000115,1,"top","lane","troop",102,"g04",0,"",15,["h0-1"]],[22,354,17.700000000000117,0,"mid","lane","troop",79,"g02",0,"",15,["h4-1"]],[23,362,18.100000000000122,0,"bot","lane","troop",91,"w04",0,"",15,["h5-1"]],[24,378,18.900000000000134,1,"bot","lane","troop",127,"g04",0,"",15,[]],[25,393,19.650000000000144,1,"top","lane","troop",106,"g02",0,"",15,["h0-1"]],[26,396,19.800000000000146,0,"mid","lane","troop",78,"g02",0,"",15,["h4-1"]],[27,398,19.900000000000148,1,"bot","lane","troop",128,"g02",0,"",15,[]],[28,400,20.00000000000015,0,"top","lane","troop",61,"w04",0,"",15,["h3-1"]],[29,403,20.15000000000015,0,"bot","lane","troop",92,"w02",0,"",15,["h5-1"]],[30,408,20.400000000000155,0,"bot","lane","troop",88,"w04",0,"",15,["h5-1"]],[31,409,20.450000000000156,0,"mid","lane","troop",77,"g04",0,"",15,["h4-1"]],[32,410,20.500000000000156,0,"top","lane","monster",21,"e02",22,"",33,["h3-1"]],[33,410,20.500000000000156,1,"top","lane","troop",105,"g02",0,"",15,["h0-1"]],[34,421,21.050000000000164,1,"bot","lane","monster",57,"e03",18,"",33,[]],[35,424,21.200000000000166,1,"bot","lane","troop",131,"g02",0,"",15,[]],[36,444,22.20000000000018,0,"bot","lane","troop",93,"w02",0,"",15,["h5-1"]],[37,445,22.25000000000018,1,"mid","lane","troop",119,"w02",0,"",15,["h1-1"]],[38,463,23.150000000000194,1,"mid","lane","hero",113,"w04",0,"",15,["h1-1"]],[39,484,24.20000000000021,0,"bot","lane","monster",35,"e02",22,"",33,["h5-1"]],[40,487,24.35000000000021,1,"bot","lane","monster",60,"e03",18,"",33,[]],[41,493,24.650000000000215,0,"top","lane","monster",19,"e05",36,"",33,["h3-1"]],[42,496,24.800000000000217,1,"top","lane","monster",40,"e05",36,"",33,["h0-1"]],[43,508,25.400000000000226,1,"bot","lane","troop",129,"g02",0,"",15,[]],[44,511,25.550000000000228,0,"mid","lane","troop",76,"g04",0,"",15,[]],[45,519,25.950000000000234,1,"top","lane","monster",42,"e02",22,"",33,["h0-1"]],[46,529,26.45000000000024,0,"bot","lane","monster",33,"e05",36,"",33,["h5-1"]],[47,536,26.800000000000246,0,"top","lane","troop",62,"w04",0,"",15,["h3-1"]],[48,538,26.900000000000247,1,"mid","lane","troop",118,"w02",0,"",15,["h1-1"]],[49,545,27.250000000000252,1,"mid","lane","troop",120,"w02",0,"",15,["h1-1"]],[50,551,27.550000000000257,1,"bot","lane","monster",54,"e05",36,"",33,[]],[51,553,27.650000000000258,1,"top","lane","hero",100,"w04",0,"",15,["h0-1"]],[52,556,27.80000000000026,0,"mid","lane","monster",26,"e05",36,"",33,[]],[53,564,28.200000000000266,1,"mid","lane","troop",117,"w04",0,"",15,["h1-1"]],[54,580,29.000000000000277,0,"top","lane","monster",22,"e03",18,"",33,[]],[55,589,29.450000000000284,1,"bot","lane","monster",56,"e02",22,"",33,[]],[56,591,29.550000000000285,0,"bot","lane","troop",89,"w04",0,"",15,["h5-1"]],[57,599,29.95000000000029,0,"mid","lane","monster",29,"e03",18,"",33,[]],[58,606,30.300000000000296,1,"top","lane","troop",101,"g04",0,"",15,["h0-1"]],[59,614,30.7000000000003,0,"bot","lane","troop",94,"w02",0,"",15,["h5-1"]],[60,626,31.30000000000031,0,"top","lane","monster",25,"e03",18,"",33,[]],[61,627,31.35000000000031,1,"mid","lane","monster",47,"e05",36,"",33,["h1-1"]],[62,636,31.800000000000317,1,"top","lane","troop",104,"g04",0,"",15,["h0-1"]],[63,645,32.250000000000306,0,"mid","lane","monster",32,"e03",18,"",33,[]],[64,647,32.3500000000003,0,"top","lane","monster",23,"e06",22,"",33,[]],[65,654,32.70000000000028,1,"bot","lane","troop",138,"g10",0,"",15,[]],[66,674,33.70000000000022,1,"top","lane","monster",43,"e03",18,"",33,["h0-1"]],[67,677,33.850000000000215,0,"bot","lane","troop",90,"w04",0,"",15,["h5-1"]],[68,681,34.0500000000002,1,"bot","lane","monster",58,"e06",22,"",33,[]],[69,687,34.350000000000186,0,"mid","lane","monster",30,"e06",22,"",33,[]],[70,690,34.50000000000018,1,"mid","lane","monster",50,"e03",18,"",33,["h1-1"]],[71,691,34.550000000000175,1,"mid","lane","monster",53,"e03",18,"",33,["h1-1"]],[72,697,34.85000000000016,1,"top","lane","monster",46,"e03",18,"",33,["h0-1"]],[73,711,35.55000000000012,0,"top","lane","troop",66,"w08",0,"",15,[]],[74,720,36.00000000000009,0,"bot","lane","monster",36,"e03",18,"",33,["h5-1"]],[75,738,36.90000000000004,1,"top","lane","monster",44,"e06",22,"",33,["h0-1"]],[76,740,37.000000000000036,0,"bot","lane","monster",39,"e03",18,"",33,["h5-1"]],[77,773,38.64999999999994,1,"mid","lane","monster",51,"e06",22,"",33,["h1-1"]],[78,774,38.69999999999994,0,"top","lane","monster",24,"e04",18,"",33,[]],[79,782,39.099999999999916,0,"bot","lane","monster",37,"e06",22,"",33,["h5-1"]],[80,790,39.49999999999989,0,"mid","lane","troop",85,"g10",0,"",15,[]],[81,798,39.89999999999987,1,"top","lane","troop",112,"g10",0,"",15,["h0-1"]],[82,814,40.699999999999825,1,"mid","lane","troop",125,"w10",0,"",15,["h1-1"]],[83,815,40.74999999999982,0,"top","lane","troop",65,"w08",0,"",15,[]],[84,824,41.1999999999998,1,"bot","lane","troop",133,"g08",0,"",15,[]],[85,831,41.54999999999978,1,"bot","lane","monster",59,"e04",18,"",33,[]],[86,845,42.24999999999974,0,"bot","lane","troop",99,"w10",0,"",15,["h5-1"]],[87,858,42.8999999999997,1,"mid","lane","troop",121,"w08",0,"",15,["h1-1"]],[88,863,43.149999999999686,1,"top","lane","troop",108,"g08",0,"",15,["h0-1"]],[89,865,43.24999999999968,1,"bot","lane","hero",134,"g05",0,"",15,[]],[90,875,43.74999999999965,1,"bot","lane","troop",132,"g08",0,"",15,[]],[91,878,43.89999999999964,1,"top","lane","monster",45,"e04",18,"",33,["h0-1"]],[92,909,45.449999999999555,0,"bot","lane","troop",95,"w08",0,"",15,[]],[93,926,46.29999999999951,1,"mid","lane","troop",122,"w06",0,"",15,["h1-1"]],[94,934,46.699999999999484,0,"top","lane","troop",68,"w06",0,"",15,[]],[95,956,47.79999999999942,0,"top","lane","troop",73,"w10",0,"",15,[]],[96,965,48.249999999999396,1,"bot","lane","troop",137,"g06",0,"",15,[]],[97,978,48.89999999999936,1,"top","lane","troop",111,"g06",0,"",15,["h0-1"]],[98,983,49.149999999999345,1,"top","lane","troop",110,"g06",0,"",15,["h0-1"]],[99,986,49.299999999999336,1,"mid","lane","troop",124,"w06",0,"",15,["h1-1"]],[100,988,49.39999999999933,1,"mid","lane","troop",123,"w06",0,"",15,["h1-1"]],[101,1005,50.24999999999928,0,"bot","lane","monster",38,"e04",18,"",33,[]],[102,1007,50.34999999999928,1,"bot","lane","troop",135,"g06",0,"",15,[]],[103,1019,50.94999999999924,1,"top","lane","troop",109,"g06",0,"",15,["h0-1"]],[104,1029,51.449999999999214,1,"mid","lane","monster",52,"e04",18,"",33,["h1-1"]],[105,1072,53.59999999999909,1,"bot","lane","troop",136,"g06",0,"",15,[]],[106,1198,59.899999999998734,0,"bot","lane","troop",98,"w06",0,"",15,[]],[107,1206,60.29999999999871,0,"top","lane","troop",72,"w06",0,"",15,[]],[108,1278,63.899999999998506,0,"bot","lane","troop",96,"w06",0,"",15,[]],[109,1325,66.24999999999838,1,"mid","lane","tower",13,"rot_mid_outer",150,"rot_mid_outer",60,["h1-1"]],[110,1418,70.89999999999812,0,"bot","lane","troop",97,"w06",0,"",15,[]],[111,1426,71.29999999999809,0,"top","lane","hero",67,"g05",0,"",15,[]],[112,1458,72.899999999998,1,"top","lane","tower",11,"rot_top_outer",150,"rot_top_outer",60,[]],[113,1537,76.84999999999778,0,"mid","lane","monster",31,"e04",18,"",33,[]],[114,1679,83.94999999999737,0,"top","lane","troop",70,"w06",0,"",15,[]],[115,1735,86.74999999999721,1,"mid","lane","tower",12,"rot_mid_inner",210,"rot_mid_inner",60,["h1-1"]],[116,1759,87.94999999999715,0,"top","lane","troop",69,"w06",0,"",15,[]],[117,1899,94.94999999999675,0,"top","lane","troop",71,"w06",0,"",15,[]],[118,2185,109.24999999999594,0,"mid","lane","troop",86,"g10",0,"",15,[]],[119,2192,109.59999999999592,0,"mid","lane","hero",84,"w10",0,"",15,[]],[120,2253,112.64999999999574,0,"mid","lane","troop",80,"g08",0,"",15,[]],[121,2373,118.6499999999954,0,"mid","lane","troop",82,"g06",0,"",15,[]],[122,2376,118.79999999999539,0,"mid","lane","troop",81,"g06",0,"",15,[]],[123,2436,121.79999999999522,0,"mid","lane","troop",83,"g06",0,"",15,[]]]}],"results":[["begin",-1,"",true,""]]},"high_wave_137":{"title":"Hohe Welle über 100: Werte, Belohnungen und Kampf bleiben endlich","snapshots":[{"label":"spawned","phase":1,"round":137,"winner":-2,"end_note":"","players":[{"gold":37030,"draft_gold":37030,"ready":true,"earned":0,"spent":0,"next_seq":15,"roster":["p0-3|g04|top|220","p0-4|g06|top|205","p0-5|g02|top|135","p0-6|g10|top|255","p0-7|g04|top|220","p0-8|g08|top|285","p0-9|g06|top|205","p0-10|g02|top|135","p0-11|g04|top|220","p0-12|g06|top|205","p0-13|g10|top|255","p0-14|g04|top|220"],"hero":"h0-1|held_quellgeflecht|0|top|quellamulett||260|false|","bookings":["c0-2|ch_schutz|top|150|138"],"new_bookings":["c0-2|ch_schutz|top|150"],"draft_roster":["p0-3|g04|top|220|true","p0-4|g06|top|205|true","p0-5|g02|top|135|true","p0-6|g10|top|255|true","p0-7|g04|top|220|true","p0-8|g08|top|285|true","p0-9|g06|top|205|true","p0-10|g02|top|135|true","p0-11|g04|top|220|true","p0-12|g06|top|205|true","p0-13|g10|top|255|true","p0-14|g04|top|220|true"],"draft_hero":"h0-1|held_quellgeflecht|0|top|quellamulett||260|true|quellamulett","boss_lane":"","undo":0},{"gold":37080,"draft_gold":37080,"ready":true,"earned":0,"spent":0,"next_seq":15,"roster":["p1-3|w04|mid|230","p1-4|w02|mid|150","p1-5|w06|mid|195","p1-6|w04|mid|230","p1-7|w08|mid|295","p1-8|w10|mid|270","p1-9|w02|mid|150","p1-10|w04|mid|230","p1-11|w06|mid|195","p1-12|w04|mid|230","p1-13|w02|mid|150","p1-14|w06|mid|195"],"hero":"h1-1|held_ringborke|0|mid|glutklinge||260|false|","bookings":["c1-2|ch_belagerung|mid|180|138"],"new_bookings":["c1-2|ch_belagerung|mid|180"],"draft_roster":["p1-3|w04|mid|230|true","p1-4|w02|mid|150|true","p1-5|w06|mid|195|true","p1-6|w04|mid|230|true","p1-7|w08|mid|295|true","p1-8|w10|mid|270|true","p1-9|w02|mid|150|true","p1-10|w04|mid|230|true","p1-11|w06|mid|195|true","p1-12|w04|mid|230|true","p1-13|w02|mid|150|true","p1-14|w06|mid|195|true"],"draft_hero":"h1-1|held_ringborke|0|mid|glutklinge||260|true|glutklinge","boss_lane":"","undo":0},{"gold":37340,"draft_gold":37340,"ready":true,"earned":0,"spent":0,"next_seq":14,"roster":["p2-2|g04|bot|220","p2-3|g02|bot|135","p2-4|g06|bot|205","p2-5|g08|bot|285","p2-6|g04|bot|220","p2-7|g10|bot|255","p2-8|g02|bot|135","p2-9|g06|bot|205","p2-10|g04|bot|220","p2-11|g02|bot|135","p2-12|g06|bot|205","p2-13|g04|bot|220"],"hero":"h2-1|held_ringborke|0|bot|basaltschild||260|false|","bookings":[],"new_bookings":[],"draft_roster":["p2-2|g04|bot|220|true","p2-3|g02|bot|135|true","p2-4|g06|bot|205|true","p2-5|g08|bot|285|true","p2-6|g04|bot|220|true","p2-7|g10|bot|255|true","p2-8|g02|bot|135|true","p2-9|g06|bot|205|true","p2-10|g04|bot|220|true","p2-11|g02|bot|135|true","p2-12|g06|bot|205|true","p2-13|g04|bot|220|true"],"draft_hero":"h2-1|held_ringborke|0|bot|basaltschild||260|true|basaltschild","boss_lane":"","undo":0},{"gold":37110,"draft_gold":37110,"ready":true,"earned":0,"spent":0,"next_seq":15,"roster":["p3-3|w04|top|230","p3-4|w06|top|195","p3-5|w02|top|150","p3-6|w04|top|230","p3-7|w08|top|295","p3-8|w10|top|270","p3-9|w06|top|195","p3-10|w04|top|230","p3-11|w02|top|150","p3-12|w04|top|230","p3-13|w06|top|195","p3-14|w02|top|150"],"hero":"h3-1|held_ringborke|0|top|basaltschild||260|false|","bookings":["c3-2|ch_schutz|top|150|138"],"new_bookings":["c3-2|ch_schutz|top|150"],"draft_roster":["p3-3|w04|top|230|true","p3-4|w06|top|195|true","p3-5|w02|top|150|true","p3-6|w04|top|230|true","p3-7|w08|top|295|true","p3-8|w10|top|270|true","p3-9|w06|top|195|true","p3-10|w04|top|230|true","p3-11|w02|top|150|true","p3-12|w04|top|230|true","p3-13|w06|top|195|true","p3-14|w02|top|150|true"],"draft_hero":"h3-1|held_ringborke|0|top|basaltschild||260|true|basaltschild","boss_lane":"","undo":0},{"gold":37180,"draft_gold":37180,"ready":true,"earned":0,"spent":0,"next_seq":15,"roster":["p4-3|g02|mid|135","p4-4|g06|mid|205","p4-5|g04|mid|220","p4-6|g08|mid|285","p4-7|g02|mid|135","p4-8|g06|mid|205","p4-9|g02|mid|135","p4-10|g04|mid|220","p4-11|g10|mid|255","p4-12|g02|mid|135","p4-13|g06|mid|205","p4-14|g08|mid|285"],"hero":"h4-1|held_funkenlanze|0|mid|glutklinge||260|false|","bookings":["c4-2|ch_belagerung|mid|180|138"],"new_bookings":["c4-2|ch_belagerung|mid|180"],"draft_roster":["p4-3|g02|mid|135|true","p4-4|g06|mid|205|true","p4-5|g04|mid|220|true","p4-6|g08|mid|285|true","p4-7|g02|mid|135|true","p4-8|g06|mid|205|true","p4-9|g02|mid|135|true","p4-10|g04|mid|220|true","p4-11|g10|mid|255|true","p4-12|g02|mid|135|true","p4-13|g06|mid|205|true","p4-14|g08|mid|285|true"],"draft_hero":"h4-1|held_funkenlanze|0|mid|glutklinge||260|true|glutklinge","boss_lane":"","undo":0},{"gold":36935,"draft_gold":36935,"ready":true,"earned":0,"spent":0,"next_seq":15,"roster":["p5-3|w06|bot|195","p5-4|w04|bot|230","p5-5|w08|bot|295","p5-6|w06|bot|195","p5-7|w02|bot|150","p5-8|w10|bot|270","p5-9|w06|bot|195","p5-10|w04|bot|230","p5-11|w06|bot|195","p5-12|w04|bot|230","p5-13|w08|bot|295","p5-14|w06|bot|195"],"hero":"h5-1|held_funkenlanze|0|bot|funkenfokus||260|false|","bookings":["c5-2|ch_druck|bot|150|138"],"new_bookings":["c5-2|ch_druck|bot|150"],"draft_roster":["p5-3|w06|bot|195|true","p5-4|w04|bot|230|true","p5-5|w08|bot|295|true","p5-6|w06|bot|195|true","p5-7|w02|bot|150|true","p5-8|w10|bot|270|true","p5-9|w06|bot|195|true","p5-10|w04|bot|230|true","p5-11|w06|bot|195|true","p5-12|w04|bot|230|true","p5-13|w08|bot|295|true","p5-14|w06|bot|195|true"],"draft_hero":"h5-1|held_funkenlanze|0|bot|funkenfokus||260|true|funkenfokus","boss_lane":"","undo":0}],"buildings":[7500.0,6000.0,7500.0,6000.0,7500.0,6000.0,9000.0,9000.0,12000.0,7500.0,6000.0,7500.0,6000.0,7500.0,6000.0,9000.0,9000.0,12000.0],"boss":{"next":1,"settled":0,"claim":""},"boss_log":[],"announcements":[],"settlement":null,"combat":{"round":137,"steps":0,"elapsed":0.0,"finished":false,"end_reason":"","destroyed":[],"grotto":"none|-1|-1|true","grotto_boss":"","grotto_boss_hp":0.0,"events":0,"mobile":[60,60,0]},"wave":[["e05",20977.920000000006,612.224,129],["e01",3933.3600000000006,229.584,39],["e02",10488.960000000003,344.37600000000003,77],["e05",20977.920000000006,612.224,129],["e04",5681.520000000001,459.168,64],["e03",6555.600000000001,420.90400000000005,64],["e06",8303.760000000002,267.848,77]]},{"label":"settled","phase":2,"round":137,"winner":1,"end_note":"Ancient von Blau zerstört.","players":[{"gold":37785,"draft_gold":37030,"ready":true,"earned":755,"spent":0,"next_seq":15,"roster":["p0-3|g04|top|220","p0-4|g06|top|205","p0-5|g02|top|135","p0-6|g10|top|255","p0-7|g04|top|220","p0-8|g08|top|285","p0-9|g06|top|205","p0-10|g02|top|135","p0-11|g04|top|220","p0-12|g06|top|205","p0-13|g10|top|255","p0-14|g04|top|220"],"hero":"h0-1|held_quellgeflecht|2280|top|quellamulett||260|false|","bookings":["c0-2|ch_schutz|top|150|138"],"new_bookings":["c0-2|ch_schutz|top|150"],"draft_roster":["p0-3|g04|top|220|true","p0-4|g06|top|205|true","p0-5|g02|top|135|true","p0-6|g10|top|255|true","p0-7|g04|top|220|true","p0-8|g08|top|285|true","p0-9|g06|top|205|true","p0-10|g02|top|135|true","p0-11|g04|top|220|true","p0-12|g06|top|205|true","p0-13|g10|top|255|true","p0-14|g04|top|220|true"],"draft_hero":"h0-1|held_quellgeflecht|0|top|quellamulett||260|true|quellamulett","boss_lane":"","undo":0},{"gold":37765,"draft_gold":37080,"ready":true,"earned":685,"spent":0,"next_seq":15,"roster":["p1-3|w04|mid|230","p1-4|w02|mid|150","p1-5|w06|mid|195","p1-6|w04|mid|230","p1-7|w08|mid|295","p1-8|w10|mid|270","p1-9|w02|mid|150","p1-10|w04|mid|230","p1-11|w06|mid|195","p1-12|w04|mid|230","p1-13|w02|mid|150","p1-14|w06|mid|195"],"hero":"h1-1|held_ringborke|1220|mid|glutklinge||260|false|","bookings":["c1-2|ch_belagerung|mid|180|138"],"new_bookings":["c1-2|ch_belagerung|mid|180"],"draft_roster":["p1-3|w04|mid|230|true","p1-4|w02|mid|150|true","p1-5|w06|mid|195|true","p1-6|w04|mid|230|true","p1-7|w08|mid|295|true","p1-8|w10|mid|270|true","p1-9|w02|mid|150|true","p1-10|w04|mid|230|true","p1-11|w06|mid|195|true","p1-12|w04|mid|230|true","p1-13|w02|mid|150|true","p1-14|w06|mid|195|true"],"draft_hero":"h1-1|held_ringborke|0|mid|glutklinge||260|true|glutklinge","boss_lane":"","undo":0},{"gold":38062,"draft_gold":37340,"ready":true,"earned":722,"spent":0,"next_seq":14,"roster":["p2-2|g04|bot|220","p2-3|g02|bot|135","p2-4|g06|bot|205","p2-5|g08|bot|285","p2-6|g04|bot|220","p2-7|g10|bot|255","p2-8|g02|bot|135","p2-9|g06|bot|205","p2-10|g04|bot|220","p2-11|g02|bot|135","p2-12|g06|bot|205","p2-13|g04|bot|220"],"hero":"h2-1|held_ringborke|1026|bot|basaltschild||260|false|","bookings":[],"new_bookings":[],"draft_roster":["p2-2|g04|bot|220|true","p2-3|g02|bot|135|true","p2-4|g06|bot|205|true","p2-5|g08|bot|285|true","p2-6|g04|bot|220|true","p2-7|g10|bot|255|true","p2-8|g02|bot|135|true","p2-9|g06|bot|205|true","p2-10|g04|bot|220|true","p2-11|g02|bot|135|true","p2-12|g06|bot|205|true","p2-13|g04|bot|220|true"],"draft_hero":"h2-1|held_ringborke|0|bot|basaltschild||260|true|basaltschild","boss_lane":"","undo":0},{"gold":37973,"draft_gold":37110,"ready":true,"earned":863,"spent":0,"next_seq":15,"roster":["p3-3|w04|top|230","p3-4|w06|top|195","p3-5|w02|top|150","p3-6|w04|top|230","p3-7|w08|top|295","p3-8|w10|top|270","p3-9|w06|top|195","p3-10|w04|top|230","p3-11|w02|top|150","p3-12|w04|top|230","p3-13|w06|top|195","p3-14|w02|top|150"],"hero":"h3-1|held_ringborke|1399|top|basaltschild||260|false|","bookings":["c3-2|ch_schutz|top|150|138"],"new_bookings":["c3-2|ch_schutz|top|150"],"draft_roster":["p3-3|w04|top|230|true","p3-4|w06|top|195|true","p3-5|w02|top|150|true","p3-6|w04|top|230|true","p3-7|w08|top|295|true","p3-8|w10|top|270|true","p3-9|w06|top|195|true","p3-10|w04|top|230|true","p3-11|w02|top|150|true","p3-12|w04|top|230|true","p3-13|w06|top|195|true","p3-14|w02|top|150|true"],"draft_hero":"h3-1|held_ringborke|0|top|basaltschild||260|true|basaltschild","boss_lane":"","undo":0},{"gold":38145,"draft_gold":37180,"ready":true,"earned":965,"spent":0,"next_seq":15,"roster":["p4-3|g02|mid|135","p4-4|g06|mid|205","p4-5|g04|mid|220","p4-6|g08|mid|285","p4-7|g02|mid|135","p4-8|g06|mid|205","p4-9|g02|mid|135","p4-10|g04|mid|220","p4-11|g10|mid|255","p4-12|g02|mid|135","p4-13|g06|mid|205","p4-14|g08|mid|285"],"hero":"h4-1|held_funkenlanze|2310|mid|glutklinge||260|false|","bookings":["c4-2|ch_belagerung|mid|180|138"],"new_bookings":["c4-2|ch_belagerung|mid|180"],"draft_roster":["p4-3|g02|mid|135|true","p4-4|g06|mid|205|true","p4-5|g04|mid|220|true","p4-6|g08|mid|285|true","p4-7|g02|mid|135|true","p4-8|g06|mid|205|true","p4-9|g02|mid|135|true","p4-10|g04|mid|220|true","p4-11|g10|mid|255|true","p4-12|g02|mid|135|true","p4-13|g06|mid|205|true","p4-14|g08|mid|285|true"],"draft_hero":"h4-1|held_funkenlanze|0|mid|glutklinge||260|true|glutklinge","boss_lane":"","undo":0},{"gold":37899,"draft_gold":36935,"ready":true,"earned":964,"spent":0,"next_seq":15,"roster":["p5-3|w06|bot|195","p5-4|w04|bot|230","p5-5|w08|bot|295","p5-6|w06|bot|195","p5-7|w02|bot|150","p5-8|w10|bot|270","p5-9|w06|bot|195","p5-10|w04|bot|230","p5-11|w06|bot|195","p5-12|w04|bot|230","p5-13|w08|bot|295","p5-14|w06|bot|195"],"hero":"h5-1|held_funkenlanze|2310|bot|funkenfokus||260|false|","bookings":["c5-2|ch_druck|bot|150|138"],"new_bookings":["c5-2|ch_druck|bot|150"],"draft_roster":["p5-3|w06|bot|195|true","p5-4|w04|bot|230|true","p5-5|w08|bot|295|true","p5-6|w06|bot|195|true","p5-7|w02|bot|150|true","p5-8|w10|bot|270|true","p5-9|w06|bot|195|true","p5-10|w04|bot|230|true","p5-11|w06|bot|195|true","p5-12|w04|bot|230|true","p5-13|w08|bot|295|true","p5-14|w06|bot|195|true"],"draft_hero":"h5-1|held_funkenlanze|0|bot|funkenfokus||260|true|funkenfokus","boss_lane":"","undo":0}],"buildings":[7500.0,6000.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,7500.0,6000.0,7500.0,6000.0,0.0,453.4965200000004,12000.0],"boss":{"next":1,"settled":137,"claim":""},"boss_log":[],"announcements":[],"settlement":{"round":137,"gains":[755,685,722,863,965,964],"income":150,"lost":["blau_bot_outer","blau_mid_outer","rot_top_outer","blau_mid_inner","blau_bot_inner","rot_top_inner","blau_base_2","rot_base_1","blau_base_1","blau_ancient"],"end_reason":"core","combat_time":96.99999999999663,"boss":"none","lane_kills":{"mid":12,"top":11,"bot":13},"xp":{"h4-1":2310,"h1-1":1220,"h0-1":2280,"h2-1":1026,"h3-1":1399,"h5-1":2310}},"combat":{"round":137,"steps":1940,"elapsed":96.99999999999663,"finished":true,"end_reason":"core","destroyed":[0],"grotto":"none|-1|-1|true","grotto_boss":"","grotto_boss_hp":0.0,"events":103,"mobile":[9,18,0]},"events":[[1,159,7.94999999999998,0,"mid","lane","monster",27,"e01",39,"",149,["h4-1"]],[2,159,7.94999999999998,1,"mid","lane","monster",48,"e01",39,"",149,["h1-1"]],[3,201,10.050000000000008,1,"mid","lane","troop",116,"g02",0,"",15,["h1-1"]],[4,242,12.100000000000037,0,"mid","lane","monster",28,"e02",77,"",149,["h4-1"]],[5,247,12.35000000000004,1,"top","lane","monster",41,"e01",39,"",149,["h0-1"]],[6,247,12.35000000000004,1,"bot","lane","monster",55,"e01",39,"",149,["h2-1"]],[7,248,12.400000000000041,0,"top","lane","monster",20,"e01",39,"",149,["h3-1"]],[8,251,12.550000000000043,0,"bot","lane","monster",34,"e01",39,"",149,["h5-1"]],[9,260,13.00000000000005,1,"mid","lane","monster",49,"e02",77,"",149,["h1-1"]],[10,263,13.150000000000052,0,"mid","lane","troop",79,"w02",0,"",15,["h4-1"]],[11,268,13.400000000000055,1,"bot","lane","troop",126,"w04",0,"",15,["h2-1"]],[12,269,13.450000000000056,1,"top","lane","troop",103,"w04",0,"",15,["h0-1"]],[13,270,13.500000000000057,0,"top","lane","troop",64,"g04",0,"",15,["h3-1"]],[14,272,13.600000000000058,0,"bot","lane","hero",87,"w04",0,"",15,["h5-1"]],[15,281,14.050000000000065,1,"mid","lane","troop",114,"g04",0,"",15,["h1-1"]],[16,282,14.100000000000065,0,"mid","lane","troop",77,"w04",0,"",15,["h4-1"]],[17,291,14.550000000000072,1,"bot","lane","troop",127,"w04",0,"",15,[]],[18,292,14.600000000000072,1,"top","lane","troop",102,"w04",0,"",15,["h0-1"]],[19,295,14.750000000000075,0,"bot","lane","troop",91,"g04",0,"",15,["h5-1"]],[20,302,15.10000000000008,1,"mid","lane","troop",115,"g02",0,"",15,["h1-1"]],[21,303,15.15000000000008,0,"mid","lane","troop",75,"w04",0,"",15,["h4-1"]],[22,303,15.15000000000008,1,"mid","lane","troop",113,"g04",0,"",15,["h1-1"]],[23,309,15.450000000000085,1,"top","lane","troop",107,"w02",0,"",15,["h0-1"]],[24,310,15.500000000000085,0,"top","lane","troop",63,"g04",0,"",15,["h3-1"]],[25,315,15.750000000000089,0,"bot","lane","troop",88,"g04",0,"",15,["h5-1"]],[26,316,15.80000000000009,0,"bot","lane","troop",92,"g02",0,"",15,["h5-1"]],[27,317,15.85000000000009,0,"top","lane","troop",62,"g04",0,"",15,["h3-1"]],[28,323,16.150000000000095,0,"mid","lane","troop",81,"w02",0,"",15,["h4-1"]],[29,324,16.200000000000095,0,"mid","lane","hero",74,"w04",0,"",15,["h4-1"]],[30,339,16.950000000000106,0,"bot","lane","troop",93,"g02",0,"",15,["h5-1"]],[31,339,16.950000000000106,1,"bot","lane","troop",129,"w02",0,"",15,[]],[32,343,17.15000000000011,1,"bot","lane","troop",128,"w04",0,"",15,[]],[33,355,17.750000000000117,1,"top","lane","troop",106,"w02",0,"",15,["h0-1"]],[34,358,17.90000000000012,0,"bot","lane","troop",94,"g02",0,"",15,["h5-1"]],[35,406,20.300000000000153,0,"mid","lane","troop",76,"w04",0,"",15,["h4-1"]],[36,412,20.600000000000158,1,"top","lane","monster",42,"e02",77,"",149,["h0-1"]],[37,432,21.600000000000172,1,"top","lane","troop",101,"w04",0,"",15,["h0-1"]],[38,443,22.15000000000018,1,"mid","lane","troop",117,"g02",0,"",15,[]],[39,449,22.450000000000184,0,"top","lane","troop",61,"g04",0,"",15,["h3-1"]],[40,449,22.450000000000184,0,"mid","lane","troop",80,"w02",0,"",15,["h4-1"]],[41,453,22.650000000000187,0,"top","lane","monster",21,"e02",77,"",149,["h3-1"]],[42,491,24.550000000000214,1,"bot","lane","monster",54,"e05",129,"",149,[]],[43,506,25.300000000000225,0,"mid","lane","monster",26,"e05",129,"",149,["h4-1"]],[44,528,26.40000000000024,0,"mid","lane","troop",78,"w04",0,"",15,["h4-1"]],[45,538,26.900000000000247,0,"bot","lane","monster",33,"e05",129,"",149,["h5-1"]],[46,549,27.450000000000255,1,"mid","lane","monster",50,"e05",129,"",149,[]],[47,569,28.45000000000027,0,"top","lane","troop",65,"g02",0,"",15,["h3-1"]],[48,570,28.50000000000027,1,"top","lane","monster",40,"e05",129,"",149,["h0-1"]],[49,571,28.55000000000027,1,"mid","lane","troop",118,"g02",0,"",15,[]],[50,574,28.700000000000273,0,"top","lane","troop",66,"g02",0,"",15,["h3-1"]],[51,574,28.700000000000273,1,"top","lane","troop",105,"w02",0,"",15,["h0-1"]],[52,580,29.000000000000277,0,"bot","lane","monster",35,"e02",77,"",149,["h5-1"]],[53,594,29.700000000000287,0,"top","lane","monster",19,"e05",129,"",149,["h3-1"]],[54,643,32.15000000000031,0,"bot","lane","troop",89,"g04",0,"",15,["h5-1"]],[55,682,34.1000000000002,0,"bot","lane","troop",90,"g04",0,"",15,["h5-1"]],[56,697,34.85000000000016,1,"top","lane","hero",100,"w04",0,"",15,["h0-1"]],[57,709,35.450000000000124,0,"mid","lane","monster",29,"e05",129,"",149,["h4-1"]],[58,711,35.55000000000012,1,"mid","lane","monster",47,"e05",129,"",149,[]],[59,712,35.600000000000115,1,"bot","lane","monster",57,"e05",129,"",149,[]],[60,750,37.50000000000001,0,"bot","lane","monster",36,"e05",129,"",149,["h5-1"]],[61,760,37.99999999999998,1,"top","lane","troop",104,"w04",0,"",15,["h0-1"]],[62,775,38.749999999999936,1,"bot","lane","monster",56,"e02",77,"",149,[]],[63,814,40.699999999999825,0,"mid","lane","monster",31,"e03",64,"",149,["h4-1"]],[64,814,40.699999999999825,1,"top","lane","monster",43,"e05",129,"",149,["h0-1"]],[65,814,40.699999999999825,1,"mid","lane","monster",52,"e03",64,"",149,[]],[66,817,40.84999999999982,0,"top","lane","monster",22,"e05",129,"",149,[]],[67,875,43.74999999999965,1,"mid","lane","troop",125,"g10",0,"",15,[]],[68,879,43.94999999999964,0,"top","lane","troop",72,"g10",0,"",15,[]],[69,951,47.549999999999436,0,"bot","lane","monster",39,"e06",77,"",149,["h5-1"]],[70,956,47.79999999999942,0,"bot","lane","monster",38,"e03",64,"",149,["h5-1"]],[71,959,47.94999999999941,1,"top","lane","monster",45,"e03",64,"",149,["h0-1"]],[72,962,48.099999999999405,0,"mid","lane","troop",82,"w08",0,"",15,["h4-1"]],[73,974,48.69999999999937,0,"bot","lane","troop",99,"g10",0,"",15,["h5-1"]],[74,995,49.74999999999931,0,"bot","lane","troop",95,"g08",0,"",15,["h5-1"]],[75,1017,50.84999999999925,0,"mid","lane","monster",32,"e06",77,"",149,["h4-1"]],[76,1033,51.6499999999992,0,"bot","lane","troop",98,"g06",0,"",15,["h5-1"]],[77,1039,51.949999999999186,0,"mid","lane","troop",86,"w10",0,"",15,["h4-1"]],[78,1056,52.79999999999914,1,"bot","lane","monster",60,"e06",77,"",149,[]],[79,1062,53.09999999999912,1,"top","lane","monster",46,"e06",77,"",149,["h0-1"]],[80,1088,54.399999999999046,1,"top","lane","troop",112,"w10",0,"",15,["h0-1"]],[81,1105,55.249999999999,1,"top","lane","troop",108,"w08",0,"",15,["h0-1"]],[82,1116,55.79999999999897,0,"bot","lane","monster",37,"e04",64,"",149,["h5-1"]],[83,1116,55.79999999999897,1,"bot","lane","monster",59,"e03",64,"",149,[]],[84,1136,56.79999999999891,0,"bot","lane","troop",97,"g06",0,"",15,["h5-1"]],[85,1156,57.79999999999885,0,"bot","lane","troop",96,"g06",0,"",15,["h5-1"]],[86,1162,58.099999999998836,0,"mid","lane","monster",30,"e04",64,"",149,["h4-1"]],[87,1184,59.199999999998774,0,"mid","lane","troop",84,"w06",0,"",15,["h4-1"]],[88,1206,60.29999999999871,0,"mid","lane","troop",83,"w06",0,"",15,["h4-1"]],[89,1210,60.4999999999987,1,"top","lane","monster",44,"e04",64,"",149,["h0-1"]],[90,1225,61.24999999999866,0,"mid","lane","troop",85,"w06",0,"",15,["h4-1"]],[91,1232,61.59999999999864,1,"top","lane","troop",109,"w06",0,"",15,["h0-1"]],[92,1233,61.649999999998634,1,"top","lane","troop",110,"w06",0,"",15,["h0-1"]],[93,1255,62.74999999999857,1,"top","lane","troop",111,"w06",0,"",15,["h0-1"]],[94,1318,65.8999999999984,0,"bot","lane","tower",6,"blau_bot_outer",150,"blau_bot_outer",60,["h5-1"]],[95,1349,67.44999999999831,0,"mid","lane","tower",4,"blau_mid_outer",150,"blau_mid_outer",60,["h4-1"]],[96,1382,69.09999999999822,1,"top","lane","tower",11,"rot_top_outer",150,"rot_top_outer",60,["h0-1"]],[97,1537,76.84999999999778,0,"mid","lane","tower",3,"blau_mid_inner",210,"blau_mid_inner",60,["h4-1"]],[98,1551,77.54999999999774,0,"bot","lane","tower",5,"blau_bot_inner",210,"blau_bot_inner",60,["h5-1"]],[99,1576,78.79999999999767,1,"top","lane","tower",10,"rot_top_inner",210,"rot_top_inner",60,["h0-1"]],[100,1741,87.0499999999972,0,"base","lane","tower",8,"blau_base_2",270,"blau_base_2",60,["h4-1","h5-1"]],[101,1802,90.09999999999702,1,"base","lane","tower",16,"rot_base_1",270,"rot_base_1",60,["h0-1"]],[102,1823,91.14999999999696,0,"base","lane","tower",7,"blau_base_1",270,"blau_base_1",60,["h4-1","h5-1"]],[103,1940,96.99999999999663,0,"base","lane","core",9,"blau_ancient",0,"blau_ancient",60,["h4-1","h5-1"]]]}],"results":[["begin",-1,"",true,""]]},"hero_levels":{"title":"Heldenentwicklung über Runden: Anwerben, Erfahrung, Stufen, Talente, Items (Bots)","snapshots":[{"label":"round-1","phase":0,"round":2,"winner":-2,"end_note":"","players":[{"gold":128,"draft_gold":128,"ready":true,"earned":88,"spent":180,"next_seq":4,"roster":["p0-1|g03|top|70","p0-2|g01|top|45","p0-3|g05|top|65"],"hero":"","bookings":[],"new_bookings":[],"draft_roster":["p0-1|g03|top|70|false","p0-2|g01|top|45|false","p0-3|g05|top|65|false"],"draft_hero":"","boss_lane":"","undo":0},{"gold":123,"draft_gold":123,"ready":true,"earned":88,"spent":185,"next_seq":4,"roster":["p1-1|w03|mid|75","p1-2|w05|mid|60","p1-3|w01|mid|50"],"hero":"","bookings":[],"new_bookings":[],"draft_roster":["p1-1|w03|mid|75|false","p1-2|w05|mid|60|false","p1-3|w01|mid|50|false"],"draft_hero":"","boss_lane":"","undo":0},{"gold":128,"draft_gold":128,"ready":true,"earned":88,"spent":180,"next_seq":4,"roster":["p2-1|g01|bot|45","p2-2|g05|bot|65","p2-3|g03|bot|70"],"hero":"","bookings":[],"new_bookings":[],"draft_roster":["p2-1|g01|bot|45|false","p2-2|g05|bot|65|false","p2-3|g03|bot|70|false"],"draft_hero":"","boss_lane":"","undo":0},{"gold":173,"draft_gold":173,"ready":true,"earned":88,"spent":135,"next_seq":3,"roster":["p3-1|w05|top|60","p3-2|w03|top|75"],"hero":"","bookings":[],"new_bookings":[],"draft_roster":["p3-1|w05|top|60|false","p3-2|w03|top|75|false"],"draft_hero":"","boss_lane":"","undo":0},{"gold":128,"draft_gold":128,"ready":true,"earned":88,"spent":180,"next_seq":4,"roster":["p4-1|g03|mid|70","p4-2|g05|mid|65","p4-3|g01|mid|45"],"hero":"","bookings":[],"new_bookings":[],"draft_roster":["p4-1|g03|mid|70|false","p4-2|g05|mid|65|false","p4-3|g01|mid|45|false"],"draft_hero":"","boss_lane":"","undo":0},{"gold":123,"draft_gold":123,"ready":true,"earned":88,"spent":185,"next_seq":4,"roster":["p5-1|w03|bot|75","p5-2|w01|bot|50","p5-3|w05|bot|60"],"hero":"","bookings":[],"new_bookings":[],"draft_roster":["p5-1|w03|bot|75|false","p5-2|w01|bot|50|false","p5-3|w05|bot|60|false"],"draft_hero":"","boss_lane":"","undo":0}],"buildings":[7500.0,6000.0,7500.0,6000.0,7500.0,5970.1,9000.0,9000.0,12000.0,7500.0,5851.35,7500.0,6000.0,7500.0,6000.0,9000.0,9000.0,12000.0],"boss":{"next":1,"settled":1,"claim":""},"boss_log":[],"announcements":[],"settlement":{"round":1,"gains":[18,18,18,18,18,18],"income":70,"lost":[],"end_reason":"cleared","combat_time":43.499999999999666,"boss":"none","lane_kills":{"mid":6,"bot":6,"top":6},"xp":{}},"combat":{"round":1,"steps":870,"elapsed":43.499999999999666,"finished":true,"end_reason":"cleared","destroyed":[],"grotto":"none|-1|-1|true","grotto_boss":"","grotto_boss_hp":0.0,"events":35,"mobile":[0,0,0]}},{"label":"round-2","phase":0,"round":3,"winner":-2,"end_note":"","players":[{"gold":125,"draft_gold":125,"ready":true,"earned":180,"spent":275,"next_seq":5,"roster":["p0-1|g03|top|70","p0-2|g01|top|45","p0-3|g05|top|65","p0-4|g07|top|95"],"hero":"","bookings":[],"new_bookings":[],"draft_roster":["p0-1|g03|top|70|false","p0-2|g01|top|45|false","p0-3|g05|top|65|false","p0-4|g07|top|95|false"],"draft_hero":"","boss_lane":"","undo":0},{"gold":140,"draft_gold":140,"ready":true,"earned":180,"spent":260,"next_seq":5,"roster":["p1-1|w03|mid|75","p1-2|w05|mid|60","p1-3|w01|mid|50","p1-4|w03|mid|75"],"hero":"","bookings":[],"new_bookings":[],"draft_roster":["p1-1|w03|mid|75|false","p1-2|w05|mid|60|false","p1-3|w01|mid|50|false","p1-4|w03|mid|75|false"],"draft_hero":"","boss_lane":"","undo":0},{"gold":125,"draft_gold":125,"ready":true,"earned":180,"spent":275,"next_seq":5,"roster":["p2-1|g01|bot|45","p2-2|g05|bot|65","p2-3|g03|bot|70","p2-4|g07|bot|95"],"hero":"","bookings":[],"new_bookings":[],"draft_roster":["p2-1|g01|bot|45|false","p2-2|g05|bot|65|false","p2-3|g03|bot|70|false","p2-4|g07|bot|95|false"],"draft_hero":"","boss_lane":"","undo":0},{"gold":105,"draft_gold":105,"ready":true,"earned":180,"spent":295,"next_seq":5,"roster":["p3-1|w05|top|60","p3-2|w03|top|75","p3-3|w07|top|100","p3-4|w05|top|60"],"hero":"","bookings":[],"new_bookings":[],"draft_roster":["p3-1|w05|top|60|false","p3-2|w03|top|75|false","p3-3|w07|top|100|false","p3-4|w05|top|60|false"],"draft_hero":"","boss_lane":"","undo":0},{"gold":135,"draft_gold":135,"ready":true,"earned":180,"spent":265,"next_seq":5,"roster":["p4-1|g03|mid|70","p4-2|g05|mid|65","p4-3|g01|mid|45","p4-4|g09|mid|85"],"hero":"","bookings":[],"new_bookings":[],"draft_roster":["p4-1|g03|mid|70|false","p4-2|g05|mid|65|false","p4-3|g01|mid|45|false","p4-4|g09|mid|85|false"],"draft_hero":"","boss_lane":"","undo":0},{"gold":140,"draft_gold":140,"ready":true,"earned":180,"spent":260,"next_seq":5,"roster":["p5-1|w03|bot|75","p5-2|w01|bot|50","p5-3|w05|bot|60","p5-4|w03|bot|75"],"hero":"","bookings":[],"new_bookings":[],"draft_roster":["p5-1|w03|bot|75|false","p5-2|w01|bot|50|false","p5-3|w05|bot|60|false","p5-4|w03|bot|75|false"],"draft_hero":"","boss_lane":"","undo":0}],"buildings":[7500.0,5850.500000000002,7500.0,5878.8,7500.0,5910.300000000001,9000.0,9000.0,12000.0,7500.0,5851.35,7500.0,6000.0,7500.0,6000.0,9000.0,9000.0,12000.0],"boss":{"next":1,"settled":2,"claim":""},"boss_log":[],"announcements":[],"settlement":{"round":2,"gains":[18,18,18,18,18,18],"income":74,"lost":[],"end_reason":"cleared","combat_time":49.699999999999314,"boss":"none","lane_kills":{"mid":6,"bot":6,"top":6},"xp":{}},"combat":{"round":2,"steps":994,"elapsed":49.699999999999314,"finished":true,"end_reason":"cleared","destroyed":[],"grotto":"none|-1|-1|true","grotto_boss":"","grotto_boss_hp":0.0,"events":42,"mobile":[0,0,0]}},{"label":"round-3","phase":0,"round":4,"winner":-2,"end_note":"","players":[{"gold":165,"draft_gold":165,"ready":true,"earned":290,"spent":345,"next_seq":6,"roster":["p0-1|g03|top|70","p0-2|g01|top|45","p0-3|g05|top|65","p0-4|g07|top|95","p0-5|g03|top|70"],"hero":"","bookings":[],"new_bookings":[],"draft_roster":["p0-1|g03|top|70|false","p0-2|g01|top|45|false","p0-3|g05|top|65|false","p0-4|g07|top|95|false","p0-5|g03|top|70|false"],"draft_hero":"","boss_lane":"","undo":0},{"gold":150,"draft_gold":150,"ready":true,"earned":290,"spent":360,"next_seq":6,"roster":["p1-1|w03|mid|75","p1-2|w05|mid|60","p1-3|w01|mid|50","p1-4|w03|mid|75","p1-5|w07|mid|100"],"hero":"","bookings":[],"new_bookings":[],"draft_roster":["p1-1|w03|mid|75|false","p1-2|w05|mid|60|false","p1-3|w01|mid|50|false","p1-4|w03|mid|75|false","p1-5|w07|mid|100|false"],"draft_hero":"","boss_lane":"","undo":0},{"gold":125,"draft_gold":125,"ready":true,"earned":290,"spent":385,"next_seq":7,"roster":["p2-1|g01|bot|45","p2-2|g05|bot|65","p2-3|g03|bot|70","p2-4|g07|bot|95","p2-5|g01|bot|45","p2-6|g05|bot|65"],"hero":"","bookings":[],"new_bookings":[],"draft_roster":["p2-1|g01|bot|45|false","p2-2|g05|bot|65|false","p2-3|g03|bot|70|false","p2-4|g07|bot|95|false","p2-5|g01|bot|45|false","p2-6|g05|bot|65|false"],"draft_hero":"","boss_lane":"","undo":0},{"gold":165,"draft_gold":165,"ready":true,"earned":290,"spent":345,"next_seq":6,"roster":["p3-1|w05|top|60","p3-2|w03|top|75","p3-3|w07|top|100","p3-4|w05|top|60","p3-5|w01|top|50"],"hero":"","bookings":[],"new_bookings":[],"draft_roster":["p3-1|w05|top|60|false","p3-2|w03|top|75|false","p3-3|w07|top|100|false","p3-4|w05|top|60|false","p3-5|w01|top|50|false"],"draft_hero":"","boss_lane":"","undo":0},{"gold":175,"draft_gold":175,"ready":true,"earned":290,"spent":335,"next_seq":6,"roster":["p4-1|g03|mid|70","p4-2|g05|mid|65","p4-3|g01|mid|45","p4-4|g09|mid|85","p4-5|g03|mid|70"],"hero":"","bookings":[],"new_bookings":[],"draft_roster":["p4-1|g03|mid|70|false","p4-2|g05|mid|65|false","p4-3|g01|mid|45|false","p4-4|g09|mid|85|false","p4-5|g03|mid|70|false"],"draft_hero":"","boss_lane":"","undo":0},{"gold":150,"draft_gold":150,"ready":true,"earned":290,"spent":360,"next_seq":6,"roster":["p5-1|w03|bot|75","p5-2|w01|bot|50","p5-3|w05|bot|60","p5-4|w03|bot|75","p5-5|w07|bot|100"],"hero":"","bookings":[],"new_bookings":[],"draft_roster":["p5-1|w03|bot|75|false","p5-2|w01|bot|50|false","p5-3|w05|bot|60|false","p5-4|w03|bot|75|false","p5-5|w07|bot|100|false"],"draft_hero":"","boss_lane":"","undo":0}],"buildings":[7500.0,5730.900000000003,7500.0,5878.8,7500.0,5910.300000000001,9000.0,9000.0,12000.0,7500.0,5851.35,7500.0,5836.4000000000015,7500.0,5672.4000000000005,9000.0,9000.0,12000.0],"boss":{"next":1,"settled":3,"claim":""},"boss_log":[],"announcements":[],"settlement":{"round":3,"gains":[32,32,32,32,32,32],"income":78,"lost":[],"end_reason":"cleared","combat_time":51.39999999999922,"boss":"none","lane_kills":{"mid":6,"top":6,"bot":6},"xp":{}},"combat":{"round":3,"steps":1028,"elapsed":51.39999999999922,"finished":true,"end_reason":"cleared","destroyed":[],"grotto":"none|-1|-1|true","grotto_boss":"","grotto_boss_hp":0.0,"events":49,"mobile":[0,0,0]}},{"label":"round-4","phase":0,"round":5,"winner":-2,"end_note":"","players":[{"gold":157,"draft_gold":157,"ready":true,"earned":412,"spent":475,"next_seq":8,"roster":["p0-1|g03|top|70","p0-2|g01|top|45","p0-3|g05|top|65","p0-4|g07|top|95","p0-5|g03|top|70","p0-6|g09|top|85","p0-7|g01|top|45"],"hero":"","bookings":[],"new_bookings":[],"draft_roster":["p0-1|g03|top|70|false","p0-2|g01|top|45|false","p0-3|g05|top|65|false","p0-4|g07|top|95|false","p0-5|g03|top|70|false","p0-6|g09|top|85|false","p0-7|g01|top|45|false"],"draft_hero":"","boss_lane":"","undo":0},{"gold":122,"draft_gold":122,"ready":true,"earned":412,"spent":510,"next_seq":8,"roster":["p1-1|w03|mid|75","p1-2|w05|mid|60","p1-3|w01|mid|50","p1-4|w03|mid|75","p1-5|w07|mid|100","p1-6|w09|mid|90","p1-7|w05|mid|60"],"hero":"","bookings":[],"new_bookings":[],"draft_roster":["p1-1|w03|mid|75|false","p1-2|w05|mid|60|false","p1-3|w01|mid|50|false","p1-4|w03|mid|75|false","p1-5|w07|mid|100|false","p1-6|w09|mid|90|false","p1-7|w05|mid|60|false"],"draft_hero":"","boss_lane":"","undo":0},{"gold":132,"draft_gold":132,"ready":true,"earned":412,"spent":500,"next_seq":9,"roster":["p2-1|g01|bot|45","p2-2|g05|bot|65","p2-3|g03|bot|70","p2-4|g07|bot|95","p2-5|g01|bot|45","p2-6|g05|bot|65","p2-7|g01|bot|45","p2-8|g03|bot|70"],"hero":"","bookings":[],"new_bookings":[],"draft_roster":["p2-1|g01|bot|45|false","p2-2|g05|bot|65|false","p2-3|g03|bot|70|false","p2-4|g07|bot|95|false","p2-5|g01|bot|45|false","p2-6|g05|bot|65|false","p2-7|g01|bot|45|false","p2-8|g03|bot|70|false"],"draft_hero":"","boss_lane":"","undo":0},{"gold":137,"draft_gold":137,"ready":true,"earned":412,"spent":495,"next_seq":8,"roster":["p3-1|w05|top|60","p3-2|w03|top|75","p3-3|w07|top|100","p3-4|w05|top|60","p3-5|w01|top|50","p3-6|w09|top|90","p3-7|w05|top|60"],"hero":"","bookings":[],"new_bookings":[],"draft_roster":["p3-1|w05|top|60|false","p3-2|w03|top|75|false","p3-3|w07|top|100|false","p3-4|w05|top|60|false","p3-5|w01|top|50|false","p3-6|w09|top|90|false","p3-7|w05|top|60|false"],"draft_hero":"","boss_lane":"","undo":0},{"gold":137,"draft_gold":137,"ready":true,"earned":412,"spent":495,"next_seq":8,"roster":["p4-1|g03|mid|70","p4-2|g05|mid|65","p4-3|g01|mid|45","p4-4|g09|mid|85","p4-5|g03|mid|70","p4-6|g07|top|95","p4-7|g05|top|65"],"hero":"","bookings":[],"new_bookings":[],"draft_roster":["p4-1|g03|mid|70|false","p4-2|g05|mid|65|false","p4-3|g01|mid|45|false","p4-4|g09|mid|85|false","p4-5|g03|mid|70|false","p4-6|g07|top|95|false","p4-7|g05|top|65|false"],"draft_hero":"","boss_lane":"","undo":0},{"gold":132,"draft_gold":132,"ready":true,"earned":412,"spent":500,"next_seq":8,"roster":["p5-1|w03|bot|75","p5-2|w01|bot|50","p5-3|w05|bot|60","p5-4|w03|bot|75","p5-5|w07|bot|100","p5-6|w09|bot|90","p5-7|w01|bot|50"],"hero":"","bookings":[],"new_bookings":[],"draft_roster":["p5-1|w03|bot|75|false","p5-2|w01|bot|50|false","p5-3|w05|bot|60|false","p5-4|w03|bot|75|false","p5-5|w07|bot|100|false","p5-6|w09|bot|90|false","p5-7|w01|bot|50|false"],"draft_hero":"","boss_lane":"","undo":0}],"buildings":[7500.0,2201.200000000007,7500.0,5878.8,7500.0,5910.300000000001,9000.0,9000.0,12000.0,7500.0,5851.35,7500.0,3942.840200000014,7500.0,5384.200000000002,9000.0,9000.0,12000.0],"boss":{"next":1,"settled":4,"claim":""},"boss_log":[],"announcements":[],"settlement":{"round":4,"gains":[40,40,40,40,40,40],"income":82,"lost":[],"end_reason":"cleared","combat_time":67.6999999999983,"boss":"none","lane_kills":{"mid":8,"bot":8,"top":8},"xp":{}},"combat":{"round":4,"steps":1354,"elapsed":67.6999999999983,"finished":true,"end_reason":"cleared","destroyed":[],"grotto":"none|-1|-1|true","grotto_boss":"","grotto_boss_hp":0.0,"events":67,"mobile":[0,0,0]}},{"label":"round-5","phase":0,"round":6,"winner":-2,"end_note":"","players":[{"gold":133,"draft_gold":133,"ready":true,"earned":543,"spent":630,"next_seq":9,"roster":["p0-1|g03|top|70","p0-2|g02|top|135","p0-3|g05|top|65","p0-4|g07|top|95","p0-5|g03|top|70","p0-6|g09|top|85","p0-7|g01|top|45","p0-8|g05|top|65"],"hero":"","bookings":[],"new_bookings":[],"draft_roster":["p0-1|g03|top|70|false","p0-2|g02|top|135|false","p0-3|g05|top|65|false","p0-4|g07|top|95|false","p0-5|g03|top|70|false","p0-6|g09|top|85|false","p0-7|g01|top|45|false","p0-8|g05|top|65|false"],"draft_hero":"","boss_lane":"","undo":0},{"gold":153,"draft_gold":153,"ready":true,"earned":543,"spent":610,"next_seq":8,"roster":["p1-1|w03|mid|75","p1-2|w05|mid|60","p1-3|w02|mid|150","p1-4|w03|mid|75","p1-5|w07|mid|100","p1-6|w09|mid|90","p1-7|w05|mid|60"],"hero":"","bookings":[],"new_bookings":[],"draft_roster":["p1-1|w03|mid|75|false","p1-2|w05|mid|60|false","p1-3|w02|mid|150|false","p1-4|w03|mid|75|false","p1-5|w07|mid|100|false","p1-6|w09|mid|90|false","p1-7|w05|mid|60|false"],"draft_hero":"","boss_lane":"","undo":0},{"gold":173,"draft_gold":173,"ready":true,"earned":543,"spent":590,"next_seq":9,"roster":["p2-1|g02|bot|135","p2-2|g05|bot|65","p2-3|g03|bot|70","p2-4|g07|bot|95","p2-5|g01|bot|45","p2-6|g05|bot|65","p2-7|g01|bot|45","p2-8|g03|bot|70"],"hero":"","bookings":[],"new_bookings":[],"draft_roster":["p2-1|g02|bot|135|false","p2-2|g05|bot|65|false","p2-3|g03|bot|70|false","p2-4|g07|bot|95|false","p2-5|g01|bot|45|false","p2-6|g05|bot|65|false","p2-7|g01|bot|45|false","p2-8|g03|bot|70|false"],"draft_hero":"","boss_lane":"","undo":0},{"gold":168,"draft_gold":168,"ready":true,"earned":543,"spent":595,"next_seq":8,"roster":["p3-1|w05|top|60","p3-2|w03|top|75","p3-3|w07|top|100","p3-4|w05|top|60","p3-5|w02|top|150","p3-6|w09|top|90","p3-7|w05|top|60"],"hero":"","bookings":[],"new_bookings":[],"draft_roster":["p3-1|w05|top|60|false","p3-2|w03|top|75|false","p3-3|w07|top|100|false","p3-4|w05|top|60|false","p3-5|w02|top|150|false","p3-6|w09|top|90|false","p3-7|w05|top|60|false"],"draft_hero":"","boss_lane":"","undo":0},{"gold":133,"draft_gold":133,"ready":true,"earned":543,"spent":630,"next_seq":9,"roster":["p4-1|g03|mid|70","p4-2|g05|mid|65","p4-3|g02|mid|135","p4-4|g09|mid|85","p4-5|g03|mid|70","p4-6|g07|top|95","p4-7|g05|top|65","p4-8|g01|mid|45"],"hero":"","bookings":[],"new_bookings":[],"draft_roster":["p4-1|g03|mid|70|false","p4-2|g05|mid|65|false","p4-3|g02|mid|135|false","p4-4|g09|mid|85|false","p4-5|g03|mid|70|false","p4-6|g07|top|95|false","p4-7|g05|top|65|false","p4-8|g01|mid|45|false"],"draft_hero":"","boss_lane":"","undo":0},{"gold":163,"draft_gold":163,"ready":true,"earned":543,"spent":600,"next_seq":8,"roster":["p5-1|w03|bot|75","p5-2|w02|bot|150","p5-3|w05|bot|60","p5-4|w03|bot|75","p5-5|w07|bot|100","p5-6|w09|bot|90","p5-7|w01|bot|50"],"hero":"","bookings":[],"new_bookings":[],"draft_roster":["p5-1|w03|bot|75|false","p5-2|w02|bot|150|false","p5-3|w05|bot|60|false","p5-4|w03|bot|75|false","p5-5|w07|bot|100|false","p5-6|w09|bot|90|false","p5-7|w01|bot|50|false"],"draft_hero":"","boss_lane":"","undo":0}],"buildings":[7500.0,15.6520000000051,7500.0,5878.8,7500.0,5910.300000000001,9000.0,9000.0,12000.0,7500.0,5851.35,7500.0,2376.813800000012,7500.0,4913.579199999994,9000.0,9000.0,12000.0],"boss":{"next":1,"settled":5,"claim":""},"boss_log":[],"announcements":[],"settlement":{"round":5,"gains":[45,45,45,45,45,45],"income":86,"lost":[],"end_reason":"cleared","combat_time":61.69999999999863,"boss":"none","lane_kills":{"mid":8,"bot":8,"top":8},"xp":{}},"combat":{"round":5,"steps":1234,"elapsed":61.69999999999863,"finished":true,"end_reason":"cleared","destroyed":[],"grotto":"none|-1|-1|true","grotto_boss":"","grotto_boss_hp":0.0,"events":69,"mobile":[0,0,0]}},{"label":"round-6","phase":0,"round":7,"winner":-2,"end_note":"","players":[{"gold":223,"draft_gold":223,"ready":true,"earned":723,"spent":720,"next_seq":9,"roster":["p0-1|g03|top|70","p0-2|g02|top|135","p0-3|g05|top|65","p0-4|g07|top|95","p0-5|g03|top|70","p0-6|g09|top|85","p0-7|g02|top|135","p0-8|g05|top|65"],"hero":"","bookings":[],"new_bookings":[],"draft_roster":["p0-1|g03|top|70|false","p0-2|g02|top|135|false","p0-3|g05|top|65|false","p0-4|g07|top|95|false","p0-5|g03|top|70|false","p0-6|g09|top|85|false","p0-7|g02|top|135|false","p0-8|g05|top|65|false"],"draft_hero":"","boss_lane":"","undo":0},{"gold":198,"draft_gold":198,"ready":true,"earned":723,"spent":745,"next_seq":8,"roster":["p1-1|w03|mid|75","p1-2|w06|mid|195","p1-3|w02|mid|150","p1-4|w03|mid|75","p1-5|w07|mid|100","p1-6|w09|mid|90","p1-7|w05|mid|60"],"hero":"","bookings":[],"new_bookings":[],"draft_roster":["p1-1|w03|mid|75|false","p1-2|w06|mid|195|false","p1-3|w02|mid|150|false","p1-4|w03|mid|75|false","p1-5|w07|mid|100|false","p1-6|w09|mid|90|false","p1-7|w05|mid|60|false"],"draft_hero":"","boss_lane":"","undo":0},{"gold":263,"draft_gold":263,"ready":true,"earned":723,"spent":680,"next_seq":9,"roster":["p2-1|g02|bot|135","p2-2|g05|bot|65","p2-3|g03|bot|70","p2-4|g07|bot|95","p2-5|g02|bot|135","p2-6|g05|bot|65","p2-7|g01|bot|45","p2-8|g03|bot|70"],"hero":"","bookings":[],"new_bookings":[],"draft_roster":["p2-1|g02|bot|135|false","p2-2|g05|bot|65|false","p2-3|g03|bot|70|false","p2-4|g07|bot|95|false","p2-5|g02|bot|135|false","p2-6|g05|bot|65|false","p2-7|g01|bot|45|false","p2-8|g03|bot|70|false"],"draft_hero":"","boss_lane":"","undo":0},{"gold":213,"draft_gold":213,"ready":true,"earned":723,"spent":730,"next_seq":8,"roster":["p3-1|w06|top|195","p3-2|w03|top|75","p3-3|w07|top|100","p3-4|w05|top|60","p3-5|w02|top|150","p3-6|w09|top|90","p3-7|w05|top|60"],"hero":"","bookings":[],"new_bookings":[],"draft_roster":["p3-1|w06|top|195|false","p3-2|w03|top|75|false","p3-3|w07|top|100|false","p3-4|w05|top|60|false","p3-5|w02|top|150|false","p3-6|w09|top|90|false","p3-7|w05|top|60|false"],"draft_hero":"","boss_lane":"","undo":0},{"gold":223,"draft_gold":223,"ready":true,"earned":723,"spent":720,"next_seq":9,"roster":["p4-1|g03|mid|70","p4-2|g05|mid|65","p4-3|g02|mid|135","p4-4|g09|mid|85","p4-5|g03|mid|70","p4-6|g07|top|95","p4-7|g05|top|65","p4-8|g02|mid|135"],"hero":"","bookings":[],"new_bookings":[],"draft_roster":["p4-1|g03|mid|70|false","p4-2|g05|mid|65|false","p4-3|g02|mid|135|false","p4-4|g09|mid|85|false","p4-5|g03|mid|70|false","p4-6|g07|top|95|false","p4-7|g05|top|65|false","p4-8|g02|mid|135|false"],"draft_hero":"","boss_lane":"","undo":0},{"gold":243,"draft_gold":243,"ready":true,"earned":723,"spent":700,"next_seq":8,"roster":["p5-1|w03|bot|75","p5-2|w02|bot|150","p5-3|w05|bot|60","p5-4|w03|bot|75","p5-5|w07|bot|100","p5-6|w09|bot|90","p5-7|w02|bot|150"],"hero":"","bookings":[],"new_bookings":[],"draft_roster":["p5-1|w03|bot|75|false","p5-2|w02|bot|150|false","p5-3|w05|bot|60|false","p5-4|w03|bot|75|false","p5-5|w07|bot|100|false","p5-6|w09|bot|90|false","p5-7|w02|bot|150|false"],"draft_hero":"","boss_lane":"","undo":0}],"buildings":[3828.309999999995,0.0,7500.0,5878.8,7500.0,5910.300000000001,9000.0,9000.0,12000.0,7500.0,5851.35,7103.499999999999,0.0,7500.0,4453.019199999991,9000.0,9000.0,12000.0],"boss":{"next":1,"settled":6,"claim":""},"boss_log":[],"announcements":[],"settlement":{"round":6,"gains":[90,90,90,90,90,90],"income":90,"lost":["blau_top_outer","rot_mid_outer"],"end_reason":"cleared","combat_time":68.74999999999824,"boss":"none","lane_kills":{"mid":8,"bot":8,"top":8},"xp":{}},"combat":{"round":6,"steps":1375,"elapsed":68.74999999999824,"finished":true,"end_reason":"cleared","destroyed":[],"grotto":"none|-1|-1|true","grotto_boss":"","grotto_boss_hp":0.0,"events":71,"mobile":[0,0,0]}},{"label":"round-7","phase":0,"round":8,"winner":-2,"end_note":"","players":[{"gold":165,"draft_gold":165,"ready":true,"earned":875,"spent":930,"next_seq":10,"roster":["p0-1|g03|top|70","p0-2|g02|top|135","p0-3|g06|top|205","p0-4|g07|top|95","p0-5|g03|top|70","p0-6|g09|top|85","p0-7|g02|top|135","p0-8|g05|top|65","p0-9|g03|top|70"],"hero":"","bookings":[],"new_bookings":[],"draft_roster":["p0-1|g03|top|70|false","p0-2|g02|top|135|false","p0-3|g06|top|205|false","p0-4|g07|top|95|false","p0-5|g03|top|70|false","p0-6|g09|top|85|false","p0-7|g02|top|135|false","p0-8|g05|top|65|false","p0-9|g03|top|70|false"],"draft_hero":"","boss_lane":"","undo":0},{"gold":200,"draft_gold":200,"ready":true,"earned":875,"spent":895,"next_seq":9,"roster":["p1-1|w03|mid|75","p1-2|w06|mid|195","p1-3|w02|mid|150","p1-4|w03|mid|75","p1-5|w07|mid|100","p1-6|w09|mid|90","p1-7|w05|mid|60"],"hero":"","bookings":["c1-8|ch_schutz|mid|150|8"],"new_bookings":[],"draft_roster":["p1-1|w03|mid|75|false","p1-2|w06|mid|195|false","p1-3|w02|mid|150|false","p1-4|w03|mid|75|false","p1-5|w07|mid|100|false","p1-6|w09|mid|90|false","p1-7|w05|mid|60|false"],"draft_hero":"","boss_lane":"","undo":0},{"gold":155,"draft_gold":155,"ready":true,"earned":875,"spent":940,"next_seq":10,"roster":["p2-1|g02|bot|135","p2-2|g05|bot|65","p2-3|g03|bot|70","p2-4|g07|bot|95","p2-5|g02|bot|135","p2-6|g05|bot|65","p2-7|g01|bot|45","p2-8|g03|bot|70"],"hero":"h2-9|held_funkenlanze|282|bot|||260|false|","bookings":[],"new_bookings":[],"draft_roster":["p2-1|g02|bot|135|false","p2-2|g05|bot|65|false","p2-3|g03|bot|70|false","p2-4|g07|bot|95|false","p2-5|g02|bot|135|false","p2-6|g05|bot|65|false","p2-7|g01|bot|45|false","p2-8|g03|bot|70|false"],"draft_hero":"h2-9|held_funkenlanze|282|bot|||260|false|","boss_lane":"","undo":0},{"gold":215,"draft_gold":215,"ready":true,"earned":875,"spent":880,"next_seq":9,"roster":["p3-1|w06|top|195","p3-2|w03|top|75","p3-3|w07|top|100","p3-4|w05|top|60","p3-5|w02|top|150","p3-6|w09|top|90","p3-7|w05|top|60"],"hero":"","bookings":["c3-8|ch_druck|top|150|8"],"new_bookings":[],"draft_roster":["p3-1|w06|top|195|false","p3-2|w03|top|75|false","p3-3|w07|top|100|false","p3-4|w05|top|60|false","p3-5|w02|top|150|false","p3-6|w09|top|90|false","p3-7|w05|top|60|false"],"draft_hero":"","boss_lane":"","undo":0},{"gold":155,"draft_gold":155,"ready":true,"earned":875,"spent":940,"next_seq":11,"roster":["p4-1|g03|mid|70","p4-2|g05|mid|65","p4-3|g02|mid|135","p4-4|g09|mid|85","p4-5|g03|mid|70","p4-6|g07|top|95","p4-7|g05|top|65","p4-8|g02|mid|135","p4-10|g03|mid|70"],"hero":"","bookings":["c4-9|ch_schutz|mid|150|8"],"new_bookings":[],"draft_roster":["p4-1|g03|mid|70|false","p4-2|g05|mid|65|false","p4-3|g02|mid|135|false","p4-4|g09|mid|85|false","p4-5|g03|mid|70|false","p4-6|g07|top|95|false","p4-7|g05|top|65|false","p4-8|g02|mid|135|false","p4-10|g03|mid|70|false"],"draft_hero":"","boss_lane":"","undo":0},{"gold":215,"draft_gold":215,"ready":true,"earned":875,"spent":880,"next_seq":9,"roster":["p5-1|w03|bot|75","p5-2|w02|bot|150","p5-3|w05|bot|60","p5-4|w03|bot|75","p5-5|w07|bot|100","p5-6|w09|bot|90","p5-7|w02|bot|150"],"hero":"","bookings":["c5-8|ch_belagerung|bot|180|8"],"new_bookings":[],"draft_roster":["p5-1|w03|bot|75|false","p5-2|w02|bot|150|false","p5-3|w05|bot|60|false","p5-4|w03|bot|75|false","p5-5|w07|bot|100|false","p5-6|w09|bot|90|false","p5-7|w02|bot|150|false"],"draft_hero":"","boss_lane":"","undo":0}],"buildings":[3828.309999999995,0.0,7500.0,5878.8,7500.0,5910.300000000001,9000.0,9000.0,12000.0,7500.0,4833.611200000001,3301.181200000009,0.0,7500.0,396.15279999999217,9000.0,9000.0,12000.0],"boss":{"next":1,"settled":7,"claim":""},"boss_log":[],"announcements":["champion|0|1|mid|ch_schutz|0","champion|1|3|top|ch_druck|0","champion|1|4|mid|ch_schutz|0","champion|1|5|bot|ch_belagerung|0"],"settlement":{"round":7,"gains":[58,58,58,58,58,58],"income":94,"lost":[],"end_reason":"cleared","combat_time":70.74999999999812,"boss":"none","lane_kills":{"mid":10,"bot":10,"top":10},"xp":{"h2-9":282}},"combat":{"round":7,"steps":1415,"elapsed":70.74999999999812,"finished":true,"end_reason":"cleared","destroyed":[],"grotto":"none|-1|-1|true","grotto_boss":"","grotto_boss_hp":0.0,"events":78,"mobile":[0,0,0]}},{"label":"round-8","phase":0,"round":9,"winner":-2,"end_note":"","players":[{"gold":298,"draft_gold":298,"ready":true,"earned":1148,"spent":1070,"next_seq":10,"roster":["p0-1|g03|top|70","p0-2|g02|top|135","p0-3|g06|top|205","p0-4|g07|top|95","p0-5|g03|top|70","p0-6|g09|top|85","p0-7|g02|top|135","p0-8|g06|top|205","p0-9|g03|top|70"],"hero":"","bookings":[],"new_bookings":[],"draft_roster":["p0-1|g03|top|70|false","p0-2|g02|top|135|false","p0-3|g06|top|205|false","p0-4|g07|top|95|false","p0-5|g03|top|70|false","p0-6|g09|top|85|false","p0-7|g02|top|135|false","p0-8|g06|top|205|false","p0-9|g03|top|70|false"],"draft_hero":"","boss_lane":"","undo":0},{"gold":338,"draft_gold":338,"ready":true,"earned":1148,"spent":1030,"next_seq":9,"roster":["p1-1|w03|mid|75","p1-2|w06|mid|195","p1-3|w02|mid|150","p1-4|w03|mid|75","p1-5|w07|mid|100","p1-6|w09|mid|90","p1-7|w06|mid|195"],"hero":"","bookings":[],"new_bookings":[],"draft_roster":["p1-1|w03|mid|75|false","p1-2|w06|mid|195|false","p1-3|w02|mid|150|false","p1-4|w03|mid|75|false","p1-5|w07|mid|100|false","p1-6|w09|mid|90|false","p1-7|w06|mid|195|false"],"draft_hero":"","boss_lane":"","undo":0},{"gold":338,"draft_gold":338,"ready":true,"earned":1148,"spent":1030,"next_seq":10,"roster":["p2-1|g02|bot|135","p2-2|g05|bot|65","p2-3|g03|bot|70","p2-4|g07|bot|95","p2-5|g02|bot|135","p2-6|g05|bot|65","p2-7|g02|bot|135","p2-8|g03|bot|70"],"hero":"h2-9|held_funkenlanze|536|bot||splitterschuss|260|false|","bookings":[],"new_bookings":[],"draft_roster":["p2-1|g02|bot|135|false","p2-2|g05|bot|65|false","p2-3|g03|bot|70|false","p2-4|g07|bot|95|false","p2-5|g02|bot|135|false","p2-6|g05|bot|65|false","p2-7|g02|bot|135|false","p2-8|g03|bot|70|false"],"draft_hero":"h2-9|held_funkenlanze|536|bot||splitterschuss|260|false|","boss_lane":"","undo":0},{"gold":250,"draft_gold":250,"ready":true,"earned":1120,"spent":1090,"next_seq":10,"roster":["p3-1|w06|top|195","p3-2|w03|top|75","p3-3|w07|top|100","p3-4|w06|top|195","p3-5|w02|top|150","p3-6|w09|top|90","p3-7|w05|top|60","p3-9|w03|top|75"],"hero":"","bookings":[],"new_bookings":[],"draft_roster":["p3-1|w06|top|195|false","p3-2|w03|top|75|false","p3-3|w07|top|100|false","p3-4|w06|top|195|false","p3-5|w02|top|150|false","p3-6|w09|top|90|false","p3-7|w05|top|60|false","p3-9|w03|top|75|false"],"draft_hero":"","boss_lane":"","undo":0},{"gold":319,"draft_gold":319,"ready":true,"earned":1179,"spent":1080,"next_seq":11,"roster":["p4-1|g03|mid|70","p4-2|g06|mid|205","p4-3|g02|mid|135","p4-4|g09|mid|85","p4-5|g03|mid|70","p4-6|g07|top|95","p4-7|g05|top|65","p4-8|g02|mid|135","p4-10|g03|mid|70"],"hero":"","bookings":[],"new_bookings":[],"draft_roster":["p4-1|g03|mid|70|false","p4-2|g06|mid|205|false","p4-3|g02|mid|135|false","p4-4|g09|mid|85|false","p4-5|g03|mid|70|false","p4-6|g07|top|95|false","p4-7|g05|top|65|false","p4-8|g02|mid|135|false","p4-10|g03|mid|70|false"],"draft_hero":"","boss_lane":"","undo":0},{"gold":249,"draft_gold":249,"ready":true,"earned":1119,"spent":1090,"next_seq":10,"roster":["p5-1|w03|bot|75","p5-2|w02|bot|150","p5-3|w06|bot|195","p5-4|w03|bot|75","p5-5|w07|bot|100","p5-6|w09|bot|90","p5-7|w02|bot|150","p5-9|w03|mid|75"],"hero":"","bookings":[],"new_bookings":[],"draft_roster":["p5-1|w03|bot|75|false","p5-2|w02|bot|150|false","p5-3|w06|bot|195|false","p5-4|w03|bot|75|false","p5-5|w07|bot|100|false","p5-6|w09|bot|90|false","p5-7|w02|bot|150|false","p5-9|w03|mid|75|false"],"draft_hero":"","boss_lane":"","undo":0}],"buildings":[0.0,0.0,7500.0,5878.8,7500.0,3623.788,6543.4000000000005,9000.0,12000.0,7500.0,4833.611200000001,1245.5094000000074,0.0,7500.0,396.15279999999217,9000.0,9000.0,12000.0],"boss":{"next":1,"settled":8,"claim":""},"boss_log":[],"announcements":[],"settlement":{"round":8,"gains":[175,175,175,147,206,146],"income":98,"lost":["blau_top_inner"],"end_reason":"cleared","combat_time":82.69999999999744,"boss":"none","lane_kills":{"mid":12,"bot":11,"top":11},"xp":{"h2-9":254}},"combat":{"round":8,"steps":1654,"elapsed":82.69999999999744,"finished":true,"end_reason":"cleared","destroyed":[],"grotto":"none|-1|-1|true","grotto_boss":"","grotto_boss_hp":0.0,"events":85,"mobile":[0,0,0]}},{"label":"round-9","phase":0,"round":10,"winner":-2,"end_note":"","players":[{"gold":326,"draft_gold":326,"ready":true,"earned":1436,"spent":1330,"next_seq":11,"roster":["p0-1|g03|top|70","p0-2|g02|top|135","p0-3|g06|top|205","p0-4|g07|top|95","p0-5|g03|top|70","p0-6|g09|top|85","p0-7|g02|top|135","p0-8|g06|top|205","p0-9|g03|top|70"],"hero":"h0-10|held_ringborke|145|top|||260|false|","bookings":[],"new_bookings":[],"draft_roster":["p0-1|g03|top|70|false","p0-2|g02|top|135|false","p0-3|g06|top|205|false","p0-4|g07|top|95|false","p0-5|g03|top|70|false","p0-6|g09|top|85|false","p0-7|g02|top|135|false","p0-8|g06|top|205|false","p0-9|g03|top|70|false"],"draft_hero":"h0-10|held_ringborke|145|top|||260|false|","boss_lane":"","undo":0},{"gold":291,"draft_gold":291,"ready":true,"earned":1436,"spent":1365,"next_seq":11,"roster":["p1-1|w03|mid|75","p1-2|w06|mid|195","p1-3|w02|mid|150","p1-4|w03|mid|75","p1-5|w07|mid|100","p1-6|w09|mid|90","p1-7|w06|mid|195","p1-10|w03|mid|75"],"hero":"h1-9|held_ringborke|298|mid|||260|false|","bookings":[],"new_bookings":[],"draft_roster":["p1-1|w03|mid|75|false","p1-2|w06|mid|195|false","p1-3|w02|mid|150|false","p1-4|w03|mid|75|false","p1-5|w07|mid|100|false","p1-6|w09|mid|90|false","p1-7|w06|mid|195|false","p1-10|w03|mid|75|false"],"draft_hero":"h1-9|held_ringborke|298|mid|||260|false|","boss_lane":"","undo":0},{"gold":306,"draft_gold":306,"ready":true,"earned":1436,"spent":1350,"next_seq":10,"roster":["p2-1|g02|bot|135","p2-2|g06|bot|205","p2-3|g03|bot|70","p2-4|g07|bot|95","p2-5|g02|bot|135","p2-6|g05|bot|65","p2-7|g02|bot|135","p2-8|g03|bot|70"],"hero":"h2-9|held_funkenlanze|975|bot|glutklinge|splitterschuss|260|false|","bookings":[],"new_bookings":[],"draft_roster":["p2-1|g02|bot|135|false","p2-2|g06|bot|205|false","p2-3|g03|bot|70|false","p2-4|g07|bot|95|false","p2-5|g02|bot|135|false","p2-6|g05|bot|65|false","p2-7|g02|bot|135|false","p2-8|g03|bot|70|false"],"draft_hero":"h2-9|held_funkenlanze|975|bot|glutklinge|splitterschuss|260|false|","boss_lane":"","undo":0},{"gold":223,"draft_gold":223,"ready":true,"earned":1288,"spent":1285,"next_seq":11,"roster":["p3-1|w06|top|195","p3-2|w03|top|75","p3-3|w07|top|100","p3-4|w06|top|195","p3-5|w02|top|150","p3-6|w09|top|90","p3-7|w06|top|195","p3-9|w03|top|75","p3-10|w05|top|60"],"hero":"","bookings":[],"new_bookings":[],"draft_roster":["p3-1|w06|top|195|false","p3-2|w03|top|75|false","p3-3|w07|top|100|false","p3-4|w06|top|195|false","p3-5|w02|top|150|false","p3-6|w09|top|90|false","p3-7|w06|top|195|false","p3-9|w03|top|75|false","p3-10|w05|top|60|false"],"draft_hero":"","boss_lane":"","undo":0},{"gold":227,"draft_gold":227,"ready":true,"earned":1347,"spent":1340,"next_seq":12,"roster":["p4-1|g03|mid|70","p4-2|g06|mid|205","p4-3|g02|mid|135","p4-4|g09|mid|85","p4-5|g03|mid|70","p4-6|g07|top|95","p4-7|g05|top|65","p4-8|g02|mid|135","p4-10|g03|mid|70"],"hero":"h4-11|held_quellgeflecht|181|mid|||260|false|","bookings":[],"new_bookings":[],"draft_roster":["p4-1|g03|mid|70|false","p4-2|g06|mid|205|false","p4-3|g02|mid|135|false","p4-4|g09|mid|85|false","p4-5|g03|mid|70|false","p4-6|g07|top|95|false","p4-7|g05|top|65|false","p4-8|g02|mid|135|false","p4-10|g03|mid|70|false"],"draft_hero":"h4-11|held_quellgeflecht|181|mid|||260|false|","boss_lane":"","undo":0},{"gold":202,"draft_gold":202,"ready":true,"earned":1287,"spent":1305,"next_seq":11,"roster":["p5-1|w04|bot|230","p5-2|w02|bot|150","p5-3|w06|bot|195","p5-4|w03|bot|75","p5-5|w07|bot|100","p5-6|w09|bot|90","p5-7|w02|bot|150","p5-9|w03|mid|75","p5-10|w05|bot|60"],"hero":"","bookings":[],"new_bookings":[],"draft_roster":["p5-1|w04|bot|230|false","p5-2|w02|bot|150|false","p5-3|w06|bot|195|false","p5-4|w03|bot|75|false","p5-5|w07|bot|100|false","p5-6|w09|bot|90|false","p5-7|w02|bot|150|false","p5-9|w03|mid|75|false","p5-10|w05|bot|60|false"],"draft_hero":"","boss_lane":"","undo":0}],"buildings":[0.0,0.0,7500.0,5878.8,7500.0,3623.788,6543.4000000000005,9000.0,12000.0,7500.0,3523.861200000001,0.0,0.0,2608.2853399999967,0.0,8716.3328,6691.832000000001,12000.0],"boss":{"next":1,"settled":9,"claim":""},"boss_log":[],"announcements":[],"settlement":{"round":9,"gains":[186,186,186,66,66,66],"income":102,"lost":["rot_bot_outer","rot_mid_inner"],"end_reason":"cleared","combat_time":78.64999999999768,"boss":"none","lane_kills":{"mid":10,"bot":10,"top":10},"xp":{"h4-11":181,"h1-9":298,"h2-9":439,"h0-10":145}},"combat":{"round":9,"steps":1573,"elapsed":78.64999999999768,"finished":true,"end_reason":"cleared","destroyed":[],"grotto":"none|-1|-1|true","grotto_boss":"","grotto_boss_hp":0.0,"events":88,"mobile":[0,0,0]}}],"results":[]},"item_purchase":{"title":"Itemkauf: Plätze, Einzigartigkeit, Stufe, Rückgabe, Normale Einheiten ohne Items","snapshots":[{"label":"planned","phase":0,"round":1,"winner":-2,"end_note":"","players":[{"gold":220,"draft_gold":4355,"ready":true,"earned":0,"spent":0,"next_seq":1,"roster":[],"hero":"","bookings":[],"new_bookings":[],"draft_roster":["p0-2|g01|top|45|true"],"draft_hero":"h0-1|held_ringborke|0|top|glutklinge+rankenmantel+basaltschild||260|true|glutklinge+rankenmantel+basaltschild","boss_lane":"","undo":7},{"gold":220,"draft_gold":220,"ready":true,"earned":0,"spent":0,"next_seq":1,"roster":[],"hero":"","bookings":[],"new_bookings":[],"draft_roster":[],"draft_hero":"","boss_lane":"","undo":0},{"gold":220,"draft_gold":220,"ready":true,"earned":0,"spent":0,"next_seq":1,"roster":[],"hero":"","bookings":[],"new_bookings":[],"draft_roster":[],"draft_hero":"","boss_lane":"","undo":0},{"gold":220,"draft_gold":220,"ready":true,"earned":0,"spent":0,"next_seq":1,"roster":[],"hero":"","bookings":[],"new_bookings":[],"draft_roster":[],"draft_hero":"","boss_lane":"","undo":0},{"gold":220,"draft_gold":220,"ready":true,"earned":0,"spent":0,"next_seq":1,"roster":[],"hero":"","bookings":[],"new_bookings":[],"draft_roster":[],"draft_hero":"","boss_lane":"","undo":0},{"gold":220,"draft_gold":220,"ready":true,"earned":0,"spent":0,"next_seq":1,"roster":[],"hero":"","bookings":[],"new_bookings":[],"draft_roster":[],"draft_hero":"","boss_lane":"","undo":0}],"buildings":[7500.0,6000.0,7500.0,6000.0,7500.0,6000.0,9000.0,9000.0,12000.0,7500.0,6000.0,7500.0,6000.0,7500.0,6000.0,9000.0,9000.0,12000.0],"boss":{"next":1,"settled":0,"claim":""},"boss_log":[],"announcements":[],"settlement":null,"combat":null},{"label":"spawned","phase":1,"round":1,"winner":-2,"end_note":"","players":[{"gold":4355,"draft_gold":4355,"ready":true,"earned":0,"spent":0,"next_seq":3,"roster":["p0-2|g01|top|45"],"hero":"h0-1|held_ringborke|0|top|glutklinge+rankenmantel+basaltschild||260|false|","bookings":[],"new_bookings":[],"draft_roster":["p0-2|g01|top|45|true"],"draft_hero":"h0-1|held_ringborke|0|top|glutklinge+rankenmantel+basaltschild||260|true|glutklinge+rankenmantel+basaltschild","boss_lane":"","undo":0},{"gold":220,"draft_gold":220,"ready":true,"earned":0,"spent":0,"next_seq":1,"roster":[],"hero":"","bookings":[],"new_bookings":[],"draft_roster":[],"draft_hero":"","boss_lane":"","undo":0},{"gold":220,"draft_gold":220,"ready":true,"earned":0,"spent":0,"next_seq":1,"roster":[],"hero":"","bookings":[],"new_bookings":[],"draft_roster":[],"draft_hero":"","boss_lane":"","undo":0},{"gold":220,"draft_gold":220,"ready":true,"earned":0,"spent":0,"next_seq":1,"roster":[],"hero":"","bookings":[],"new_bookings":[],"draft_roster":[],"draft_hero":"","boss_lane":"","undo":0},{"gold":220,"draft_gold":220,"ready":true,"earned":0,"spent":0,"next_seq":1,"roster":[],"hero":"","bookings":[],"new_bookings":[],"draft_roster":[],"draft_hero":"","boss_lane":"","undo":0},{"gold":220,"draft_gold":220,"ready":true,"earned":0,"spent":0,"next_seq":1,"roster":[],"hero":"","bookings":[],"new_bookings":[],"draft_roster":[],"draft_hero":"","boss_lane":"","undo":0}],"buildings":[7500.0,6000.0,7500.0,6000.0,7500.0,6000.0,9000.0,9000.0,12000.0,7500.0,6000.0,7500.0,6000.0,7500.0,6000.0,9000.0,9000.0,12000.0],"boss":{"next":1,"settled":0,"claim":""},"boss_log":[],"announcements":[],"settlement":null,"combat":{"round":1,"steps":0,"elapsed":0.0,"finished":false,"end_reason":"","destroyed":[],"grotto":"none|-1|-1|true","grotto_boss":"","grotto_boss_hp":0.0,"events":0,"mobile":[11,9,0]},"units":[{"id":1,"kind":"tower","team":0,"lane":"top","zone":"lane","slot":-1,"uid":"","def":"blau_top_inner","alive":true,"hp":7500.0,"max_hp":7500.0,"shield":0.0,"x":-24.931251525878906,"y":4.5293378829956055,"facing":0.0,"progress":0.0,"target":-1,"hits":0,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":2,"kind":"tower","team":0,"lane":"top","zone":"lane","slot":-1,"uid":"","def":"blau_top_outer","alive":true,"hp":6000.0,"max_hp":6000.0,"shield":0.0,"x":-24.921451568603516,"y":-12.715348243713379,"facing":0.0,"progress":0.0,"target":-1,"hits":0,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":3,"kind":"tower","team":0,"lane":"mid","zone":"lane","slot":-1,"uid":"","def":"blau_mid_inner","alive":true,"hp":7500.0,"max_hp":7500.0,"shield":0.0,"x":-11.427590370178223,"y":17.012392044067383,"facing":0.0,"progress":0.0,"target":-1,"hits":0,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":4,"kind":"tower","team":0,"lane":"mid","zone":"lane","slot":-1,"uid":"","def":"blau_mid_outer","alive":true,"hp":6000.0,"max_hp":6000.0,"shield":0.0,"x":-3.8433847427368164,"y":8.990991592407227,"facing":0.0,"progress":0.0,"target":-1,"hits":0,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":5,"kind":"tower","team":0,"lane":"bot","zone":"lane","slot":-1,"uid":"","def":"blau_bot_inner","alive":true,"hp":7500.0,"max_hp":7500.0,"shield":0.0,"x":-4.349228858947754,"y":31.034507751464844,"facing":0.0,"progress":0.0,"target":-1,"hits":0,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":6,"kind":"tower","team":0,"lane":"bot","zone":"lane","slot":-1,"uid":"","def":"blau_bot_outer","alive":true,"hp":6000.0,"max_hp":6000.0,"shield":0.0,"x":11.117134094238281,"y":28.989334106445313,"facing":0.0,"progress":0.0,"target":-1,"hits":0,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":7,"kind":"tower","team":0,"lane":"base","zone":"lane","slot":-1,"uid":"","def":"blau_base_1","alive":true,"hp":9000.0,"max_hp":9000.0,"shield":0.0,"x":-29.476999282836914,"y":24.023000717163086,"facing":0.0,"progress":0.0,"target":-1,"hits":0,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":8,"kind":"tower","team":0,"lane":"base","zone":"lane","slot":-1,"uid":"","def":"blau_base_2","alive":true,"hp":9000.0,"max_hp":9000.0,"shield":0.0,"x":-24.023000717163086,"y":29.476999282836914,"facing":0.0,"progress":0.0,"target":-1,"hits":0,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":9,"kind":"core","team":0,"lane":"base","zone":"lane","slot":-1,"uid":"","def":"blau_ancient","alive":true,"hp":12000.0,"max_hp":12000.0,"shield":0.0,"x":-30.0,"y":30.0,"facing":0.0,"progress":0.0,"target":-1,"hits":0,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":10,"kind":"tower","team":1,"lane":"top","zone":"lane","slot":-1,"uid":"","def":"rot_top_inner","alive":true,"hp":7500.0,"max_hp":7500.0,"shield":0.0,"x":4.5293378829956055,"y":-24.931251525878906,"facing":0.0,"progress":0.0,"target":-1,"hits":0,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":11,"kind":"tower","team":1,"lane":"top","zone":"lane","slot":-1,"uid":"","def":"rot_top_outer","alive":true,"hp":6000.0,"max_hp":6000.0,"shield":0.0,"x":-12.715348243713379,"y":-24.921451568603516,"facing":0.0,"progress":0.0,"target":-1,"hits":0,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":12,"kind":"tower","team":1,"lane":"mid","zone":"lane","slot":-1,"uid":"","def":"rot_mid_inner","alive":true,"hp":7500.0,"max_hp":7500.0,"shield":0.0,"x":17.012392044067383,"y":-11.427590370178223,"facing":0.0,"progress":0.0,"target":-1,"hits":0,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":13,"kind":"tower","team":1,"lane":"mid","zone":"lane","slot":-1,"uid":"","def":"rot_mid_outer","alive":true,"hp":6000.0,"max_hp":6000.0,"shield":0.0,"x":8.990991592407227,"y":-3.8433847427368164,"facing":0.0,"progress":0.0,"target":-1,"hits":0,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":14,"kind":"tower","team":1,"lane":"bot","zone":"lane","slot":-1,"uid":"","def":"rot_bot_inner","alive":true,"hp":7500.0,"max_hp":7500.0,"shield":0.0,"x":31.034507751464844,"y":-4.349228858947754,"facing":0.0,"progress":0.0,"target":-1,"hits":0,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":15,"kind":"tower","team":1,"lane":"bot","zone":"lane","slot":-1,"uid":"","def":"rot_bot_outer","alive":true,"hp":6000.0,"max_hp":6000.0,"shield":0.0,"x":28.989334106445313,"y":11.117134094238281,"facing":0.0,"progress":0.0,"target":-1,"hits":0,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":16,"kind":"tower","team":1,"lane":"base","zone":"lane","slot":-1,"uid":"","def":"rot_base_1","alive":true,"hp":9000.0,"max_hp":9000.0,"shield":0.0,"x":24.023000717163086,"y":-29.476999282836914,"facing":0.0,"progress":0.0,"target":-1,"hits":0,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":17,"kind":"tower","team":1,"lane":"base","zone":"lane","slot":-1,"uid":"","def":"rot_base_2","alive":true,"hp":9000.0,"max_hp":9000.0,"shield":0.0,"x":29.476999282836914,"y":-24.023000717163086,"facing":0.0,"progress":0.0,"target":-1,"hits":0,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":18,"kind":"core","team":1,"lane":"base","zone":"lane","slot":-1,"uid":"","def":"rot_ancient","alive":true,"hp":12000.0,"max_hp":12000.0,"shield":0.0,"x":30.0,"y":-30.0,"facing":0.0,"progress":0.0,"target":-1,"hits":0,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":19,"kind":"monster","team":0,"lane":"top","zone":"lane","slot":-1,"uid":"","def":"e01","alive":true,"hp":90.0,"max_hp":90.0,"shield":0.0,"x":-28.243892669677734,"y":10.502157211303711,"facing":-2.864119239296395,"progress":11.0,"target":-1,"hits":0,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":20,"kind":"monster","team":0,"lane":"top","zone":"lane","slot":-1,"uid":"","def":"e01","alive":true,"hp":90.0,"max_hp":90.0,"shield":0.0,"x":-26.993616104125977,"y":10.146052360534668,"facing":-2.864119239296395,"progress":11.0,"target":-1,"hits":0,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":21,"kind":"monster","team":0,"lane":"top","zone":"lane","slot":-1,"uid":"","def":"e01","alive":true,"hp":90.0,"max_hp":90.0,"shield":0.0,"x":-25.74333953857422,"y":9.789947509765625,"facing":-2.864119239296395,"progress":11.0,"target":-1,"hits":0,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":22,"kind":"monster","team":0,"lane":"mid","zone":"lane","slot":-1,"uid":"","def":"e01","alive":true,"hp":90.0,"max_hp":90.0,"shield":0.0,"x":-14.408708572387695,"y":13.32747745513916,"facing":2.3870002372622334,"progress":11.0,"target":-1,"hits":0,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":23,"kind":"monster","team":0,"lane":"mid","zone":"lane","slot":-1,"uid":"","def":"e01","alive":true,"hp":90.0,"max_hp":90.0,"shield":0.0,"x":-13.461592674255371,"y":14.21796703338623,"facing":2.3870002372622334,"progress":11.0,"target":-1,"hits":0,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":24,"kind":"monster","team":0,"lane":"mid","zone":"lane","slot":-1,"uid":"","def":"e01","alive":true,"hp":90.0,"max_hp":90.0,"shield":0.0,"x":-12.514476776123047,"y":15.1084566116333,"facing":2.3870002372622334,"progress":11.0,"target":-1,"hits":0,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":25,"kind":"monster","team":0,"lane":"bot","zone":"lane","slot":-1,"uid":"","def":"e01","alive":true,"hp":90.0,"max_hp":90.0,"shield":0.0,"x":-9.842267036437988,"y":25.94097137451172,"facing":1.4313591016628469,"progress":11.0,"target":-1,"hits":0,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":26,"kind":"monster","team":0,"lane":"bot","zone":"lane","slot":-1,"uid":"","def":"e01","alive":true,"hp":90.0,"max_hp":90.0,"shield":0.0,"x":-10.022948265075684,"y":27.22835350036621,"facing":1.4313591016628469,"progress":11.0,"target":-1,"hits":0,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":27,"kind":"monster","team":0,"lane":"bot","zone":"lane","slot":-1,"uid":"","def":"e01","alive":true,"hp":90.0,"max_hp":90.0,"shield":0.0,"x":-10.203629493713379,"y":28.515735626220703,"facing":1.4313591016628469,"progress":11.0,"target":-1,"hits":0,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":28,"kind":"monster","team":1,"lane":"top","zone":"lane","slot":-1,"uid":"","def":"e01","alive":true,"hp":90.0,"max_hp":90.0,"shield":0.0,"x":10.502157211303711,"y":-28.243892669677734,"facing":-1.8482697410882951,"progress":11.0,"target":-1,"hits":0,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":29,"kind":"monster","team":1,"lane":"top","zone":"lane","slot":-1,"uid":"","def":"e01","alive":true,"hp":90.0,"max_hp":90.0,"shield":0.0,"x":10.146052360534668,"y":-26.993616104125977,"facing":-1.8482697410882951,"progress":11.0,"target":-1,"hits":0,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":30,"kind":"monster","team":1,"lane":"top","zone":"lane","slot":-1,"uid":"","def":"e01","alive":true,"hp":90.0,"max_hp":90.0,"shield":0.0,"x":9.789947509765625,"y":-25.74333953857422,"facing":-1.8482697410882951,"progress":11.0,"target":-1,"hits":0,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":31,"kind":"monster","team":1,"lane":"mid","zone":"lane","slot":-1,"uid":"","def":"e01","alive":true,"hp":90.0,"max_hp":90.0,"shield":0.0,"x":13.32747745513916,"y":-14.408708572387695,"facing":-0.816203910467337,"progress":11.0,"target":-1,"hits":0,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":32,"kind":"monster","team":1,"lane":"mid","zone":"lane","slot":-1,"uid":"","def":"e01","alive":true,"hp":90.0,"max_hp":90.0,"shield":0.0,"x":14.21796703338623,"y":-13.461592674255371,"facing":-0.816203910467337,"progress":11.0,"target":-1,"hits":0,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":33,"kind":"monster","team":1,"lane":"mid","zone":"lane","slot":-1,"uid":"","def":"e01","alive":true,"hp":90.0,"max_hp":90.0,"shield":0.0,"x":15.1084566116333,"y":-12.514476776123047,"facing":-0.816203910467337,"progress":11.0,"target":-1,"hits":0,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":34,"kind":"monster","team":1,"lane":"bot","zone":"lane","slot":-1,"uid":"","def":"e01","alive":true,"hp":90.0,"max_hp":90.0,"shield":0.0,"x":25.94097137451172,"y":-9.842267036437988,"facing":0.13943722513204979,"progress":11.0,"target":-1,"hits":0,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":35,"kind":"monster","team":1,"lane":"bot","zone":"lane","slot":-1,"uid":"","def":"e01","alive":true,"hp":90.0,"max_hp":90.0,"shield":0.0,"x":27.22835350036621,"y":-10.022948265075684,"facing":0.13943722513204979,"progress":11.0,"target":-1,"hits":0,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":36,"kind":"monster","team":1,"lane":"bot","zone":"lane","slot":-1,"uid":"","def":"e01","alive":true,"hp":90.0,"max_hp":90.0,"shield":0.0,"x":28.515735626220703,"y":-10.203629493713379,"facing":0.13943722513204979,"progress":11.0,"target":-1,"hits":0,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":37,"kind":"hero","team":0,"lane":"top","zone":"lane","slot":0,"uid":"h0-1","def":"w04","alive":true,"hp":2550.0,"max_hp":2550.0,"shield":0.0,"x":-28.204208374023438,"y":13.871247291564941,"facing":3.1367842018723553,"progress":7.2,"target":-1,"hits":0,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":38,"kind":"troop","team":0,"lane":"top","zone":"lane","slot":0,"uid":"p0-2","def":"g01","alive":true,"hp":260.0,"max_hp":260.0,"shield":0.0,"x":-27.004222869873047,"y":13.877017974853516,"facing":3.1367842018723553,"progress":7.2,"target":-1,"hits":0,"reached":false,"dormant":false,"effects":[],"dots":[]}]},{"label":"after_round","phase":0,"round":2,"winner":-2,"end_note":"","players":[{"gold":4443,"draft_gold":4533,"ready":true,"earned":88,"spent":0,"next_seq":3,"roster":["p0-2|g01|top|45"],"hero":"h0-1|held_ringborke|85|top|glutklinge+rankenmantel+basaltschild||260|false|","bookings":[],"new_bookings":[],"draft_roster":["p0-2|g01|top|45|false"],"draft_hero":"h0-1|held_ringborke|85|top|glutklinge+rankenmantel||260|false|","boss_lane":"","undo":1},{"gold":308,"draft_gold":308,"ready":true,"earned":88,"spent":0,"next_seq":1,"roster":[],"hero":"","bookings":[],"new_bookings":[],"draft_roster":[],"draft_hero":"","boss_lane":"","undo":0},{"gold":308,"draft_gold":308,"ready":true,"earned":88,"spent":0,"next_seq":1,"roster":[],"hero":"","bookings":[],"new_bookings":[],"draft_roster":[],"draft_hero":"","boss_lane":"","undo":0},{"gold":308,"draft_gold":308,"ready":true,"earned":88,"spent":0,"next_seq":1,"roster":[],"hero":"","bookings":[],"new_bookings":[],"draft_roster":[],"draft_hero":"","boss_lane":"","undo":0},{"gold":308,"draft_gold":308,"ready":true,"earned":88,"spent":0,"next_seq":1,"roster":[],"hero":"","bookings":[],"new_bookings":[],"draft_roster":[],"draft_hero":"","boss_lane":"","undo":0},{"gold":308,"draft_gold":308,"ready":true,"earned":88,"spent":0,"next_seq":1,"roster":[],"hero":"","bookings":[],"new_bookings":[],"draft_roster":[],"draft_hero":"","boss_lane":"","undo":0}],"buildings":[7500.0,6000.0,7500.0,6000.0,7500.0,6000.0,9000.0,9000.0,12000.0,7500.0,4236.102000000002,7500.0,6000.0,7500.0,6000.0,9000.0,9000.0,12000.0],"boss":{"next":1,"settled":1,"claim":""},"boss_log":[],"announcements":[],"settlement":{"round":1,"gains":[18,18,18,18,18,18],"income":70,"lost":[],"end_reason":"cleared","combat_time":51.6999999999992,"boss":"none","lane_kills":{"bot":6,"top":6,"mid":6},"xp":{"h0-1":85}},"combat":{"round":1,"steps":1034,"elapsed":51.6999999999992,"finished":true,"end_reason":"cleared","destroyed":[],"grotto":"none|-1|-1|true","grotto_boss":"","grotto_boss_hp":0.0,"events":20,"mobile":[0,0,0]}}],"results":[["cmd",0,"hero_buy",true,"Ringborke angeworben."],["cmd",0,"buy",true,"Kohlenbeißer gekauft."],["cmd",0,"item_buy",false,"Normale Truppen tragen keine Items."],["cmd",0,"item_buy",true,"Glutklinge ausgerüstet."],["cmd",0,"item_buy",false,"Glutklinge trägt dein Held bereits; Items sind einzigartig."],["cmd",0,"item_buy",false,"Kristallsplitter erfordert Stufe 3."],["cmd",0,"item_buy",true,"Rankenmantel ausgerüstet."],["cmd",0,"item_buy",true,"Basaltschild ausgerüstet."],["cmd",0,"item_buy",false,"Alle 3 Itemplätze sind belegt."],["cmd",0,"item_sell",true,"Item für 180 Gold verkauft."],["cmd",0,"item_buy",true,"Basaltschild ausgerüstet."],["begin",-1,"",true,""],["cmd",0,"item_sell",true,"Item für 90 Gold verkauft."],["cmd",0,"hero_cancel",false,"Nur ein Held aus dieser Planung lässt sich zurückgeben."]]},"attack_champion":{"title":"Angriffschampion: Buchung n, öffentliche Ankündigung, Einsatz n+1, Kopfgeld, Verbrauch","snapshots":[{"label":"announced","phase":0,"round":2,"winner":-2,"end_note":"","players":[{"gold":1128,"draft_gold":1128,"ready":true,"earned":88,"spent":0,"next_seq":3,"roster":[],"hero":"","bookings":["c0-1|ch_belagerung|bot|180|2"],"new_bookings":[],"draft_roster":[],"draft_hero":"","boss_lane":"","undo":0},{"gold":308,"draft_gold":308,"ready":true,"earned":88,"spent":0,"next_seq":1,"roster":[],"hero":"","bookings":[],"new_bookings":[],"draft_roster":[],"draft_hero":"","boss_lane":"","undo":0},{"gold":308,"draft_gold":308,"ready":true,"earned":88,"spent":0,"next_seq":1,"roster":[],"hero":"","bookings":[],"new_bookings":[],"draft_roster":[],"draft_hero":"","boss_lane":"","undo":0},{"gold":308,"draft_gold":308,"ready":true,"earned":88,"spent":0,"next_seq":1,"roster":[],"hero":"","bookings":[],"new_bookings":[],"draft_roster":[],"draft_hero":"","boss_lane":"","undo":0},{"gold":308,"draft_gold":308,"ready":true,"earned":88,"spent":0,"next_seq":1,"roster":[],"hero":"","bookings":[],"new_bookings":[],"draft_roster":[],"draft_hero":"","boss_lane":"","undo":0},{"gold":308,"draft_gold":308,"ready":true,"earned":88,"spent":0,"next_seq":1,"roster":[],"hero":"","bookings":[],"new_bookings":[],"draft_roster":[],"draft_hero":"","boss_lane":"","undo":0}],"buildings":[7500.0,6000.0,7500.0,6000.0,7500.0,6000.0,9000.0,9000.0,12000.0,7500.0,6000.0,7500.0,6000.0,7500.0,6000.0,9000.0,9000.0,12000.0],"boss":{"next":1,"settled":1,"claim":""},"boss_log":[],"announcements":["champion|0|0|bot|ch_belagerung|0"],"settlement":{"round":1,"gains":[18,18,18,18,18,18],"income":70,"lost":[],"end_reason":"cleared","combat_time":26.050000000000235,"boss":"none","lane_kills":{"bot":6,"top":6,"mid":6},"xp":{}},"combat":{"round":1,"steps":521,"elapsed":26.050000000000235,"finished":true,"end_reason":"cleared","destroyed":[],"grotto":"none|-1|-1|true","grotto_boss":"","grotto_boss_hp":0.0,"events":18,"mobile":[0,0,0]}},{"label":"deployed","phase":1,"round":2,"winner":-2,"end_note":"","players":[{"gold":1128,"draft_gold":1128,"ready":true,"earned":88,"spent":0,"next_seq":3,"roster":[],"hero":"","bookings":["c0-1|ch_belagerung|bot|180|2"],"new_bookings":[],"draft_roster":[],"draft_hero":"","boss_lane":"","undo":0},{"gold":308,"draft_gold":308,"ready":true,"earned":88,"spent":0,"next_seq":1,"roster":[],"hero":"","bookings":[],"new_bookings":[],"draft_roster":[],"draft_hero":"","boss_lane":"","undo":0},{"gold":308,"draft_gold":308,"ready":true,"earned":88,"spent":0,"next_seq":1,"roster":[],"hero":"","bookings":[],"new_bookings":[],"draft_roster":[],"draft_hero":"","boss_lane":"","undo":0},{"gold":308,"draft_gold":308,"ready":true,"earned":88,"spent":0,"next_seq":1,"roster":[],"hero":"","bookings":[],"new_bookings":[],"draft_roster":[],"draft_hero":"","boss_lane":"","undo":0},{"gold":308,"draft_gold":308,"ready":true,"earned":88,"spent":0,"next_seq":1,"roster":[],"hero":"","bookings":[],"new_bookings":[],"draft_roster":[],"draft_hero":"","boss_lane":"","undo":0},{"gold":308,"draft_gold":308,"ready":true,"earned":88,"spent":0,"next_seq":1,"roster":[],"hero":"","bookings":[],"new_bookings":[],"draft_roster":[],"draft_hero":"","boss_lane":"","undo":0}],"buildings":[7500.0,6000.0,7500.0,6000.0,7500.0,6000.0,9000.0,9000.0,12000.0,7500.0,6000.0,7500.0,6000.0,7500.0,6000.0,9000.0,9000.0,12000.0],"boss":{"next":1,"settled":1,"claim":""},"boss_log":[],"announcements":["champion|0|0|bot|ch_belagerung|0"],"settlement":{"round":1,"gains":[18,18,18,18,18,18],"income":70,"lost":[],"end_reason":"cleared","combat_time":26.050000000000235,"boss":"none","lane_kills":{"bot":6,"top":6,"mid":6},"xp":{}},"combat":{"round":2,"steps":0,"elapsed":0.0,"finished":false,"end_reason":"","destroyed":[],"grotto":"none|-1|-1|true","grotto_boss":"","grotto_boss_hp":0.0,"events":0,"mobile":[10,9,0]},"units":[{"id":1,"kind":"tower","team":0,"lane":"top","zone":"lane","slot":-1,"uid":"","def":"blau_top_inner","alive":true,"hp":7500.0,"max_hp":7500.0,"shield":0.0,"x":-24.931251525878906,"y":4.5293378829956055,"facing":0.0,"progress":0.0,"target":-1,"hits":0,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":2,"kind":"tower","team":0,"lane":"top","zone":"lane","slot":-1,"uid":"","def":"blau_top_outer","alive":true,"hp":6000.0,"max_hp":6000.0,"shield":0.0,"x":-24.921451568603516,"y":-12.715348243713379,"facing":0.0,"progress":0.0,"target":-1,"hits":0,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":3,"kind":"tower","team":0,"lane":"mid","zone":"lane","slot":-1,"uid":"","def":"blau_mid_inner","alive":true,"hp":7500.0,"max_hp":7500.0,"shield":0.0,"x":-11.427590370178223,"y":17.012392044067383,"facing":0.0,"progress":0.0,"target":-1,"hits":0,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":4,"kind":"tower","team":0,"lane":"mid","zone":"lane","slot":-1,"uid":"","def":"blau_mid_outer","alive":true,"hp":6000.0,"max_hp":6000.0,"shield":0.0,"x":-3.8433847427368164,"y":8.990991592407227,"facing":0.0,"progress":0.0,"target":-1,"hits":0,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":5,"kind":"tower","team":0,"lane":"bot","zone":"lane","slot":-1,"uid":"","def":"blau_bot_inner","alive":true,"hp":7500.0,"max_hp":7500.0,"shield":0.0,"x":-4.349228858947754,"y":31.034507751464844,"facing":0.0,"progress":0.0,"target":-1,"hits":0,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":6,"kind":"tower","team":0,"lane":"bot","zone":"lane","slot":-1,"uid":"","def":"blau_bot_outer","alive":true,"hp":6000.0,"max_hp":6000.0,"shield":0.0,"x":11.117134094238281,"y":28.989334106445313,"facing":0.0,"progress":0.0,"target":-1,"hits":0,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":7,"kind":"tower","team":0,"lane":"base","zone":"lane","slot":-1,"uid":"","def":"blau_base_1","alive":true,"hp":9000.0,"max_hp":9000.0,"shield":0.0,"x":-29.476999282836914,"y":24.023000717163086,"facing":0.0,"progress":0.0,"target":-1,"hits":0,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":8,"kind":"tower","team":0,"lane":"base","zone":"lane","slot":-1,"uid":"","def":"blau_base_2","alive":true,"hp":9000.0,"max_hp":9000.0,"shield":0.0,"x":-24.023000717163086,"y":29.476999282836914,"facing":0.0,"progress":0.0,"target":-1,"hits":0,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":9,"kind":"core","team":0,"lane":"base","zone":"lane","slot":-1,"uid":"","def":"blau_ancient","alive":true,"hp":12000.0,"max_hp":12000.0,"shield":0.0,"x":-30.0,"y":30.0,"facing":0.0,"progress":0.0,"target":-1,"hits":0,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":10,"kind":"tower","team":1,"lane":"top","zone":"lane","slot":-1,"uid":"","def":"rot_top_inner","alive":true,"hp":7500.0,"max_hp":7500.0,"shield":0.0,"x":4.5293378829956055,"y":-24.931251525878906,"facing":0.0,"progress":0.0,"target":-1,"hits":0,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":11,"kind":"tower","team":1,"lane":"top","zone":"lane","slot":-1,"uid":"","def":"rot_top_outer","alive":true,"hp":6000.0,"max_hp":6000.0,"shield":0.0,"x":-12.715348243713379,"y":-24.921451568603516,"facing":0.0,"progress":0.0,"target":-1,"hits":0,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":12,"kind":"tower","team":1,"lane":"mid","zone":"lane","slot":-1,"uid":"","def":"rot_mid_inner","alive":true,"hp":7500.0,"max_hp":7500.0,"shield":0.0,"x":17.012392044067383,"y":-11.427590370178223,"facing":0.0,"progress":0.0,"target":-1,"hits":0,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":13,"kind":"tower","team":1,"lane":"mid","zone":"lane","slot":-1,"uid":"","def":"rot_mid_outer","alive":true,"hp":6000.0,"max_hp":6000.0,"shield":0.0,"x":8.990991592407227,"y":-3.8433847427368164,"facing":0.0,"progress":0.0,"target":-1,"hits":0,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":14,"kind":"tower","team":1,"lane":"bot","zone":"lane","slot":-1,"uid":"","def":"rot_bot_inner","alive":true,"hp":7500.0,"max_hp":7500.0,"shield":0.0,"x":31.034507751464844,"y":-4.349228858947754,"facing":0.0,"progress":0.0,"target":-1,"hits":0,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":15,"kind":"tower","team":1,"lane":"bot","zone":"lane","slot":-1,"uid":"","def":"rot_bot_outer","alive":true,"hp":6000.0,"max_hp":6000.0,"shield":0.0,"x":28.989334106445313,"y":11.117134094238281,"facing":0.0,"progress":0.0,"target":-1,"hits":0,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":16,"kind":"tower","team":1,"lane":"base","zone":"lane","slot":-1,"uid":"","def":"rot_base_1","alive":true,"hp":9000.0,"max_hp":9000.0,"shield":0.0,"x":24.023000717163086,"y":-29.476999282836914,"facing":0.0,"progress":0.0,"target":-1,"hits":0,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":17,"kind":"tower","team":1,"lane":"base","zone":"lane","slot":-1,"uid":"","def":"rot_base_2","alive":true,"hp":9000.0,"max_hp":9000.0,"shield":0.0,"x":29.476999282836914,"y":-24.023000717163086,"facing":0.0,"progress":0.0,"target":-1,"hits":0,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":18,"kind":"core","team":1,"lane":"base","zone":"lane","slot":-1,"uid":"","def":"rot_ancient","alive":true,"hp":12000.0,"max_hp":12000.0,"shield":0.0,"x":30.0,"y":-30.0,"facing":0.0,"progress":0.0,"target":-1,"hits":0,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":19,"kind":"monster","team":0,"lane":"top","zone":"lane","slot":-1,"uid":"","def":"e01","alive":true,"hp":100.03500000000001,"max_hp":100.03500000000001,"shield":0.0,"x":-28.243892669677734,"y":10.502157211303711,"facing":-2.864119239296395,"progress":11.0,"target":-1,"hits":0,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":20,"kind":"monster","team":0,"lane":"top","zone":"lane","slot":-1,"uid":"","def":"e01","alive":true,"hp":100.03500000000001,"max_hp":100.03500000000001,"shield":0.0,"x":-26.993616104125977,"y":10.146052360534668,"facing":-2.864119239296395,"progress":11.0,"target":-1,"hits":0,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":21,"kind":"monster","team":0,"lane":"top","zone":"lane","slot":-1,"uid":"","def":"e01","alive":true,"hp":100.03500000000001,"max_hp":100.03500000000001,"shield":0.0,"x":-25.74333953857422,"y":9.789947509765625,"facing":-2.864119239296395,"progress":11.0,"target":-1,"hits":0,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":22,"kind":"monster","team":0,"lane":"mid","zone":"lane","slot":-1,"uid":"","def":"e01","alive":true,"hp":100.03500000000001,"max_hp":100.03500000000001,"shield":0.0,"x":-14.408708572387695,"y":13.32747745513916,"facing":2.3870002372622334,"progress":11.0,"target":-1,"hits":0,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":23,"kind":"monster","team":0,"lane":"mid","zone":"lane","slot":-1,"uid":"","def":"e01","alive":true,"hp":100.03500000000001,"max_hp":100.03500000000001,"shield":0.0,"x":-13.461592674255371,"y":14.21796703338623,"facing":2.3870002372622334,"progress":11.0,"target":-1,"hits":0,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":24,"kind":"monster","team":0,"lane":"mid","zone":"lane","slot":-1,"uid":"","def":"e01","alive":true,"hp":100.03500000000001,"max_hp":100.03500000000001,"shield":0.0,"x":-12.514476776123047,"y":15.1084566116333,"facing":2.3870002372622334,"progress":11.0,"target":-1,"hits":0,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":25,"kind":"monster","team":0,"lane":"bot","zone":"lane","slot":-1,"uid":"","def":"e01","alive":true,"hp":100.03500000000001,"max_hp":100.03500000000001,"shield":0.0,"x":-9.842267036437988,"y":25.94097137451172,"facing":1.4313591016628469,"progress":11.0,"target":-1,"hits":0,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":26,"kind":"monster","team":0,"lane":"bot","zone":"lane","slot":-1,"uid":"","def":"e01","alive":true,"hp":100.03500000000001,"max_hp":100.03500000000001,"shield":0.0,"x":-10.022948265075684,"y":27.22835350036621,"facing":1.4313591016628469,"progress":11.0,"target":-1,"hits":0,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":27,"kind":"monster","team":0,"lane":"bot","zone":"lane","slot":-1,"uid":"","def":"e01","alive":true,"hp":100.03500000000001,"max_hp":100.03500000000001,"shield":0.0,"x":-10.203629493713379,"y":28.515735626220703,"facing":1.4313591016628469,"progress":11.0,"target":-1,"hits":0,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":28,"kind":"monster","team":1,"lane":"top","zone":"lane","slot":-1,"uid":"","def":"e01","alive":true,"hp":100.03500000000001,"max_hp":100.03500000000001,"shield":0.0,"x":10.502157211303711,"y":-28.243892669677734,"facing":-1.8482697410882951,"progress":11.0,"target":-1,"hits":0,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":29,"kind":"monster","team":1,"lane":"top","zone":"lane","slot":-1,"uid":"","def":"e01","alive":true,"hp":100.03500000000001,"max_hp":100.03500000000001,"shield":0.0,"x":10.146052360534668,"y":-26.993616104125977,"facing":-1.8482697410882951,"progress":11.0,"target":-1,"hits":0,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":30,"kind":"monster","team":1,"lane":"top","zone":"lane","slot":-1,"uid":"","def":"e01","alive":true,"hp":100.03500000000001,"max_hp":100.03500000000001,"shield":0.0,"x":9.789947509765625,"y":-25.74333953857422,"facing":-1.8482697410882951,"progress":11.0,"target":-1,"hits":0,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":31,"kind":"monster","team":1,"lane":"mid","zone":"lane","slot":-1,"uid":"","def":"e01","alive":true,"hp":100.03500000000001,"max_hp":100.03500000000001,"shield":0.0,"x":13.32747745513916,"y":-14.408708572387695,"facing":-0.816203910467337,"progress":11.0,"target":-1,"hits":0,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":32,"kind":"monster","team":1,"lane":"mid","zone":"lane","slot":-1,"uid":"","def":"e01","alive":true,"hp":100.03500000000001,"max_hp":100.03500000000001,"shield":0.0,"x":14.21796703338623,"y":-13.461592674255371,"facing":-0.816203910467337,"progress":11.0,"target":-1,"hits":0,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":33,"kind":"monster","team":1,"lane":"mid","zone":"lane","slot":-1,"uid":"","def":"e01","alive":true,"hp":100.03500000000001,"max_hp":100.03500000000001,"shield":0.0,"x":15.1084566116333,"y":-12.514476776123047,"facing":-0.816203910467337,"progress":11.0,"target":-1,"hits":0,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":34,"kind":"monster","team":1,"lane":"bot","zone":"lane","slot":-1,"uid":"","def":"e01","alive":true,"hp":100.03500000000001,"max_hp":100.03500000000001,"shield":0.0,"x":25.94097137451172,"y":-9.842267036437988,"facing":0.13943722513204979,"progress":11.0,"target":-1,"hits":0,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":35,"kind":"monster","team":1,"lane":"bot","zone":"lane","slot":-1,"uid":"","def":"e01","alive":true,"hp":100.03500000000001,"max_hp":100.03500000000001,"shield":0.0,"x":27.22835350036621,"y":-10.022948265075684,"facing":0.13943722513204979,"progress":11.0,"target":-1,"hits":0,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":36,"kind":"monster","team":1,"lane":"bot","zone":"lane","slot":-1,"uid":"","def":"e01","alive":true,"hp":100.03500000000001,"max_hp":100.03500000000001,"shield":0.0,"x":28.515735626220703,"y":-10.203629493713379,"facing":0.13943722513204979,"progress":11.0,"target":-1,"hits":0,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":37,"kind":"champion","team":0,"lane":"bot","zone":"lane","slot":0,"uid":"c0-1","def":"s04","alive":true,"hp":1589.4450000000004,"max_hp":1589.4450000000004,"shield":0.0,"x":-7.847529888153076,"y":26.120159149169922,"facing":1.4311578182023115,"progress":13.0,"target":-1,"hits":0,"reached":false,"dormant":false,"effects":[],"dots":[]}]},{"label":"t30","phase":1,"round":2,"winner":-2,"end_note":"","players":[{"gold":1128,"draft_gold":1128,"ready":true,"earned":88,"spent":0,"next_seq":3,"roster":[],"hero":"","bookings":["c0-1|ch_belagerung|bot|180|2"],"new_bookings":[],"draft_roster":[],"draft_hero":"","boss_lane":"","undo":0},{"gold":308,"draft_gold":308,"ready":true,"earned":88,"spent":0,"next_seq":1,"roster":[],"hero":"","bookings":[],"new_bookings":[],"draft_roster":[],"draft_hero":"","boss_lane":"","undo":0},{"gold":308,"draft_gold":308,"ready":true,"earned":88,"spent":0,"next_seq":1,"roster":[],"hero":"","bookings":[],"new_bookings":[],"draft_roster":[],"draft_hero":"","boss_lane":"","undo":0},{"gold":308,"draft_gold":308,"ready":true,"earned":88,"spent":0,"next_seq":1,"roster":[],"hero":"","bookings":[],"new_bookings":[],"draft_roster":[],"draft_hero":"","boss_lane":"","undo":0},{"gold":308,"draft_gold":308,"ready":true,"earned":88,"spent":0,"next_seq":1,"roster":[],"hero":"","bookings":[],"new_bookings":[],"draft_roster":[],"draft_hero":"","boss_lane":"","undo":0},{"gold":308,"draft_gold":308,"ready":true,"earned":88,"spent":0,"next_seq":1,"roster":[],"hero":"","bookings":[],"new_bookings":[],"draft_roster":[],"draft_hero":"","boss_lane":"","undo":0}],"buildings":[7500.0,6000.0,7500.0,6000.0,7500.0,6000.0,9000.0,9000.0,12000.0,7500.0,6000.0,7500.0,6000.0,7500.0,6000.0,9000.0,9000.0,12000.0],"boss":{"next":1,"settled":1,"claim":""},"boss_log":[],"announcements":["champion|0|0|bot|ch_belagerung|0"],"settlement":{"round":1,"gains":[18,18,18,18,18,18],"income":70,"lost":[],"end_reason":"cleared","combat_time":26.050000000000235,"boss":"none","lane_kills":{"bot":6,"top":6,"mid":6},"xp":{}},"combat":{"round":2,"steps":600,"elapsed":30.00000000000029,"finished":false,"end_reason":"","destroyed":[],"grotto":"none|-1|-1|true","grotto_boss":"","grotto_boss_hp":0.0,"events":18,"mobile":[1,0,0]},"units":[{"id":1,"kind":"tower","team":0,"lane":"top","zone":"lane","slot":-1,"uid":"","def":"blau_top_inner","alive":true,"hp":7500.0,"max_hp":7500.0,"shield":0.0,"x":-24.931251525878906,"y":4.5293378829956055,"facing":0.0,"progress":0.0,"target":-1,"hits":0,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":2,"kind":"tower","team":0,"lane":"top","zone":"lane","slot":-1,"uid":"","def":"blau_top_outer","alive":true,"hp":6000.0,"max_hp":6000.0,"shield":0.0,"x":-24.921451568603516,"y":-12.715348243713379,"facing":0.0,"progress":0.0,"target":-1,"hits":0,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":3,"kind":"tower","team":0,"lane":"mid","zone":"lane","slot":-1,"uid":"","def":"blau_mid_inner","alive":true,"hp":7500.0,"max_hp":7500.0,"shield":0.0,"x":-11.427590370178223,"y":17.012392044067383,"facing":0.0,"progress":0.0,"target":-1,"hits":0,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":4,"kind":"tower","team":0,"lane":"mid","zone":"lane","slot":-1,"uid":"","def":"blau_mid_outer","alive":true,"hp":6000.0,"max_hp":6000.0,"shield":0.0,"x":-3.8433847427368164,"y":8.990991592407227,"facing":0.0,"progress":0.0,"target":-1,"hits":0,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":5,"kind":"tower","team":0,"lane":"bot","zone":"lane","slot":-1,"uid":"","def":"blau_bot_inner","alive":true,"hp":7500.0,"max_hp":7500.0,"shield":0.0,"x":-4.349228858947754,"y":31.034507751464844,"facing":0.0,"progress":0.0,"target":-1,"hits":0,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":6,"kind":"tower","team":0,"lane":"bot","zone":"lane","slot":-1,"uid":"","def":"blau_bot_outer","alive":true,"hp":6000.0,"max_hp":6000.0,"shield":0.0,"x":11.117134094238281,"y":28.989334106445313,"facing":0.0,"progress":0.0,"target":-1,"hits":0,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":7,"kind":"tower","team":0,"lane":"base","zone":"lane","slot":-1,"uid":"","def":"blau_base_1","alive":true,"hp":9000.0,"max_hp":9000.0,"shield":0.0,"x":-29.476999282836914,"y":24.023000717163086,"facing":0.0,"progress":0.0,"target":-1,"hits":0,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":8,"kind":"tower","team":0,"lane":"base","zone":"lane","slot":-1,"uid":"","def":"blau_base_2","alive":true,"hp":9000.0,"max_hp":9000.0,"shield":0.0,"x":-24.023000717163086,"y":29.476999282836914,"facing":0.0,"progress":0.0,"target":-1,"hits":0,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":9,"kind":"core","team":0,"lane":"base","zone":"lane","slot":-1,"uid":"","def":"blau_ancient","alive":true,"hp":12000.0,"max_hp":12000.0,"shield":0.0,"x":-30.0,"y":30.0,"facing":0.0,"progress":0.0,"target":-1,"hits":0,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":10,"kind":"tower","team":1,"lane":"top","zone":"lane","slot":-1,"uid":"","def":"rot_top_inner","alive":true,"hp":7500.0,"max_hp":7500.0,"shield":0.0,"x":4.5293378829956055,"y":-24.931251525878906,"facing":0.0,"progress":0.0,"target":-1,"hits":0,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":11,"kind":"tower","team":1,"lane":"top","zone":"lane","slot":-1,"uid":"","def":"rot_top_outer","alive":true,"hp":6000.0,"max_hp":6000.0,"shield":0.0,"x":-12.715348243713379,"y":-24.921451568603516,"facing":0.0,"progress":0.0,"target":-1,"hits":0,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":12,"kind":"tower","team":1,"lane":"mid","zone":"lane","slot":-1,"uid":"","def":"rot_mid_inner","alive":true,"hp":7500.0,"max_hp":7500.0,"shield":0.0,"x":17.012392044067383,"y":-11.427590370178223,"facing":0.0,"progress":0.0,"target":-1,"hits":0,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":13,"kind":"tower","team":1,"lane":"mid","zone":"lane","slot":-1,"uid":"","def":"rot_mid_outer","alive":true,"hp":6000.0,"max_hp":6000.0,"shield":0.0,"x":8.990991592407227,"y":-3.8433847427368164,"facing":0.0,"progress":0.0,"target":-1,"hits":0,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":14,"kind":"tower","team":1,"lane":"bot","zone":"lane","slot":-1,"uid":"","def":"rot_bot_inner","alive":true,"hp":7500.0,"max_hp":7500.0,"shield":0.0,"x":31.034507751464844,"y":-4.349228858947754,"facing":0.0,"progress":0.0,"target":-1,"hits":0,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":15,"kind":"tower","team":1,"lane":"bot","zone":"lane","slot":-1,"uid":"","def":"rot_bot_outer","alive":true,"hp":5518.596480000002,"max_hp":6000.0,"shield":0.0,"x":28.989334106445313,"y":11.117134094238281,"facing":0.0,"progress":0.0,"target":37,"hits":10,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":16,"kind":"tower","team":1,"lane":"base","zone":"lane","slot":-1,"uid":"","def":"rot_base_1","alive":true,"hp":9000.0,"max_hp":9000.0,"shield":0.0,"x":24.023000717163086,"y":-29.476999282836914,"facing":0.0,"progress":0.0,"target":-1,"hits":0,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":17,"kind":"tower","team":1,"lane":"base","zone":"lane","slot":-1,"uid":"","def":"rot_base_2","alive":true,"hp":9000.0,"max_hp":9000.0,"shield":0.0,"x":29.476999282836914,"y":-24.023000717163086,"facing":0.0,"progress":0.0,"target":-1,"hits":0,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":18,"kind":"core","team":1,"lane":"base","zone":"lane","slot":-1,"uid":"","def":"rot_ancient","alive":true,"hp":12000.0,"max_hp":12000.0,"shield":0.0,"x":30.0,"y":-30.0,"facing":0.0,"progress":0.0,"target":-1,"hits":0,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":19,"kind":"monster","team":0,"lane":"top","zone":"lane","slot":-1,"uid":"","def":"e01","alive":false,"hp":0.0,"max_hp":100.03500000000001,"shield":0.0,"x":-26.336877822875977,"y":-25.78684425354004,"facing":2.356194490192345,"progress":47.90360550768908,"target":-1,"hits":12,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":20,"kind":"monster","team":0,"lane":"top","zone":"lane","slot":-1,"uid":"","def":"e01","alive":false,"hp":0.0,"max_hp":100.03500000000001,"shield":0.0,"x":-24.334409713745117,"y":-24.494911193847656,"facing":-2.930499320367047,"progress":48.45789523532882,"target":-1,"hits":18,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":21,"kind":"monster","team":0,"lane":"top","zone":"lane","slot":-1,"uid":"","def":"e01","alive":false,"hp":0.0,"max_hp":100.03500000000001,"shield":0.0,"x":-24.103269577026367,"y":-23.419477462768555,"facing":0.21109333322274654,"progress":48.119907427881714,"target":-1,"hits":6,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":22,"kind":"monster","team":0,"lane":"mid","zone":"lane","slot":-1,"uid":"","def":"e01","alive":false,"hp":0.0,"max_hp":100.03500000000001,"shield":0.0,"x":-1.183314561843872,"y":-0.6025248169898987,"facing":2.356194490192345,"progress":30.181223480769713,"target":-1,"hits":12,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":23,"kind":"monster","team":0,"lane":"mid","zone":"lane","slot":-1,"uid":"","def":"e01","alive":false,"hp":0.0,"max_hp":100.03500000000001,"shield":0.0,"x":-0.23837746679782867,"y":0.2985708713531494,"facing":2.3561945340953137,"progress":30.20001472364576,"target":-1,"hits":12,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":24,"kind":"monster","team":0,"lane":"mid","zone":"lane","slot":-1,"uid":"","def":"e01","alive":false,"hp":0.0,"max_hp":100.03500000000001,"shield":0.0,"x":0.6764076948165894,"y":1.2298187017440796,"facing":2.356194703746955,"progress":30.176166371817065,"target":-1,"hits":12,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":25,"kind":"monster","team":0,"lane":"bot","zone":"lane","slot":-1,"uid":"","def":"e01","alive":false,"hp":0.0,"max_hp":100.03500000000001,"shield":0.0,"x":22.507102966308594,"y":22.51051139831543,"facing":-2.359400689128409,"progress":48.4104163646698,"target":-1,"hits":5,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":26,"kind":"monster","team":0,"lane":"bot","zone":"lane","slot":-1,"uid":"","def":"e01","alive":false,"hp":0.0,"max_hp":100.03500000000001,"shield":0.0,"x":28.089502334594727,"y":14.279857635498047,"facing":2.8728271343072542,"progress":60.18999805358268,"target":-1,"hits":7,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":27,"kind":"monster","team":0,"lane":"bot","zone":"lane","slot":-1,"uid":"","def":"e01","alive":false,"hp":0.0,"max_hp":100.03500000000001,"shield":0.0,"x":28.772884368896484,"y":13.386837005615234,"facing":3.046511511232836,"progress":60.93700803051335,"target":-1,"hits":8,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":28,"kind":"monster","team":1,"lane":"top","zone":"lane","slot":-1,"uid":"","def":"e01","alive":false,"hp":0.0,"max_hp":100.03500000000001,"shield":0.0,"x":-25.78684425354004,"y":-26.336877822875977,"facing":-0.7853981633974483,"progress":47.90360550768908,"target":-1,"hits":12,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":29,"kind":"monster","team":1,"lane":"top","zone":"lane","slot":-1,"uid":"","def":"e01","alive":false,"hp":0.0,"max_hp":100.03500000000001,"shield":0.0,"x":-24.494911193847656,"y":-24.334409713745117,"facing":-1.7818896600176433,"progress":48.45789523532882,"target":-1,"hits":18,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":30,"kind":"monster","team":1,"lane":"top","zone":"lane","slot":-1,"uid":"","def":"e01","alive":false,"hp":0.0,"max_hp":100.03500000000001,"shield":0.0,"x":-23.419477462768555,"y":-24.103269577026367,"facing":1.35970299357215,"progress":48.119907427881714,"target":-1,"hits":6,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":31,"kind":"monster","team":1,"lane":"mid","zone":"lane","slot":-1,"uid":"","def":"e01","alive":false,"hp":0.0,"max_hp":100.03500000000001,"shield":0.0,"x":-0.6025248169898987,"y":-1.183314561843872,"facing":-0.7853981633974483,"progress":30.181223480769713,"target":-1,"hits":12,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":32,"kind":"monster","team":1,"lane":"mid","zone":"lane","slot":-1,"uid":"","def":"e01","alive":false,"hp":0.0,"max_hp":100.03500000000001,"shield":0.0,"x":0.2985708713531494,"y":-0.23837746679782867,"facing":-0.785398207300417,"progress":30.20001472364576,"target":-1,"hits":12,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":33,"kind":"monster","team":1,"lane":"mid","zone":"lane","slot":-1,"uid":"","def":"e01","alive":false,"hp":0.0,"max_hp":100.03500000000001,"shield":0.0,"x":1.2298187017440796,"y":0.6764076948165894,"facing":-0.7853983769520584,"progress":30.176166371817065,"target":-1,"hits":12,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":34,"kind":"monster","team":1,"lane":"bot","zone":"lane","slot":-1,"uid":"","def":"e01","alive":false,"hp":0.0,"max_hp":100.03500000000001,"shield":0.0,"x":22.51051139831543,"y":22.507102966308594,"facing":-2.3529882912562807,"progress":48.4104163646698,"target":-1,"hits":5,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":35,"kind":"monster","team":1,"lane":"bot","zone":"lane","slot":-1,"uid":"","def":"e01","alive":false,"hp":0.0,"max_hp":100.03500000000001,"shield":0.0,"x":23.4947566986084,"y":22.728078842163086,"facing":2.350014099169128,"progress":48.11259454169054,"target":-1,"hits":7,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":36,"kind":"monster","team":1,"lane":"bot","zone":"lane","slot":-1,"uid":"","def":"e01","alive":false,"hp":0.0,"max_hp":100.03500000000001,"shield":0.0,"x":22.71196174621582,"y":23.500873565673828,"facing":-0.7915785544206653,"progress":48.782345006484604,"target":-1,"hits":6,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":37,"kind":"champion","team":0,"lane":"bot","zone":"lane","slot":0,"uid":"c0-1","def":"s04","alive":true,"hp":653.4450000000004,"max_hp":1589.4450000000004,"shield":0.0,"x":27.866182327270508,"y":13.439833641052246,"facing":2.69120384714436,"progress":61.040272104935255,"target":15,"hits":11,"reached":false,"dormant":false,"effects":[],"dots":[]}]},{"label":"settled","phase":0,"round":3,"winner":-2,"end_note":"","players":[{"gold":1220,"draft_gold":1220,"ready":true,"earned":180,"spent":0,"next_seq":3,"roster":[],"hero":"","bookings":[],"new_bookings":[],"draft_roster":[],"draft_hero":"","boss_lane":"","undo":0},{"gold":400,"draft_gold":400,"ready":true,"earned":180,"spent":0,"next_seq":1,"roster":[],"hero":"","bookings":[],"new_bookings":[],"draft_roster":[],"draft_hero":"","boss_lane":"","undo":0},{"gold":400,"draft_gold":400,"ready":true,"earned":180,"spent":0,"next_seq":1,"roster":[],"hero":"","bookings":[],"new_bookings":[],"draft_roster":[],"draft_hero":"","boss_lane":"","undo":0},{"gold":414,"draft_gold":414,"ready":true,"earned":194,"spent":0,"next_seq":1,"roster":[],"hero":"","bookings":[],"new_bookings":[],"draft_roster":[],"draft_hero":"","boss_lane":"","undo":0},{"gold":414,"draft_gold":414,"ready":true,"earned":194,"spent":0,"next_seq":1,"roster":[],"hero":"","bookings":[],"new_bookings":[],"draft_roster":[],"draft_hero":"","boss_lane":"","undo":0},{"gold":454,"draft_gold":454,"ready":true,"earned":234,"spent":0,"next_seq":1,"roster":[],"hero":"","bookings":[],"new_bookings":[],"draft_roster":[],"draft_hero":"","boss_lane":"","undo":0}],"buildings":[7500.0,6000.0,7500.0,6000.0,7500.0,6000.0,9000.0,9000.0,12000.0,7500.0,6000.0,7500.0,6000.0,7500.0,5037.192960000004,9000.0,9000.0,12000.0],"boss":{"next":1,"settled":2,"claim":""},"boss_log":[],"announcements":[],"settlement":{"round":2,"gains":[18,18,18,32,32,72],"income":74,"lost":[],"end_reason":"cleared","combat_time":35.30000000000013,"boss":"none","lane_kills":{"bot":7,"top":6,"mid":6},"xp":{}},"combat":{"round":2,"steps":706,"elapsed":35.30000000000013,"finished":true,"end_reason":"cleared","destroyed":[],"grotto":"none|-1|-1|true","grotto_boss":"","grotto_boss_hp":0.0,"events":19,"mobile":[0,0,0]},"events":[[1,248,12.400000000000041,0,"bot","lane","monster",25,"e01",6,"",14,[]],[2,248,12.400000000000041,1,"bot","lane","monster",34,"e01",6,"",14,[]],[3,278,13.900000000000063,0,"top","lane","monster",21,"e01",6,"",14,[]],[4,278,13.900000000000063,1,"top","lane","monster",30,"e01",6,"",14,[]],[5,298,14.900000000000077,1,"bot","lane","monster",36,"e01",6,"",14,[]],[6,319,15.950000000000092,0,"mid","lane","monster",22,"e01",6,"",14,[]],[7,319,15.950000000000092,0,"mid","lane","monster",23,"e01",6,"",14,[]],[8,319,15.950000000000092,0,"mid","lane","monster",24,"e01",6,"",14,[]],[9,319,15.950000000000092,1,"mid","lane","monster",31,"e01",6,"",14,[]],[10,319,15.950000000000092,1,"mid","lane","monster",32,"e01",6,"",14,[]],[11,319,15.950000000000092,1,"mid","lane","monster",33,"e01",6,"",14,[]],[12,349,17.450000000000113,1,"bot","lane","monster",35,"e01",6,"",14,[]],[13,393,19.650000000000144,0,"top","lane","monster",19,"e01",6,"",14,[]],[14,393,19.650000000000144,1,"top","lane","monster",28,"e01",6,"",14,[]],[15,406,20.300000000000153,0,"bot","lane","monster",26,"e01",6,"",14,[]],[16,426,21.300000000000168,0,"bot","lane","monster",27,"e01",6,"",14,[]],[17,521,26.050000000000235,0,"top","lane","monster",20,"e01",6,"",14,[]],[18,521,26.050000000000235,1,"top","lane","monster",29,"e01",6,"",14,[]],[19,706,35.30000000000013,0,"bot","lane","champion",37,"s04",82,"",34,[]]]},{"label":"consumed","phase":1,"round":3,"winner":-2,"end_note":"","players":[{"gold":1220,"draft_gold":1220,"ready":true,"earned":180,"spent":0,"next_seq":3,"roster":[],"hero":"","bookings":[],"new_bookings":[],"draft_roster":[],"draft_hero":"","boss_lane":"","undo":0},{"gold":400,"draft_gold":400,"ready":true,"earned":180,"spent":0,"next_seq":1,"roster":[],"hero":"","bookings":[],"new_bookings":[],"draft_roster":[],"draft_hero":"","boss_lane":"","undo":0},{"gold":400,"draft_gold":400,"ready":true,"earned":180,"spent":0,"next_seq":1,"roster":[],"hero":"","bookings":[],"new_bookings":[],"draft_roster":[],"draft_hero":"","boss_lane":"","undo":0},{"gold":414,"draft_gold":414,"ready":true,"earned":194,"spent":0,"next_seq":1,"roster":[],"hero":"","bookings":[],"new_bookings":[],"draft_roster":[],"draft_hero":"","boss_lane":"","undo":0},{"gold":414,"draft_gold":414,"ready":true,"earned":194,"spent":0,"next_seq":1,"roster":[],"hero":"","bookings":[],"new_bookings":[],"draft_roster":[],"draft_hero":"","boss_lane":"","undo":0},{"gold":454,"draft_gold":454,"ready":true,"earned":234,"spent":0,"next_seq":1,"roster":[],"hero":"","bookings":[],"new_bookings":[],"draft_roster":[],"draft_hero":"","boss_lane":"","undo":0}],"buildings":[7500.0,6000.0,7500.0,6000.0,7500.0,6000.0,9000.0,9000.0,12000.0,7500.0,6000.0,7500.0,6000.0,7500.0,5037.192960000004,9000.0,9000.0,12000.0],"boss":{"next":1,"settled":2,"claim":""},"boss_log":[],"announcements":[],"settlement":{"round":2,"gains":[18,18,18,32,32,72],"income":74,"lost":[],"end_reason":"cleared","combat_time":35.30000000000013,"boss":"none","lane_kills":{"bot":7,"top":6,"mid":6},"xp":{}},"combat":{"round":3,"steps":0,"elapsed":0.0,"finished":false,"end_reason":"","destroyed":[],"grotto":"none|-1|-1|true","grotto_boss":"","grotto_boss_hp":0.0,"events":0,"mobile":[9,9,0]}}],"results":[["cmd",0,"champion_book",true,"Keilbrecher für die nächste Runde auf Bottom gebucht."],["cmd",0,"champion_book",true,"Dunstsänger für die nächste Runde auf Top gebucht."],["cmd",0,"champion_book",false,"Höchstens 2 Angriffschampions pro Runde."],["cmd",0,"champion_cancel",true,"Buchung zurückgenommen."],["begin",-1,"",true,""],["cmd",0,"champion_cancel",false,"Nur Buchungen aus dieser Planung lassen sich zurücknehmen."],["begin",-1,"",true,""],["begin",-1,"",true,""]]},"boss_cycle":{"title":"Bossversuch erfolgreich, Anspruch, Entsendung auf gewählter Lane, Boss getötet mit Kopfgeld, dreirundige Sperre, Wiederverfügbarkeit","snapshots":[{"label":"round-1","phase":0,"round":2,"winner":-2,"end_note":"","players":[{"gold":308,"draft_gold":308,"ready":true,"earned":88,"spent":0,"next_seq":1,"roster":[],"hero":"","bookings":[],"new_bookings":[],"draft_roster":[],"draft_hero":"","boss_lane":"","undo":0},{"gold":308,"draft_gold":308,"ready":true,"earned":88,"spent":0,"next_seq":1,"roster":[],"hero":"","bookings":[],"new_bookings":[],"draft_roster":[],"draft_hero":"","boss_lane":"","undo":0},{"gold":308,"draft_gold":308,"ready":true,"earned":88,"spent":0,"next_seq":1,"roster":[],"hero":"","bookings":[],"new_bookings":[],"draft_roster":[],"draft_hero":"","boss_lane":"","undo":0},{"gold":308,"draft_gold":308,"ready":true,"earned":88,"spent":0,"next_seq":1,"roster":[],"hero":"","bookings":[],"new_bookings":[],"draft_roster":[],"draft_hero":"","boss_lane":"","undo":0},{"gold":308,"draft_gold":308,"ready":true,"earned":88,"spent":0,"next_seq":1,"roster":[],"hero":"","bookings":[],"new_bookings":[],"draft_roster":[],"draft_hero":"","boss_lane":"","undo":0},{"gold":308,"draft_gold":308,"ready":true,"earned":88,"spent":0,"next_seq":1,"roster":[],"hero":"","bookings":[],"new_bookings":[],"draft_roster":[],"draft_hero":"","boss_lane":"","undo":0}],"buildings":[7500.0,6000.0,7500.0,6000.0,7500.0,6000.0,9000.0,9000.0,12000.0,7500.0,6000.0,7500.0,6000.0,7500.0,6000.0,9000.0,9000.0,12000.0],"boss":{"next":1,"settled":1,"claim":""},"boss_log":[],"announcements":[],"settlement":{"round":1,"gains":[18,18,18,18,18,18],"income":70,"lost":[],"end_reason":"cleared","combat_time":26.050000000000235,"boss":"none","lane_kills":{"bot":6,"top":6,"mid":6},"xp":{}},"combat":{"round":1,"steps":521,"elapsed":26.050000000000235,"finished":true,"end_reason":"cleared","destroyed":[],"grotto":"none|-1|-1|true","grotto_boss":"","grotto_boss_hp":0.0,"events":18,"mobile":[0,0,0]}},{"label":"round-2","phase":0,"round":3,"winner":-2,"end_note":"","players":[{"gold":400,"draft_gold":400,"ready":true,"earned":180,"spent":0,"next_seq":1,"roster":[],"hero":"","bookings":[],"new_bookings":[],"draft_roster":[],"draft_hero":"","boss_lane":"","undo":0},{"gold":400,"draft_gold":400,"ready":true,"earned":180,"spent":0,"next_seq":1,"roster":[],"hero":"","bookings":[],"new_bookings":[],"draft_roster":[],"draft_hero":"","boss_lane":"","undo":0},{"gold":400,"draft_gold":400,"ready":true,"earned":180,"spent":0,"next_seq":1,"roster":[],"hero":"","bookings":[],"new_bookings":[],"draft_roster":[],"draft_hero":"","boss_lane":"","undo":0},{"gold":400,"draft_gold":400,"ready":true,"earned":180,"spent":0,"next_seq":1,"roster":[],"hero":"","bookings":[],"new_bookings":[],"draft_roster":[],"draft_hero":"","boss_lane":"","undo":0},{"gold":400,"draft_gold":400,"ready":true,"earned":180,"spent":0,"next_seq":1,"roster":[],"hero":"","bookings":[],"new_bookings":[],"draft_roster":[],"draft_hero":"","boss_lane":"","undo":0},{"gold":400,"draft_gold":400,"ready":true,"earned":180,"spent":0,"next_seq":1,"roster":[],"hero":"","bookings":[],"new_bookings":[],"draft_roster":[],"draft_hero":"","boss_lane":"","undo":0}],"buildings":[7500.0,6000.0,7500.0,6000.0,7500.0,6000.0,9000.0,9000.0,12000.0,7500.0,6000.0,7500.0,6000.0,7500.0,6000.0,9000.0,9000.0,12000.0],"boss":{"next":1,"settled":2,"claim":""},"boss_log":[],"announcements":[],"settlement":{"round":2,"gains":[18,18,18,18,18,18],"income":74,"lost":[],"end_reason":"cleared","combat_time":26.050000000000235,"boss":"none","lane_kills":{"bot":6,"top":6,"mid":6},"xp":{}},"combat":{"round":2,"steps":521,"elapsed":26.050000000000235,"finished":true,"end_reason":"cleared","destroyed":[],"grotto":"none|-1|-1|true","grotto_boss":"","grotto_boss_hp":0.0,"events":18,"mobile":[0,0,0]}},{"label":"round-3","phase":0,"round":4,"winner":-2,"end_note":"","players":[{"gold":510,"draft_gold":510,"ready":true,"earned":290,"spent":0,"next_seq":1,"roster":[],"hero":"","bookings":[],"new_bookings":[],"draft_roster":[],"draft_hero":"","boss_lane":"","undo":0},{"gold":510,"draft_gold":510,"ready":true,"earned":290,"spent":0,"next_seq":1,"roster":[],"hero":"","bookings":[],"new_bookings":[],"draft_roster":[],"draft_hero":"","boss_lane":"","undo":0},{"gold":510,"draft_gold":510,"ready":true,"earned":290,"spent":0,"next_seq":1,"roster":[],"hero":"","bookings":[],"new_bookings":[],"draft_roster":[],"draft_hero":"","boss_lane":"","undo":0},{"gold":510,"draft_gold":510,"ready":true,"earned":290,"spent":0,"next_seq":1,"roster":[],"hero":"","bookings":[],"new_bookings":[],"draft_roster":[],"draft_hero":"","boss_lane":"","undo":0},{"gold":510,"draft_gold":510,"ready":true,"earned":290,"spent":0,"next_seq":1,"roster":[],"hero":"","bookings":[],"new_bookings":[],"draft_roster":[],"draft_hero":"","boss_lane":"","undo":0},{"gold":510,"draft_gold":510,"ready":true,"earned":290,"spent":0,"next_seq":1,"roster":[],"hero":"","bookings":[],"new_bookings":[],"draft_roster":[],"draft_hero":"","boss_lane":"","undo":0}],"buildings":[7500.0,6000.0,7500.0,6000.0,7500.0,6000.0,9000.0,9000.0,12000.0,7500.0,6000.0,7500.0,6000.0,7500.0,6000.0,9000.0,9000.0,12000.0],"boss":{"next":1,"settled":3,"claim":""},"boss_log":[],"announcements":[],"settlement":{"round":3,"gains":[32,32,32,32,32,32],"income":78,"lost":[],"end_reason":"cleared","combat_time":47.899999999999416,"boss":"none","lane_kills":{"mid":6,"bot":6,"top":6},"xp":{}},"combat":{"round":3,"steps":958,"elapsed":47.899999999999416,"finished":true,"end_reason":"cleared","destroyed":[],"grotto":"none|-1|-1|true","grotto_boss":"","grotto_boss_hp":0.0,"events":18,"mobile":[0,0,0]}},{"label":"round-4","phase":0,"round":5,"winner":-2,"end_note":"","players":[{"gold":632,"draft_gold":632,"ready":true,"earned":412,"spent":0,"next_seq":1,"roster":[],"hero":"","bookings":[],"new_bookings":[],"draft_roster":[],"draft_hero":"","boss_lane":"","undo":0},{"gold":632,"draft_gold":632,"ready":true,"earned":412,"spent":0,"next_seq":1,"roster":[],"hero":"","bookings":[],"new_bookings":[],"draft_roster":[],"draft_hero":"","boss_lane":"","undo":0},{"gold":632,"draft_gold":632,"ready":true,"earned":412,"spent":0,"next_seq":1,"roster":[],"hero":"","bookings":[],"new_bookings":[],"draft_roster":[],"draft_hero":"","boss_lane":"","undo":0},{"gold":632,"draft_gold":632,"ready":true,"earned":412,"spent":0,"next_seq":1,"roster":[],"hero":"","bookings":[],"new_bookings":[],"draft_roster":[],"draft_hero":"","boss_lane":"","undo":0},{"gold":632,"draft_gold":632,"ready":true,"earned":412,"spent":0,"next_seq":1,"roster":[],"hero":"","bookings":[],"new_bookings":[],"draft_roster":[],"draft_hero":"","boss_lane":"","undo":0},{"gold":632,"draft_gold":632,"ready":true,"earned":412,"spent":0,"next_seq":1,"roster":[],"hero":"","bookings":[],"new_bookings":[],"draft_roster":[],"draft_hero":"","boss_lane":"","undo":0}],"buildings":[7500.0,6000.0,7500.0,6000.0,7500.0,6000.0,9000.0,9000.0,12000.0,7500.0,6000.0,7500.0,6000.0,7500.0,6000.0,9000.0,9000.0,12000.0],"boss":{"next":1,"settled":4,"claim":""},"boss_log":[],"announcements":[],"settlement":{"round":4,"gains":[40,40,40,40,40,40],"income":82,"lost":[],"end_reason":"cleared","combat_time":50.84999999999925,"boss":"none","lane_kills":{"mid":8,"bot":8,"top":8},"xp":{}},"combat":{"round":4,"steps":1017,"elapsed":50.84999999999925,"finished":true,"end_reason":"cleared","destroyed":[],"grotto":"none|-1|-1|true","grotto_boss":"","grotto_boss_hp":0.0,"events":24,"mobile":[0,0,0]}},{"label":"round-5","phase":0,"round":6,"winner":-2,"end_note":"","players":[{"gold":763,"draft_gold":763,"ready":true,"earned":543,"spent":0,"next_seq":1,"roster":[],"hero":"","bookings":[],"new_bookings":[],"draft_roster":[],"draft_hero":"","boss_lane":"","undo":0},{"gold":763,"draft_gold":763,"ready":true,"earned":543,"spent":0,"next_seq":1,"roster":[],"hero":"","bookings":[],"new_bookings":[],"draft_roster":[],"draft_hero":"","boss_lane":"","undo":0},{"gold":763,"draft_gold":763,"ready":true,"earned":543,"spent":0,"next_seq":1,"roster":[],"hero":"","bookings":[],"new_bookings":[],"draft_roster":[],"draft_hero":"","boss_lane":"","undo":0},{"gold":763,"draft_gold":763,"ready":true,"earned":543,"spent":0,"next_seq":1,"roster":[],"hero":"","bookings":[],"new_bookings":[],"draft_roster":[],"draft_hero":"","boss_lane":"","undo":0},{"gold":763,"draft_gold":763,"ready":true,"earned":543,"spent":0,"next_seq":1,"roster":[],"hero":"","bookings":[],"new_bookings":[],"draft_roster":[],"draft_hero":"","boss_lane":"","undo":0},{"gold":763,"draft_gold":763,"ready":true,"earned":543,"spent":0,"next_seq":1,"roster":[],"hero":"","bookings":[],"new_bookings":[],"draft_roster":[],"draft_hero":"","boss_lane":"","undo":0}],"buildings":[7500.0,6000.0,7500.0,6000.0,7500.0,6000.0,9000.0,9000.0,12000.0,7500.0,6000.0,7500.0,6000.0,7500.0,6000.0,9000.0,9000.0,12000.0],"boss":{"next":1,"settled":5,"claim":""},"boss_log":[],"announcements":[],"settlement":{"round":5,"gains":[45,45,45,45,45,45],"income":86,"lost":[],"end_reason":"cleared","combat_time":32.55000000000029,"boss":"none","lane_kills":{"mid":8,"bot":8,"top":8},"xp":{}},"combat":{"round":5,"steps":651,"elapsed":32.55000000000029,"finished":true,"end_reason":"cleared","destroyed":[],"grotto":"none|-1|-1|true","grotto_boss":"","grotto_boss_hp":0.0,"events":24,"mobile":[0,0,0]}},{"label":"expedition","phase":1,"round":6,"winner":-2,"end_note":"","players":[{"gold":763,"draft_gold":763,"ready":true,"earned":543,"spent":0,"next_seq":1,"roster":[],"hero":"","bookings":[],"new_bookings":[],"draft_roster":[],"draft_hero":"","boss_lane":"","undo":0},{"gold":5078,"draft_gold":5078,"ready":true,"earned":543,"spent":0,"next_seq":9,"roster":["p1-1|w04|grotto|230","p1-2|w04|grotto|230","p1-3|w04|grotto|230","p1-4|w02|grotto|150","p1-5|w06|grotto|195","p1-6|w06|grotto|195","p1-7|w06|grotto|195"],"hero":"h1-8|held_ringborke|0|grotto|||260|false|","bookings":[],"new_bookings":[],"draft_roster":["p1-1|w04|grotto|230|true","p1-2|w04|grotto|230|true","p1-3|w04|grotto|230|true","p1-4|w02|grotto|150|true","p1-5|w06|grotto|195|true","p1-6|w06|grotto|195|true","p1-7|w06|grotto|195|true"],"draft_hero":"h1-8|held_ringborke|0|grotto|||260|true|","boss_lane":"","undo":0},{"gold":763,"draft_gold":763,"ready":true,"earned":543,"spent":0,"next_seq":1,"roster":[],"hero":"","bookings":[],"new_bookings":[],"draft_roster":[],"draft_hero":"","boss_lane":"","undo":0},{"gold":763,"draft_gold":763,"ready":true,"earned":543,"spent":0,"next_seq":1,"roster":[],"hero":"","bookings":[],"new_bookings":[],"draft_roster":[],"draft_hero":"","boss_lane":"","undo":0},{"gold":763,"draft_gold":763,"ready":true,"earned":543,"spent":0,"next_seq":1,"roster":[],"hero":"","bookings":[],"new_bookings":[],"draft_roster":[],"draft_hero":"","boss_lane":"","undo":0},{"gold":763,"draft_gold":763,"ready":true,"earned":543,"spent":0,"next_seq":1,"roster":[],"hero":"","bookings":[],"new_bookings":[],"draft_roster":[],"draft_hero":"","boss_lane":"","undo":0}],"buildings":[7500.0,6000.0,7500.0,6000.0,7500.0,6000.0,9000.0,9000.0,12000.0,7500.0,6000.0,7500.0,6000.0,7500.0,6000.0,9000.0,9000.0,12000.0],"boss":{"next":1,"settled":5,"claim":""},"boss_log":[],"announcements":[],"settlement":{"round":5,"gains":[45,45,45,45,45,45],"income":86,"lost":[],"end_reason":"cleared","combat_time":32.55000000000029,"boss":"none","lane_kills":{"mid":8,"bot":8,"top":8},"xp":{}},"combat":{"round":6,"steps":0,"elapsed":0.0,"finished":false,"end_reason":"","destroyed":[],"grotto":"none|-1|-1|false","grotto_boss":"true|true|51","grotto_boss_hp":5715.000000000001,"events":0,"mobile":[20,12,1]},"units":[{"id":1,"kind":"tower","team":0,"lane":"top","zone":"lane","slot":-1,"uid":"","def":"blau_top_inner","alive":true,"hp":7500.0,"max_hp":7500.0,"shield":0.0,"x":-24.931251525878906,"y":4.5293378829956055,"facing":0.0,"progress":0.0,"target":-1,"hits":0,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":2,"kind":"tower","team":0,"lane":"top","zone":"lane","slot":-1,"uid":"","def":"blau_top_outer","alive":true,"hp":6000.0,"max_hp":6000.0,"shield":0.0,"x":-24.921451568603516,"y":-12.715348243713379,"facing":0.0,"progress":0.0,"target":-1,"hits":0,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":3,"kind":"tower","team":0,"lane":"mid","zone":"lane","slot":-1,"uid":"","def":"blau_mid_inner","alive":true,"hp":7500.0,"max_hp":7500.0,"shield":0.0,"x":-11.427590370178223,"y":17.012392044067383,"facing":0.0,"progress":0.0,"target":-1,"hits":0,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":4,"kind":"tower","team":0,"lane":"mid","zone":"lane","slot":-1,"uid":"","def":"blau_mid_outer","alive":true,"hp":6000.0,"max_hp":6000.0,"shield":0.0,"x":-3.8433847427368164,"y":8.990991592407227,"facing":0.0,"progress":0.0,"target":-1,"hits":0,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":5,"kind":"tower","team":0,"lane":"bot","zone":"lane","slot":-1,"uid":"","def":"blau_bot_inner","alive":true,"hp":7500.0,"max_hp":7500.0,"shield":0.0,"x":-4.349228858947754,"y":31.034507751464844,"facing":0.0,"progress":0.0,"target":-1,"hits":0,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":6,"kind":"tower","team":0,"lane":"bot","zone":"lane","slot":-1,"uid":"","def":"blau_bot_outer","alive":true,"hp":6000.0,"max_hp":6000.0,"shield":0.0,"x":11.117134094238281,"y":28.989334106445313,"facing":0.0,"progress":0.0,"target":-1,"hits":0,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":7,"kind":"tower","team":0,"lane":"base","zone":"lane","slot":-1,"uid":"","def":"blau_base_1","alive":true,"hp":9000.0,"max_hp":9000.0,"shield":0.0,"x":-29.476999282836914,"y":24.023000717163086,"facing":0.0,"progress":0.0,"target":-1,"hits":0,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":8,"kind":"tower","team":0,"lane":"base","zone":"lane","slot":-1,"uid":"","def":"blau_base_2","alive":true,"hp":9000.0,"max_hp":9000.0,"shield":0.0,"x":-24.023000717163086,"y":29.476999282836914,"facing":0.0,"progress":0.0,"target":-1,"hits":0,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":9,"kind":"core","team":0,"lane":"base","zone":"lane","slot":-1,"uid":"","def":"blau_ancient","alive":true,"hp":12000.0,"max_hp":12000.0,"shield":0.0,"x":-30.0,"y":30.0,"facing":0.0,"progress":0.0,"target":-1,"hits":0,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":10,"kind":"tower","team":1,"lane":"top","zone":"lane","slot":-1,"uid":"","def":"rot_top_inner","alive":true,"hp":7500.0,"max_hp":7500.0,"shield":0.0,"x":4.5293378829956055,"y":-24.931251525878906,"facing":0.0,"progress":0.0,"target":-1,"hits":0,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":11,"kind":"tower","team":1,"lane":"top","zone":"lane","slot":-1,"uid":"","def":"rot_top_outer","alive":true,"hp":6000.0,"max_hp":6000.0,"shield":0.0,"x":-12.715348243713379,"y":-24.921451568603516,"facing":0.0,"progress":0.0,"target":-1,"hits":0,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":12,"kind":"tower","team":1,"lane":"mid","zone":"lane","slot":-1,"uid":"","def":"rot_mid_inner","alive":true,"hp":7500.0,"max_hp":7500.0,"shield":0.0,"x":17.012392044067383,"y":-11.427590370178223,"facing":0.0,"progress":0.0,"target":-1,"hits":0,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":13,"kind":"tower","team":1,"lane":"mid","zone":"lane","slot":-1,"uid":"","def":"rot_mid_outer","alive":true,"hp":6000.0,"max_hp":6000.0,"shield":0.0,"x":8.990991592407227,"y":-3.8433847427368164,"facing":0.0,"progress":0.0,"target":-1,"hits":0,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":14,"kind":"tower","team":1,"lane":"bot","zone":"lane","slot":-1,"uid":"","def":"rot_bot_inner","alive":true,"hp":7500.0,"max_hp":7500.0,"shield":0.0,"x":31.034507751464844,"y":-4.349228858947754,"facing":0.0,"progress":0.0,"target":-1,"hits":0,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":15,"kind":"tower","team":1,"lane":"bot","zone":"lane","slot":-1,"uid":"","def":"rot_bot_outer","alive":true,"hp":6000.0,"max_hp":6000.0,"shield":0.0,"x":28.989334106445313,"y":11.117134094238281,"facing":0.0,"progress":0.0,"target":-1,"hits":0,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":16,"kind":"tower","team":1,"lane":"base","zone":"lane","slot":-1,"uid":"","def":"rot_base_1","alive":true,"hp":9000.0,"max_hp":9000.0,"shield":0.0,"x":24.023000717163086,"y":-29.476999282836914,"facing":0.0,"progress":0.0,"target":-1,"hits":0,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":17,"kind":"tower","team":1,"lane":"base","zone":"lane","slot":-1,"uid":"","def":"rot_base_2","alive":true,"hp":9000.0,"max_hp":9000.0,"shield":0.0,"x":29.476999282836914,"y":-24.023000717163086,"facing":0.0,"progress":0.0,"target":-1,"hits":0,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":18,"kind":"core","team":1,"lane":"base","zone":"lane","slot":-1,"uid":"","def":"rot_ancient","alive":true,"hp":12000.0,"max_hp":12000.0,"shield":0.0,"x":30.0,"y":-30.0,"facing":0.0,"progress":0.0,"target":-1,"hits":0,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":19,"kind":"monster","team":0,"lane":"top","zone":"lane","slot":-1,"uid":"","def":"e01","alive":true,"hp":142.875,"max_hp":142.875,"shield":0.0,"x":-28.243892669677734,"y":10.502157211303711,"facing":-2.864119239296395,"progress":11.0,"target":-1,"hits":0,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":20,"kind":"monster","team":0,"lane":"top","zone":"lane","slot":-1,"uid":"","def":"e02","alive":true,"hp":381.00000000000006,"max_hp":381.00000000000006,"shield":0.0,"x":-26.993616104125977,"y":10.146052360534668,"facing":-2.864119239296395,"progress":11.0,"target":-1,"hits":0,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":21,"kind":"monster","team":0,"lane":"top","zone":"lane","slot":-1,"uid":"","def":"e01","alive":true,"hp":142.875,"max_hp":142.875,"shield":0.0,"x":-25.74333953857422,"y":9.789947509765625,"facing":-2.864119239296395,"progress":11.0,"target":-1,"hits":0,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":22,"kind":"monster","team":0,"lane":"top","zone":"lane","slot":-1,"uid":"","def":"e04","alive":true,"hp":206.37500000000003,"max_hp":206.37500000000003,"shield":0.0,"x":-27.921968460083008,"y":11.702203750610352,"facing":-2.9843745641096318,"progress":9.6,"target":-1,"hits":0,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":23,"kind":"monster","team":0,"lane":"mid","zone":"lane","slot":-1,"uid":"","def":"e01","alive":true,"hp":142.875,"max_hp":142.875,"shield":0.0,"x":-14.408708572387695,"y":13.32747745513916,"facing":2.3870002372622334,"progress":11.0,"target":-1,"hits":0,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":24,"kind":"monster","team":0,"lane":"mid","zone":"lane","slot":-1,"uid":"","def":"e02","alive":true,"hp":381.00000000000006,"max_hp":381.00000000000006,"shield":0.0,"x":-13.461592674255371,"y":14.21796703338623,"facing":2.3870002372622334,"progress":11.0,"target":-1,"hits":0,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":25,"kind":"monster","team":0,"lane":"mid","zone":"lane","slot":-1,"uid":"","def":"e01","alive":true,"hp":142.875,"max_hp":142.875,"shield":0.0,"x":-12.514476776123047,"y":15.1084566116333,"facing":2.3870002372622334,"progress":11.0,"target":-1,"hits":0,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":26,"kind":"monster","team":0,"lane":"mid","zone":"lane","slot":-1,"uid":"","def":"e04","alive":true,"hp":206.37500000000003,"max_hp":206.37500000000003,"shield":0.0,"x":-15.366670608520508,"y":14.327392578125,"facing":2.3752783515087157,"progress":9.6,"target":-1,"hits":0,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":27,"kind":"monster","team":0,"lane":"bot","zone":"lane","slot":-1,"uid":"","def":"e01","alive":true,"hp":142.875,"max_hp":142.875,"shield":0.0,"x":-9.842267036437988,"y":25.94097137451172,"facing":1.4313591016628469,"progress":11.0,"target":-1,"hits":0,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":28,"kind":"monster","team":0,"lane":"bot","zone":"lane","slot":-1,"uid":"","def":"e02","alive":true,"hp":381.00000000000006,"max_hp":381.00000000000006,"shield":0.0,"x":-10.022948265075684,"y":27.22835350036621,"facing":1.4313591016628469,"progress":11.0,"target":-1,"hits":0,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":29,"kind":"monster","team":0,"lane":"bot","zone":"lane","slot":-1,"uid":"","def":"e01","alive":true,"hp":142.875,"max_hp":142.875,"shield":0.0,"x":-10.203629493713379,"y":28.515735626220703,"facing":1.4313591016628469,"progress":11.0,"target":-1,"hits":0,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":30,"kind":"monster","team":0,"lane":"bot","zone":"lane","slot":-1,"uid":"","def":"e04","alive":true,"hp":206.37500000000003,"max_hp":206.37500000000003,"shield":0.0,"x":-11.322441101074219,"y":25.77979278564453,"facing":1.5004101357551378,"progress":9.6,"target":-1,"hits":0,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":31,"kind":"monster","team":1,"lane":"top","zone":"lane","slot":-1,"uid":"","def":"e01","alive":true,"hp":142.875,"max_hp":142.875,"shield":0.0,"x":10.502157211303711,"y":-28.243892669677734,"facing":-1.8482697410882951,"progress":11.0,"target":-1,"hits":0,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":32,"kind":"monster","team":1,"lane":"top","zone":"lane","slot":-1,"uid":"","def":"e02","alive":true,"hp":381.00000000000006,"max_hp":381.00000000000006,"shield":0.0,"x":10.146052360534668,"y":-26.993616104125977,"facing":-1.8482697410882951,"progress":11.0,"target":-1,"hits":0,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":33,"kind":"monster","team":1,"lane":"top","zone":"lane","slot":-1,"uid":"","def":"e01","alive":true,"hp":142.875,"max_hp":142.875,"shield":0.0,"x":9.789947509765625,"y":-25.74333953857422,"facing":-1.8482697410882951,"progress":11.0,"target":-1,"hits":0,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":34,"kind":"monster","team":1,"lane":"top","zone":"lane","slot":-1,"uid":"","def":"e04","alive":true,"hp":206.37500000000003,"max_hp":206.37500000000003,"shield":0.0,"x":11.702203750610352,"y":-27.921968460083008,"facing":-1.7280144162750581,"progress":9.6,"target":-1,"hits":0,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":35,"kind":"monster","team":1,"lane":"mid","zone":"lane","slot":-1,"uid":"","def":"e01","alive":true,"hp":142.875,"max_hp":142.875,"shield":0.0,"x":13.32747745513916,"y":-14.408708572387695,"facing":-0.816203910467337,"progress":11.0,"target":-1,"hits":0,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":36,"kind":"monster","team":1,"lane":"mid","zone":"lane","slot":-1,"uid":"","def":"e02","alive":true,"hp":381.00000000000006,"max_hp":381.00000000000006,"shield":0.0,"x":14.21796703338623,"y":-13.461592674255371,"facing":-0.816203910467337,"progress":11.0,"target":-1,"hits":0,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":37,"kind":"monster","team":1,"lane":"mid","zone":"lane","slot":-1,"uid":"","def":"e01","alive":true,"hp":142.875,"max_hp":142.875,"shield":0.0,"x":15.1084566116333,"y":-12.514476776123047,"facing":-0.816203910467337,"progress":11.0,"target":-1,"hits":0,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":38,"kind":"monster","team":1,"lane":"mid","zone":"lane","slot":-1,"uid":"","def":"e04","alive":true,"hp":206.37500000000003,"max_hp":206.37500000000003,"shield":0.0,"x":14.327392578125,"y":-15.366670608520508,"facing":-0.804482024713819,"progress":9.6,"target":-1,"hits":0,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":39,"kind":"monster","team":1,"lane":"bot","zone":"lane","slot":-1,"uid":"","def":"e01","alive":true,"hp":142.875,"max_hp":142.875,"shield":0.0,"x":25.94097137451172,"y":-9.842267036437988,"facing":0.13943722513204979,"progress":11.0,"target":-1,"hits":0,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":40,"kind":"monster","team":1,"lane":"bot","zone":"lane","slot":-1,"uid":"","def":"e02","alive":true,"hp":381.00000000000006,"max_hp":381.00000000000006,"shield":0.0,"x":27.22835350036621,"y":-10.022948265075684,"facing":0.13943722513204979,"progress":11.0,"target":-1,"hits":0,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":41,"kind":"monster","team":1,"lane":"bot","zone":"lane","slot":-1,"uid":"","def":"e01","alive":true,"hp":142.875,"max_hp":142.875,"shield":0.0,"x":28.515735626220703,"y":-10.203629493713379,"facing":0.13943722513204979,"progress":11.0,"target":-1,"hits":0,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":42,"kind":"monster","team":1,"lane":"bot","zone":"lane","slot":-1,"uid":"","def":"e04","alive":true,"hp":206.37500000000003,"max_hp":206.37500000000003,"shield":0.0,"x":25.77979278564453,"y":-11.322441101074219,"facing":0.07038619103975874,"progress":9.6,"target":-1,"hits":0,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":43,"kind":"troop","team":0,"lane":"grotto","zone":"grotto","slot":1,"uid":"p1-1","def":"w04","alive":true,"hp":1560.0,"max_hp":1560.0,"shield":0.0,"x":-13.305871963500977,"y":-8.454777717590332,"facing":2.261898072281642,"progress":0.0,"target":-1,"hits":0,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":44,"kind":"troop","team":0,"lane":"grotto","zone":"grotto","slot":1,"uid":"p1-2","def":"w04","alive":true,"hp":1560.0,"max_hp":1560.0,"shield":0.0,"x":-12.300000190734863,"y":-8.899999618530273,"facing":2.261898072281642,"progress":0.0,"target":-1,"hits":0,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":45,"kind":"troop","team":0,"lane":"grotto","zone":"grotto","slot":1,"uid":"p1-3","def":"w04","alive":true,"hp":1560.0,"max_hp":1560.0,"shield":0.0,"x":-11.29412841796875,"y":-9.345221519470215,"facing":2.261898072281642,"progress":0.0,"target":-1,"hits":0,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":46,"kind":"hero","team":0,"lane":"grotto","zone":"grotto","slot":1,"uid":"h1-8","def":"w04","alive":true,"hp":2200.0,"max_hp":2200.0,"shield":0.0,"x":-12.820175170898438,"y":-7.357463359832764,"facing":2.261898072281642,"progress":0.0,"target":-1,"hits":0,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":47,"kind":"troop","team":0,"lane":"grotto","zone":"grotto","slot":1,"uid":"p1-4","def":"w02","alive":true,"hp":800.0,"max_hp":800.0,"shield":0.0,"x":-11.814303398132324,"y":-7.802685260772705,"facing":2.261898072281642,"progress":0.0,"target":-1,"hits":0,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":48,"kind":"troop","team":0,"lane":"grotto","zone":"grotto","slot":1,"uid":"p1-5","def":"w06","alive":true,"hp":630.0,"max_hp":630.0,"shield":0.0,"x":-10.808431625366211,"y":-8.247906684875488,"facing":2.261898072281642,"progress":0.0,"target":-1,"hits":0,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":49,"kind":"troop","team":0,"lane":"grotto","zone":"grotto","slot":1,"uid":"p1-6","def":"w06","alive":true,"hp":630.0,"max_hp":630.0,"shield":0.0,"x":-12.334479331970215,"y":-6.260149002075195,"facing":2.261898072281642,"progress":0.0,"target":-1,"hits":0,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":50,"kind":"troop","team":0,"lane":"grotto","zone":"grotto","slot":1,"uid":"p1-7","def":"w06","alive":true,"hp":630.0,"max_hp":630.0,"shield":0.0,"x":-11.328607559204102,"y":-6.705370903015137,"facing":2.261898072281642,"progress":0.0,"target":-1,"hits":0,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":51,"kind":"boss","team":2,"lane":"grotto","zone":"grotto","slot":-1,"uid":"","def":"e10","alive":true,"hp":5715.000000000001,"max_hp":5715.000000000001,"shield":0.0,"x":-15.0,"y":-15.0,"facing":-0.6911017454867453,"progress":0.0,"target":-1,"hits":0,"reached":false,"dormant":true,"effects":[],"dots":[]}]},{"label":"won","phase":0,"round":7,"winner":-2,"end_note":"","players":[{"gold":893,"draft_gold":893,"ready":true,"earned":673,"spent":0,"next_seq":1,"roster":[],"hero":"","bookings":[],"new_bookings":[],"draft_roster":[],"draft_hero":"","boss_lane":"","undo":0},{"gold":5208,"draft_gold":5208,"ready":true,"earned":673,"spent":0,"next_seq":9,"roster":["p1-1|w04|mid|230","p1-2|w04|mid|230","p1-3|w04|mid|230","p1-4|w02|mid|150","p1-5|w06|mid|195","p1-6|w06|mid|195","p1-7|w06|mid|195"],"hero":"h1-8|held_ringborke|296|mid|||260|false|","bookings":[],"new_bookings":[],"draft_roster":["p1-1|w04|mid|230|false","p1-2|w04|mid|230|false","p1-3|w04|mid|230|false","p1-4|w02|mid|150|false","p1-5|w06|mid|195|false","p1-6|w06|mid|195|false","p1-7|w06|mid|195|false"],"draft_hero":"h1-8|held_ringborke|296|mid|||260|false|","boss_lane":"","undo":0},{"gold":893,"draft_gold":893,"ready":true,"earned":673,"spent":0,"next_seq":1,"roster":[],"hero":"","bookings":[],"new_bookings":[],"draft_roster":[],"draft_hero":"","boss_lane":"","undo":0},{"gold":893,"draft_gold":893,"ready":true,"earned":673,"spent":0,"next_seq":1,"roster":[],"hero":"","bookings":[],"new_bookings":[],"draft_roster":[],"draft_hero":"","boss_lane":"","undo":0},{"gold":893,"draft_gold":893,"ready":true,"earned":673,"spent":0,"next_seq":1,"roster":[],"hero":"","bookings":[],"new_bookings":[],"draft_roster":[],"draft_hero":"","boss_lane":"","undo":0},{"gold":893,"draft_gold":893,"ready":true,"earned":673,"spent":0,"next_seq":1,"roster":[],"hero":"","bookings":[],"new_bookings":[],"draft_roster":[],"draft_hero":"","boss_lane":"","undo":0}],"buildings":[7500.0,6000.0,7500.0,6000.0,7500.0,6000.0,9000.0,9000.0,12000.0,7500.0,6000.0,7500.0,6000.0,7500.0,6000.0,9000.0,9000.0,12000.0],"boss":{"next":10,"settled":6,"claim":"0|6|7|1|mid"},"boss_log":["6|won|0||1"],"announcements":["boss|0|1|mid||940"],"settlement":{"round":6,"gains":[40,40,40,40,40,40],"income":90,"lost":[],"end_reason":"cleared","combat_time":40.79999999999982,"boss":"won","lane_kills":{"mid":8,"bot":8,"top":8},"xp":{"h1-8":296}},"combat":{"round":6,"steps":816,"elapsed":40.79999999999982,"finished":true,"end_reason":"cleared","destroyed":[],"grotto":"success|0|0|true","grotto_boss":"false|false|51","grotto_boss_hp":0.0,"events":25,"mobile":[8,0,0]},"events":[[1,199,9.950000000000006,0,"mid","lane","monster",23,"e01",7,"",18,[]],[2,199,9.950000000000006,1,"mid","lane","monster",35,"e01",7,"",18,[]],[3,220,11.000000000000021,0,"mid","lane","monster",25,"e01",7,"",18,[]],[4,220,11.000000000000021,1,"mid","lane","monster",37,"e01",7,"",18,[]],[5,239,11.950000000000035,0,"bot","lane","monster",27,"e01",7,"",18,[]],[6,239,11.950000000000035,1,"bot","lane","monster",39,"e01",7,"",18,[]],[7,275,13.75000000000006,0,"top","lane","monster",19,"e01",7,"",18,[]],[8,275,13.75000000000006,1,"top","lane","monster",31,"e01",7,"",18,[]],[9,279,13.950000000000063,2,"grotto","grotto","boss",51,"e10",0,"",220,["h1-8"]],[10,312,15.600000000000087,0,"top","lane","monster",21,"e01",7,"",18,[]],[11,312,15.600000000000087,1,"top","lane","monster",33,"e01",7,"",18,[]],[12,315,15.750000000000089,0,"bot","lane","monster",29,"e01",7,"",18,[]],[13,315,15.750000000000089,1,"bot","lane","monster",41,"e01",7,"",18,[]],[14,443,22.15000000000018,0,"mid","lane","monster",24,"e02",14,"",18,[]],[15,443,22.15000000000018,1,"mid","lane","monster",36,"e02",14,"",18,[]],[16,536,26.800000000000246,0,"top","lane","monster",20,"e02",14,"",18,[]],[17,536,26.800000000000246,1,"top","lane","monster",32,"e02",14,"",18,[]],[18,538,26.900000000000247,0,"bot","lane","monster",28,"e02",14,"",18,[]],[19,538,26.900000000000247,1,"bot","lane","monster",40,"e02",14,"",18,[]],[20,715,35.75000000000011,0,"mid","lane","monster",26,"e04",12,"",18,[]],[21,715,35.75000000000011,1,"mid","lane","monster",38,"e04",12,"",18,[]],[22,811,40.549999999999834,0,"top","lane","monster",22,"e04",12,"",18,[]],[23,811,40.549999999999834,1,"top","lane","monster",34,"e04",12,"",18,[]],[24,816,40.79999999999982,0,"bot","lane","monster",30,"e04",12,"",18,[]],[25,816,40.79999999999982,1,"bot","lane","monster",42,"e04",12,"",18,[]]]},{"label":"announced","phase":0,"round":7,"winner":-2,"end_note":"","players":[{"gold":893,"draft_gold":893,"ready":true,"earned":673,"spent":0,"next_seq":1,"roster":[],"hero":"","bookings":[],"new_bookings":[],"draft_roster":[],"draft_hero":"","boss_lane":"","undo":0},{"gold":5208,"draft_gold":5208,"ready":true,"earned":673,"spent":0,"next_seq":9,"roster":["p1-1|w04|mid|230","p1-2|w04|mid|230","p1-3|w04|mid|230","p1-4|w02|mid|150","p1-5|w06|mid|195","p1-6|w06|mid|195","p1-7|w06|mid|195"],"hero":"h1-8|held_ringborke|296|mid|||260|false|","bookings":[],"new_bookings":[],"draft_roster":["p1-1|w04|mid|230|false","p1-2|w04|mid|230|false","p1-3|w04|mid|230|false","p1-4|w02|mid|150|false","p1-5|w06|mid|195|false","p1-6|w06|mid|195|false","p1-7|w06|mid|195|false"],"draft_hero":"h1-8|held_ringborke|296|mid|||260|false|","boss_lane":"top","undo":2},{"gold":893,"draft_gold":893,"ready":true,"earned":673,"spent":0,"next_seq":1,"roster":[],"hero":"","bookings":[],"new_bookings":[],"draft_roster":[],"draft_hero":"","boss_lane":"","undo":0},{"gold":893,"draft_gold":893,"ready":true,"earned":673,"spent":0,"next_seq":1,"roster":[],"hero":"","bookings":[],"new_bookings":[],"draft_roster":[],"draft_hero":"","boss_lane":"","undo":0},{"gold":893,"draft_gold":893,"ready":true,"earned":673,"spent":0,"next_seq":1,"roster":[],"hero":"","bookings":[],"new_bookings":[],"draft_roster":[],"draft_hero":"","boss_lane":"","undo":0},{"gold":893,"draft_gold":893,"ready":true,"earned":673,"spent":0,"next_seq":1,"roster":[],"hero":"","bookings":[],"new_bookings":[],"draft_roster":[],"draft_hero":"","boss_lane":"","undo":0}],"buildings":[7500.0,6000.0,7500.0,6000.0,7500.0,6000.0,9000.0,9000.0,12000.0,7500.0,6000.0,7500.0,6000.0,7500.0,6000.0,9000.0,9000.0,12000.0],"boss":{"next":10,"settled":6,"claim":"0|6|7|1|mid"},"boss_log":["6|won|0||1"],"announcements":["boss|0|1|mid||940"],"settlement":{"round":6,"gains":[40,40,40,40,40,40],"income":90,"lost":[],"end_reason":"cleared","combat_time":40.79999999999982,"boss":"won","lane_kills":{"mid":8,"bot":8,"top":8},"xp":{"h1-8":296}},"combat":{"round":6,"steps":816,"elapsed":40.79999999999982,"finished":true,"end_reason":"cleared","destroyed":[],"grotto":"success|0|0|true","grotto_boss":"false|false|51","grotto_boss_hp":0.0,"events":25,"mobile":[8,0,0]}},{"label":"deployed","phase":1,"round":7,"winner":-2,"end_note":"","players":[{"gold":893,"draft_gold":893,"ready":true,"earned":673,"spent":0,"next_seq":1,"roster":[],"hero":"","bookings":[],"new_bookings":[],"draft_roster":[],"draft_hero":"","boss_lane":"","undo":0},{"gold":5208,"draft_gold":5208,"ready":true,"earned":673,"spent":0,"next_seq":9,"roster":["p1-1|w04|mid|230","p1-2|w04|mid|230","p1-3|w04|mid|230","p1-4|w02|mid|150","p1-5|w06|mid|195","p1-6|w06|mid|195","p1-7|w06|mid|195"],"hero":"h1-8|held_ringborke|296|mid|||260|false|","bookings":[],"new_bookings":[],"draft_roster":["p1-1|w04|mid|230|false","p1-2|w04|mid|230|false","p1-3|w04|mid|230|false","p1-4|w02|mid|150|false","p1-5|w06|mid|195|false","p1-6|w06|mid|195|false","p1-7|w06|mid|195|false"],"draft_hero":"h1-8|held_ringborke|296|mid|||260|false|","boss_lane":"top","undo":0},{"gold":893,"draft_gold":893,"ready":true,"earned":673,"spent":0,"next_seq":1,"roster":[],"hero":"","bookings":[],"new_bookings":[],"draft_roster":[],"draft_hero":"","boss_lane":"","undo":0},{"gold":893,"draft_gold":893,"ready":true,"earned":673,"spent":0,"next_seq":1,"roster":[],"hero":"","bookings":[],"new_bookings":[],"draft_roster":[],"draft_hero":"","boss_lane":"","undo":0},{"gold":893,"draft_gold":893,"ready":true,"earned":673,"spent":0,"next_seq":1,"roster":[],"hero":"","bookings":[],"new_bookings":[],"draft_roster":[],"draft_hero":"","boss_lane":"","undo":0},{"gold":893,"draft_gold":893,"ready":true,"earned":673,"spent":0,"next_seq":1,"roster":[],"hero":"","bookings":[],"new_bookings":[],"draft_roster":[],"draft_hero":"","boss_lane":"","undo":0}],"buildings":[7500.0,6000.0,7500.0,6000.0,7500.0,6000.0,9000.0,9000.0,12000.0,7500.0,6000.0,7500.0,6000.0,7500.0,6000.0,9000.0,9000.0,12000.0],"boss":{"next":10,"settled":6,"claim":"0|6|7|1|top"},"boss_log":["6|won|0||1","7|deployed|0|top|-1"],"announcements":["boss|0|1|top||940"],"settlement":{"round":6,"gains":[40,40,40,40,40,40],"income":90,"lost":[],"end_reason":"cleared","combat_time":40.79999999999982,"boss":"won","lane_kills":{"mid":8,"bot":8,"top":8},"xp":{"h1-8":296}},"combat":{"round":7,"steps":0,"elapsed":0.0,"finished":false,"end_reason":"","destroyed":[],"grotto":"none|-1|-1|true","grotto_boss":"","grotto_boss_hp":0.0,"events":0,"mobile":[24,15,0]},"units":[{"id":1,"kind":"tower","team":0,"lane":"top","zone":"lane","slot":-1,"uid":"","def":"blau_top_inner","alive":true,"hp":7500.0,"max_hp":7500.0,"shield":0.0,"x":-24.931251525878906,"y":4.5293378829956055,"facing":0.0,"progress":0.0,"target":-1,"hits":0,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":2,"kind":"tower","team":0,"lane":"top","zone":"lane","slot":-1,"uid":"","def":"blau_top_outer","alive":true,"hp":6000.0,"max_hp":6000.0,"shield":0.0,"x":-24.921451568603516,"y":-12.715348243713379,"facing":0.0,"progress":0.0,"target":-1,"hits":0,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":3,"kind":"tower","team":0,"lane":"mid","zone":"lane","slot":-1,"uid":"","def":"blau_mid_inner","alive":true,"hp":7500.0,"max_hp":7500.0,"shield":0.0,"x":-11.427590370178223,"y":17.012392044067383,"facing":0.0,"progress":0.0,"target":-1,"hits":0,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":4,"kind":"tower","team":0,"lane":"mid","zone":"lane","slot":-1,"uid":"","def":"blau_mid_outer","alive":true,"hp":6000.0,"max_hp":6000.0,"shield":0.0,"x":-3.8433847427368164,"y":8.990991592407227,"facing":0.0,"progress":0.0,"target":-1,"hits":0,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":5,"kind":"tower","team":0,"lane":"bot","zone":"lane","slot":-1,"uid":"","def":"blau_bot_inner","alive":true,"hp":7500.0,"max_hp":7500.0,"shield":0.0,"x":-4.349228858947754,"y":31.034507751464844,"facing":0.0,"progress":0.0,"target":-1,"hits":0,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":6,"kind":"tower","team":0,"lane":"bot","zone":"lane","slot":-1,"uid":"","def":"blau_bot_outer","alive":true,"hp":6000.0,"max_hp":6000.0,"shield":0.0,"x":11.117134094238281,"y":28.989334106445313,"facing":0.0,"progress":0.0,"target":-1,"hits":0,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":7,"kind":"tower","team":0,"lane":"base","zone":"lane","slot":-1,"uid":"","def":"blau_base_1","alive":true,"hp":9000.0,"max_hp":9000.0,"shield":0.0,"x":-29.476999282836914,"y":24.023000717163086,"facing":0.0,"progress":0.0,"target":-1,"hits":0,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":8,"kind":"tower","team":0,"lane":"base","zone":"lane","slot":-1,"uid":"","def":"blau_base_2","alive":true,"hp":9000.0,"max_hp":9000.0,"shield":0.0,"x":-24.023000717163086,"y":29.476999282836914,"facing":0.0,"progress":0.0,"target":-1,"hits":0,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":9,"kind":"core","team":0,"lane":"base","zone":"lane","slot":-1,"uid":"","def":"blau_ancient","alive":true,"hp":12000.0,"max_hp":12000.0,"shield":0.0,"x":-30.0,"y":30.0,"facing":0.0,"progress":0.0,"target":-1,"hits":0,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":10,"kind":"tower","team":1,"lane":"top","zone":"lane","slot":-1,"uid":"","def":"rot_top_inner","alive":true,"hp":7500.0,"max_hp":7500.0,"shield":0.0,"x":4.5293378829956055,"y":-24.931251525878906,"facing":0.0,"progress":0.0,"target":-1,"hits":0,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":11,"kind":"tower","team":1,"lane":"top","zone":"lane","slot":-1,"uid":"","def":"rot_top_outer","alive":true,"hp":6000.0,"max_hp":6000.0,"shield":0.0,"x":-12.715348243713379,"y":-24.921451568603516,"facing":0.0,"progress":0.0,"target":-1,"hits":0,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":12,"kind":"tower","team":1,"lane":"mid","zone":"lane","slot":-1,"uid":"","def":"rot_mid_inner","alive":true,"hp":7500.0,"max_hp":7500.0,"shield":0.0,"x":17.012392044067383,"y":-11.427590370178223,"facing":0.0,"progress":0.0,"target":-1,"hits":0,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":13,"kind":"tower","team":1,"lane":"mid","zone":"lane","slot":-1,"uid":"","def":"rot_mid_outer","alive":true,"hp":6000.0,"max_hp":6000.0,"shield":0.0,"x":8.990991592407227,"y":-3.8433847427368164,"facing":0.0,"progress":0.0,"target":-1,"hits":0,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":14,"kind":"tower","team":1,"lane":"bot","zone":"lane","slot":-1,"uid":"","def":"rot_bot_inner","alive":true,"hp":7500.0,"max_hp":7500.0,"shield":0.0,"x":31.034507751464844,"y":-4.349228858947754,"facing":0.0,"progress":0.0,"target":-1,"hits":0,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":15,"kind":"tower","team":1,"lane":"bot","zone":"lane","slot":-1,"uid":"","def":"rot_bot_outer","alive":true,"hp":6000.0,"max_hp":6000.0,"shield":0.0,"x":28.989334106445313,"y":11.117134094238281,"facing":0.0,"progress":0.0,"target":-1,"hits":0,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":16,"kind":"tower","team":1,"lane":"base","zone":"lane","slot":-1,"uid":"","def":"rot_base_1","alive":true,"hp":9000.0,"max_hp":9000.0,"shield":0.0,"x":24.023000717163086,"y":-29.476999282836914,"facing":0.0,"progress":0.0,"target":-1,"hits":0,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":17,"kind":"tower","team":1,"lane":"base","zone":"lane","slot":-1,"uid":"","def":"rot_base_2","alive":true,"hp":9000.0,"max_hp":9000.0,"shield":0.0,"x":29.476999282836914,"y":-24.023000717163086,"facing":0.0,"progress":0.0,"target":-1,"hits":0,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":18,"kind":"core","team":1,"lane":"base","zone":"lane","slot":-1,"uid":"","def":"rot_ancient","alive":true,"hp":12000.0,"max_hp":12000.0,"shield":0.0,"x":30.0,"y":-30.0,"facing":0.0,"progress":0.0,"target":-1,"hits":0,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":19,"kind":"monster","team":0,"lane":"top","zone":"lane","slot":-1,"uid":"","def":"e01","alive":true,"hp":154.26000000000002,"max_hp":154.26000000000002,"shield":0.0,"x":-28.243892669677734,"y":10.502157211303711,"facing":-2.864119239296395,"progress":11.0,"target":-1,"hits":0,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":20,"kind":"monster","team":0,"lane":"top","zone":"lane","slot":-1,"uid":"","def":"e02","alive":true,"hp":411.36000000000007,"max_hp":411.36000000000007,"shield":0.0,"x":-26.993616104125977,"y":10.146052360534668,"facing":-2.864119239296395,"progress":11.0,"target":-1,"hits":0,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":21,"kind":"monster","team":0,"lane":"top","zone":"lane","slot":-1,"uid":"","def":"e03","alive":true,"hp":257.1,"max_hp":257.1,"shield":0.0,"x":-25.74333953857422,"y":9.789947509765625,"facing":-2.864119239296395,"progress":11.0,"target":-1,"hits":0,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":22,"kind":"monster","team":0,"lane":"top","zone":"lane","slot":-1,"uid":"","def":"e04","alive":true,"hp":222.82000000000002,"max_hp":222.82000000000002,"shield":0.0,"x":-27.921968460083008,"y":11.702203750610352,"facing":-2.9843745641096318,"progress":9.6,"target":-1,"hits":0,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":23,"kind":"monster","team":0,"lane":"top","zone":"lane","slot":-1,"uid":"","def":"e03","alive":true,"hp":257.1,"max_hp":257.1,"shield":0.0,"x":-26.638002395629883,"y":11.498661041259766,"facing":-2.9843745641096318,"progress":9.6,"target":-1,"hits":0,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":24,"kind":"monster","team":0,"lane":"mid","zone":"lane","slot":-1,"uid":"","def":"e01","alive":true,"hp":154.26000000000002,"max_hp":154.26000000000002,"shield":0.0,"x":-14.408708572387695,"y":13.32747745513916,"facing":2.3870002372622334,"progress":11.0,"target":-1,"hits":0,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":25,"kind":"monster","team":0,"lane":"mid","zone":"lane","slot":-1,"uid":"","def":"e02","alive":true,"hp":411.36000000000007,"max_hp":411.36000000000007,"shield":0.0,"x":-13.461592674255371,"y":14.21796703338623,"facing":2.3870002372622334,"progress":11.0,"target":-1,"hits":0,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":26,"kind":"monster","team":0,"lane":"mid","zone":"lane","slot":-1,"uid":"","def":"e03","alive":true,"hp":257.1,"max_hp":257.1,"shield":0.0,"x":-12.514476776123047,"y":15.1084566116333,"facing":2.3870002372622334,"progress":11.0,"target":-1,"hits":0,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":27,"kind":"monster","team":0,"lane":"mid","zone":"lane","slot":-1,"uid":"","def":"e04","alive":true,"hp":222.82000000000002,"max_hp":222.82000000000002,"shield":0.0,"x":-15.366670608520508,"y":14.327392578125,"facing":2.3752783515087157,"progress":9.6,"target":-1,"hits":0,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":28,"kind":"monster","team":0,"lane":"mid","zone":"lane","slot":-1,"uid":"","def":"e03","alive":true,"hp":257.1,"max_hp":257.1,"shield":0.0,"x":-14.430057525634766,"y":15.228922843933105,"facing":2.3752783515087157,"progress":9.6,"target":-1,"hits":0,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":29,"kind":"monster","team":0,"lane":"bot","zone":"lane","slot":-1,"uid":"","def":"e01","alive":true,"hp":154.26000000000002,"max_hp":154.26000000000002,"shield":0.0,"x":-9.842267036437988,"y":25.94097137451172,"facing":1.4313591016628469,"progress":11.0,"target":-1,"hits":0,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":30,"kind":"monster","team":0,"lane":"bot","zone":"lane","slot":-1,"uid":"","def":"e02","alive":true,"hp":411.36000000000007,"max_hp":411.36000000000007,"shield":0.0,"x":-10.022948265075684,"y":27.22835350036621,"facing":1.4313591016628469,"progress":11.0,"target":-1,"hits":0,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":31,"kind":"monster","team":0,"lane":"bot","zone":"lane","slot":-1,"uid":"","def":"e03","alive":true,"hp":257.1,"max_hp":257.1,"shield":0.0,"x":-10.203629493713379,"y":28.515735626220703,"facing":1.4313591016628469,"progress":11.0,"target":-1,"hits":0,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":32,"kind":"monster","team":0,"lane":"bot","zone":"lane","slot":-1,"uid":"","def":"e04","alive":true,"hp":222.82000000000002,"max_hp":222.82000000000002,"shield":0.0,"x":-11.322441101074219,"y":25.77979278564453,"facing":1.5004101357551378,"progress":9.6,"target":-1,"hits":0,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":33,"kind":"monster","team":0,"lane":"bot","zone":"lane","slot":-1,"uid":"","def":"e03","alive":true,"hp":257.1,"max_hp":257.1,"shield":0.0,"x":-11.413867950439453,"y":27.076574325561523,"facing":1.5004101357551378,"progress":9.6,"target":-1,"hits":0,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":34,"kind":"monster","team":1,"lane":"top","zone":"lane","slot":-1,"uid":"","def":"e01","alive":true,"hp":154.26000000000002,"max_hp":154.26000000000002,"shield":0.0,"x":10.502157211303711,"y":-28.243892669677734,"facing":-1.8482697410882951,"progress":11.0,"target":-1,"hits":0,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":35,"kind":"monster","team":1,"lane":"top","zone":"lane","slot":-1,"uid":"","def":"e02","alive":true,"hp":411.36000000000007,"max_hp":411.36000000000007,"shield":0.0,"x":10.146052360534668,"y":-26.993616104125977,"facing":-1.8482697410882951,"progress":11.0,"target":-1,"hits":0,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":36,"kind":"monster","team":1,"lane":"top","zone":"lane","slot":-1,"uid":"","def":"e03","alive":true,"hp":257.1,"max_hp":257.1,"shield":0.0,"x":9.789947509765625,"y":-25.74333953857422,"facing":-1.8482697410882951,"progress":11.0,"target":-1,"hits":0,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":37,"kind":"monster","team":1,"lane":"top","zone":"lane","slot":-1,"uid":"","def":"e04","alive":true,"hp":222.82000000000002,"max_hp":222.82000000000002,"shield":0.0,"x":11.702203750610352,"y":-27.921968460083008,"facing":-1.7280144162750581,"progress":9.6,"target":-1,"hits":0,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":38,"kind":"monster","team":1,"lane":"top","zone":"lane","slot":-1,"uid":"","def":"e03","alive":true,"hp":257.1,"max_hp":257.1,"shield":0.0,"x":11.498661041259766,"y":-26.638002395629883,"facing":-1.7280144162750581,"progress":9.6,"target":-1,"hits":0,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":39,"kind":"monster","team":1,"lane":"mid","zone":"lane","slot":-1,"uid":"","def":"e01","alive":true,"hp":154.26000000000002,"max_hp":154.26000000000002,"shield":0.0,"x":13.32747745513916,"y":-14.408708572387695,"facing":-0.816203910467337,"progress":11.0,"target":-1,"hits":0,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":40,"kind":"monster","team":1,"lane":"mid","zone":"lane","slot":-1,"uid":"","def":"e02","alive":true,"hp":411.36000000000007,"max_hp":411.36000000000007,"shield":0.0,"x":14.21796703338623,"y":-13.461592674255371,"facing":-0.816203910467337,"progress":11.0,"target":-1,"hits":0,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":41,"kind":"monster","team":1,"lane":"mid","zone":"lane","slot":-1,"uid":"","def":"e03","alive":true,"hp":257.1,"max_hp":257.1,"shield":0.0,"x":15.1084566116333,"y":-12.514476776123047,"facing":-0.816203910467337,"progress":11.0,"target":-1,"hits":0,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":42,"kind":"monster","team":1,"lane":"mid","zone":"lane","slot":-1,"uid":"","def":"e04","alive":true,"hp":222.82000000000002,"max_hp":222.82000000000002,"shield":0.0,"x":14.327392578125,"y":-15.366670608520508,"facing":-0.804482024713819,"progress":9.6,"target":-1,"hits":0,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":43,"kind":"monster","team":1,"lane":"mid","zone":"lane","slot":-1,"uid":"","def":"e03","alive":true,"hp":257.1,"max_hp":257.1,"shield":0.0,"x":15.228922843933105,"y":-14.430057525634766,"facing":-0.804482024713819,"progress":9.6,"target":-1,"hits":0,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":44,"kind":"monster","team":1,"lane":"bot","zone":"lane","slot":-1,"uid":"","def":"e01","alive":true,"hp":154.26000000000002,"max_hp":154.26000000000002,"shield":0.0,"x":25.94097137451172,"y":-9.842267036437988,"facing":0.13943722513204979,"progress":11.0,"target":-1,"hits":0,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":45,"kind":"monster","team":1,"lane":"bot","zone":"lane","slot":-1,"uid":"","def":"e02","alive":true,"hp":411.36000000000007,"max_hp":411.36000000000007,"shield":0.0,"x":27.22835350036621,"y":-10.022948265075684,"facing":0.13943722513204979,"progress":11.0,"target":-1,"hits":0,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":46,"kind":"monster","team":1,"lane":"bot","zone":"lane","slot":-1,"uid":"","def":"e03","alive":true,"hp":257.1,"max_hp":257.1,"shield":0.0,"x":28.515735626220703,"y":-10.203629493713379,"facing":0.13943722513204979,"progress":11.0,"target":-1,"hits":0,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":47,"kind":"monster","team":1,"lane":"bot","zone":"lane","slot":-1,"uid":"","def":"e04","alive":true,"hp":222.82000000000002,"max_hp":222.82000000000002,"shield":0.0,"x":25.77979278564453,"y":-11.322441101074219,"facing":0.07038619103975874,"progress":9.6,"target":-1,"hits":0,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":48,"kind":"monster","team":1,"lane":"bot","zone":"lane","slot":-1,"uid":"","def":"e03","alive":true,"hp":257.1,"max_hp":257.1,"shield":0.0,"x":27.076574325561523,"y":-11.413867950439453,"facing":0.07038619103975874,"progress":9.6,"target":-1,"hits":0,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":49,"kind":"boss","team":0,"lane":"top","zone":"lane","slot":1,"uid":"boss-7","def":"e10","alive":true,"hp":11655.2,"max_hp":11655.2,"shield":0.0,"x":-27.853185653686523,"y":7.272462844848633,"facing":-2.8943554742250743,"progress":14.0,"target":-1,"hits":0,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":50,"kind":"troop","team":0,"lane":"mid","zone":"lane","slot":1,"uid":"p1-1","def":"w04","alive":true,"hp":1560.0,"max_hp":1560.0,"shield":0.0,"x":-17.386140823364258,"y":15.645247459411621,"facing":2.347786769279204,"progress":7.2,"target":-1,"hits":0,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":51,"kind":"troop","team":0,"lane":"mid","zone":"lane","slot":1,"uid":"p1-2","def":"w04","alive":true,"hp":1560.0,"max_hp":1560.0,"shield":0.0,"x":-16.544776916503906,"y":16.500879287719727,"facing":2.347786769279204,"progress":7.2,"target":-1,"hits":0,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":52,"kind":"troop","team":0,"lane":"mid","zone":"lane","slot":1,"uid":"p1-3","def":"w04","alive":true,"hp":1560.0,"max_hp":1560.0,"shield":0.0,"x":-15.703412055969238,"y":17.35651206970215,"facing":2.347786769279204,"progress":7.2,"target":-1,"hits":0,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":53,"kind":"hero","team":0,"lane":"mid","zone":"lane","slot":1,"uid":"h1-8","def":"w04","alive":true,"hp":2596.0,"max_hp":2596.0,"shield":0.0,"x":-14.862048149108887,"y":18.21214485168457,"facing":2.347786769279204,"progress":7.2,"target":-1,"hits":0,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":54,"kind":"troop","team":0,"lane":"mid","zone":"lane","slot":1,"uid":"p1-4","def":"w02","alive":true,"hp":800.0,"max_hp":800.0,"shield":0.0,"x":-18.432058334350586,"y":16.60871696472168,"facing":2.3046223302823,"progress":5.7,"target":-1,"hits":0,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":55,"kind":"troop","team":0,"lane":"mid","zone":"lane","slot":1,"uid":"p1-5","def":"w06","alive":true,"hp":630.0,"max_hp":630.0,"shield":0.0,"x":-17.628398895263672,"y":17.499858856201172,"facing":2.3046223302823,"progress":5.7,"target":-1,"hits":0,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":56,"kind":"troop","team":0,"lane":"mid","zone":"lane","slot":1,"uid":"p1-6","def":"w06","alive":true,"hp":630.0,"max_hp":630.0,"shield":0.0,"x":-16.82474136352539,"y":18.39099884033203,"facing":2.3046223302823,"progress":5.7,"target":-1,"hits":0,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":57,"kind":"troop","team":0,"lane":"mid","zone":"lane","slot":1,"uid":"p1-7","def":"w06","alive":true,"hp":630.0,"max_hp":630.0,"shield":0.0,"x":-16.021081924438477,"y":19.282140731811523,"facing":2.3046223302823,"progress":5.7,"target":-1,"hits":0,"reached":false,"dormant":false,"effects":[],"dots":[]}]},{"label":"marching","phase":1,"round":7,"winner":-2,"end_note":"","players":[{"gold":893,"draft_gold":893,"ready":true,"earned":673,"spent":0,"next_seq":1,"roster":[],"hero":"","bookings":[],"new_bookings":[],"draft_roster":[],"draft_hero":"","boss_lane":"","undo":0},{"gold":5208,"draft_gold":5208,"ready":true,"earned":673,"spent":0,"next_seq":9,"roster":["p1-1|w04|mid|230","p1-2|w04|mid|230","p1-3|w04|mid|230","p1-4|w02|mid|150","p1-5|w06|mid|195","p1-6|w06|mid|195","p1-7|w06|mid|195"],"hero":"h1-8|held_ringborke|296|mid|||260|false|","bookings":[],"new_bookings":[],"draft_roster":["p1-1|w04|mid|230|false","p1-2|w04|mid|230|false","p1-3|w04|mid|230|false","p1-4|w02|mid|150|false","p1-5|w06|mid|195|false","p1-6|w06|mid|195|false","p1-7|w06|mid|195|false"],"draft_hero":"h1-8|held_ringborke|296|mid|||260|false|","boss_lane":"top","undo":0},{"gold":893,"draft_gold":893,"ready":true,"earned":673,"spent":0,"next_seq":1,"roster":[],"hero":"","bookings":[],"new_bookings":[],"draft_roster":[],"draft_hero":"","boss_lane":"","undo":0},{"gold":893,"draft_gold":893,"ready":true,"earned":673,"spent":0,"next_seq":1,"roster":[],"hero":"","bookings":[],"new_bookings":[],"draft_roster":[],"draft_hero":"","boss_lane":"","undo":0},{"gold":893,"draft_gold":893,"ready":true,"earned":673,"spent":0,"next_seq":1,"roster":[],"hero":"","bookings":[],"new_bookings":[],"draft_roster":[],"draft_hero":"","boss_lane":"","undo":0},{"gold":893,"draft_gold":893,"ready":true,"earned":673,"spent":0,"next_seq":1,"roster":[],"hero":"","bookings":[],"new_bookings":[],"draft_roster":[],"draft_hero":"","boss_lane":"","undo":0}],"buildings":[7500.0,6000.0,7500.0,6000.0,7500.0,6000.0,9000.0,9000.0,12000.0,7500.0,6000.0,7500.0,6000.0,7500.0,6000.0,9000.0,9000.0,12000.0],"boss":{"next":10,"settled":6,"claim":"0|6|7|1|top"},"boss_log":["6|won|0||1","7|deployed|0|top|-1"],"announcements":["boss|0|1|top||940"],"settlement":{"round":6,"gains":[40,40,40,40,40,40],"income":90,"lost":[],"end_reason":"cleared","combat_time":40.79999999999982,"boss":"won","lane_kills":{"mid":8,"bot":8,"top":8},"xp":{"h1-8":296}},"combat":{"round":7,"steps":200,"elapsed":10.000000000000007,"finished":false,"end_reason":"","destroyed":[],"grotto":"none|-1|-1|true","grotto_boss":"","grotto_boss_hp":0.0,"events":4,"mobile":[23,12,0]},"units":[{"id":1,"kind":"tower","team":0,"lane":"top","zone":"lane","slot":-1,"uid":"","def":"blau_top_inner","alive":true,"hp":7500.0,"max_hp":7500.0,"shield":0.0,"x":-24.931251525878906,"y":4.5293378829956055,"facing":0.0,"progress":0.0,"target":-1,"hits":0,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":2,"kind":"tower","team":0,"lane":"top","zone":"lane","slot":-1,"uid":"","def":"blau_top_outer","alive":true,"hp":6000.0,"max_hp":6000.0,"shield":0.0,"x":-24.921451568603516,"y":-12.715348243713379,"facing":0.0,"progress":0.0,"target":-1,"hits":0,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":3,"kind":"tower","team":0,"lane":"mid","zone":"lane","slot":-1,"uid":"","def":"blau_mid_inner","alive":true,"hp":7500.0,"max_hp":7500.0,"shield":0.0,"x":-11.427590370178223,"y":17.012392044067383,"facing":0.0,"progress":0.0,"target":-1,"hits":0,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":4,"kind":"tower","team":0,"lane":"mid","zone":"lane","slot":-1,"uid":"","def":"blau_mid_outer","alive":true,"hp":6000.0,"max_hp":6000.0,"shield":0.0,"x":-3.8433847427368164,"y":8.990991592407227,"facing":0.0,"progress":0.0,"target":-1,"hits":0,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":5,"kind":"tower","team":0,"lane":"bot","zone":"lane","slot":-1,"uid":"","def":"blau_bot_inner","alive":true,"hp":7500.0,"max_hp":7500.0,"shield":0.0,"x":-4.349228858947754,"y":31.034507751464844,"facing":0.0,"progress":0.0,"target":-1,"hits":0,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":6,"kind":"tower","team":0,"lane":"bot","zone":"lane","slot":-1,"uid":"","def":"blau_bot_outer","alive":true,"hp":6000.0,"max_hp":6000.0,"shield":0.0,"x":11.117134094238281,"y":28.989334106445313,"facing":0.0,"progress":0.0,"target":-1,"hits":0,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":7,"kind":"tower","team":0,"lane":"base","zone":"lane","slot":-1,"uid":"","def":"blau_base_1","alive":true,"hp":9000.0,"max_hp":9000.0,"shield":0.0,"x":-29.476999282836914,"y":24.023000717163086,"facing":0.0,"progress":0.0,"target":-1,"hits":0,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":8,"kind":"tower","team":0,"lane":"base","zone":"lane","slot":-1,"uid":"","def":"blau_base_2","alive":true,"hp":9000.0,"max_hp":9000.0,"shield":0.0,"x":-24.023000717163086,"y":29.476999282836914,"facing":0.0,"progress":0.0,"target":-1,"hits":0,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":9,"kind":"core","team":0,"lane":"base","zone":"lane","slot":-1,"uid":"","def":"blau_ancient","alive":true,"hp":12000.0,"max_hp":12000.0,"shield":0.0,"x":-30.0,"y":30.0,"facing":0.0,"progress":0.0,"target":-1,"hits":0,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":10,"kind":"tower","team":1,"lane":"top","zone":"lane","slot":-1,"uid":"","def":"rot_top_inner","alive":true,"hp":7500.0,"max_hp":7500.0,"shield":0.0,"x":4.5293378829956055,"y":-24.931251525878906,"facing":0.0,"progress":0.0,"target":-1,"hits":0,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":11,"kind":"tower","team":1,"lane":"top","zone":"lane","slot":-1,"uid":"","def":"rot_top_outer","alive":true,"hp":6000.0,"max_hp":6000.0,"shield":0.0,"x":-12.715348243713379,"y":-24.921451568603516,"facing":0.0,"progress":0.0,"target":-1,"hits":0,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":12,"kind":"tower","team":1,"lane":"mid","zone":"lane","slot":-1,"uid":"","def":"rot_mid_inner","alive":true,"hp":7500.0,"max_hp":7500.0,"shield":0.0,"x":17.012392044067383,"y":-11.427590370178223,"facing":0.0,"progress":0.0,"target":-1,"hits":0,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":13,"kind":"tower","team":1,"lane":"mid","zone":"lane","slot":-1,"uid":"","def":"rot_mid_outer","alive":true,"hp":6000.0,"max_hp":6000.0,"shield":0.0,"x":8.990991592407227,"y":-3.8433847427368164,"facing":0.0,"progress":0.0,"target":53,"hits":1,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":14,"kind":"tower","team":1,"lane":"bot","zone":"lane","slot":-1,"uid":"","def":"rot_bot_inner","alive":true,"hp":7500.0,"max_hp":7500.0,"shield":0.0,"x":31.034507751464844,"y":-4.349228858947754,"facing":0.0,"progress":0.0,"target":-1,"hits":0,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":15,"kind":"tower","team":1,"lane":"bot","zone":"lane","slot":-1,"uid":"","def":"rot_bot_outer","alive":true,"hp":6000.0,"max_hp":6000.0,"shield":0.0,"x":28.989334106445313,"y":11.117134094238281,"facing":0.0,"progress":0.0,"target":-1,"hits":0,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":16,"kind":"tower","team":1,"lane":"base","zone":"lane","slot":-1,"uid":"","def":"rot_base_1","alive":true,"hp":9000.0,"max_hp":9000.0,"shield":0.0,"x":24.023000717163086,"y":-29.476999282836914,"facing":0.0,"progress":0.0,"target":-1,"hits":0,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":17,"kind":"tower","team":1,"lane":"base","zone":"lane","slot":-1,"uid":"","def":"rot_base_2","alive":true,"hp":9000.0,"max_hp":9000.0,"shield":0.0,"x":29.476999282836914,"y":-24.023000717163086,"facing":0.0,"progress":0.0,"target":-1,"hits":0,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":18,"kind":"core","team":1,"lane":"base","zone":"lane","slot":-1,"uid":"","def":"rot_ancient","alive":true,"hp":12000.0,"max_hp":12000.0,"shield":0.0,"x":30.0,"y":-30.0,"facing":0.0,"progress":0.0,"target":-1,"hits":0,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":19,"kind":"monster","team":0,"lane":"top","zone":"lane","slot":-1,"uid":"","def":"e01","alive":true,"hp":113.57760000000003,"max_hp":154.26000000000002,"shield":0.0,"x":-26.336877822875977,"y":-25.78684425354004,"facing":2.356194490192345,"progress":47.90360550768908,"target":34,"hits":2,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":20,"kind":"monster","team":0,"lane":"top","zone":"lane","slot":-1,"uid":"","def":"e02","alive":true,"hp":411.36000000000007,"max_hp":411.36000000000007,"shield":0.0,"x":-28.341217041015625,"y":-20.92352867126465,"facing":2.699363634351024,"progress":42.98637802400238,"target":34,"hits":0,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":21,"kind":"monster","team":0,"lane":"top","zone":"lane","slot":-1,"uid":"","def":"e03","alive":true,"hp":257.1,"max_hp":257.1,"shield":0.0,"x":-26.601463317871094,"y":-22.94614028930664,"facing":2.905818788798706,"progress":45.840293725802226,"target":34,"hits":0,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":22,"kind":"monster","team":0,"lane":"top","zone":"lane","slot":-1,"uid":"","def":"e04","alive":true,"hp":222.82000000000002,"max_hp":222.82000000000002,"shield":0.0,"x":-29.262495040893555,"y":-21.470657348632813,"facing":2.521403754389891,"progress":43.245321393013,"target":34,"hits":1,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":23,"kind":"monster","team":0,"lane":"top","zone":"lane","slot":-1,"uid":"","def":"e03","alive":true,"hp":257.1,"max_hp":257.1,"shield":0.0,"x":-27.546323776245117,"y":-22.54451560974121,"facing":2.707198012883433,"progress":44.83561688586266,"target":34,"hits":0,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":24,"kind":"monster","team":0,"lane":"mid","zone":"lane","slot":-1,"uid":"","def":"e01","alive":false,"hp":0.0,"max_hp":154.26000000000002,"shield":0.0,"x":-0.6020870804786682,"y":-1.812448501586914,"facing":2.3382455166629583,"progress":31.419926076234496,"target":-1,"hits":3,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":25,"kind":"monster","team":0,"lane":"mid","zone":"lane","slot":-1,"uid":"","def":"e02","alive":true,"hp":332.9432000000001,"max_hp":411.36000000000007,"shield":0.0,"x":1.6447325944900513,"y":-1.8410542011260986,"facing":2.150857640248518,"progress":33.041067413705164,"target":41,"hits":3,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":26,"kind":"monster","team":0,"lane":"mid","zone":"lane","slot":-1,"uid":"","def":"e03","alive":true,"hp":257.1,"max_hp":257.1,"shield":0.0,"x":-0.1895594447851181,"y":0.9672461748123169,"facing":0.6841567693149535,"progress":29.768859908901682,"target":41,"hits":4,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":27,"kind":"monster","team":0,"lane":"mid","zone":"lane","slot":-1,"uid":"","def":"e04","alive":true,"hp":222.82000000000002,"max_hp":222.82000000000002,"shield":0.0,"x":-3.082301139831543,"y":1.2166125774383545,"facing":-2.5973830390333226,"progress":27.572365520450376,"target":41,"hits":4,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":28,"kind":"monster","team":0,"lane":"mid","zone":"lane","slot":-1,"uid":"","def":"e03","alive":true,"hp":257.1,"max_hp":257.1,"shield":0.0,"x":-0.8833057284355164,"y":0.11660989373922348,"facing":-2.4574212905992012,"progress":29.878129928586194,"target":41,"hits":3,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":29,"kind":"monster","team":0,"lane":"bot","zone":"lane","slot":-1,"uid":"","def":"e01","alive":true,"hp":95.88960000000002,"max_hp":154.26000000000002,"shield":0.0,"x":23.674602508544922,"y":24.313919067382813,"facing":2.356194490192345,"progress":48.0619000491272,"target":44,"hits":2,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":30,"kind":"monster","team":0,"lane":"bot","zone":"lane","slot":-1,"uid":"","def":"e02","alive":true,"hp":411.36000000000007,"max_hp":411.36000000000007,"shield":0.0,"x":20.59243392944336,"y":25.554128646850586,"facing":2.025200166918588,"progress":42.08134894166333,"target":44,"hits":0,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":31,"kind":"monster","team":0,"lane":"bot","zone":"lane","slot":-1,"uid":"","def":"e03","alive":true,"hp":257.1,"max_hp":257.1,"shield":0.0,"x":21.768817901611328,"y":26.064674377441406,"facing":0.5891694641615062,"progress":45.23375970158394,"target":44,"hits":0,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":32,"kind":"monster","team":0,"lane":"bot","zone":"lane","slot":-1,"uid":"","def":"e04","alive":true,"hp":222.82000000000002,"max_hp":222.82000000000002,"shield":0.0,"x":18.534770965576172,"y":25.21143341064453,"facing":1.830713247620907,"progress":40.326850408195746,"target":44,"hits":2,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":33,"kind":"monster","team":0,"lane":"bot","zone":"lane","slot":-1,"uid":"","def":"e03","alive":true,"hp":257.1,"max_hp":257.1,"shield":0.0,"x":21.20718765258789,"y":25.175628662109375,"facing":2.3157620364457894,"progress":42.540604860876265,"target":44,"hits":0,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":34,"kind":"monster","team":1,"lane":"top","zone":"lane","slot":-1,"uid":"","def":"e01","alive":true,"hp":113.57760000000003,"max_hp":154.26000000000002,"shield":0.0,"x":-25.78684425354004,"y":-26.336877822875977,"facing":-0.7853981633974483,"progress":47.90360550768908,"target":19,"hits":2,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":35,"kind":"monster","team":1,"lane":"top","zone":"lane","slot":-1,"uid":"","def":"e02","alive":true,"hp":411.36000000000007,"max_hp":411.36000000000007,"shield":0.0,"x":-20.92352867126465,"y":-28.341217041015625,"facing":-1.1285673075561276,"progress":42.98637802400238,"target":19,"hits":0,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":36,"kind":"monster","team":1,"lane":"top","zone":"lane","slot":-1,"uid":"","def":"e03","alive":true,"hp":257.1,"max_hp":257.1,"shield":0.0,"x":-22.94614028930664,"y":-26.601463317871094,"facing":-1.3350224620038094,"progress":45.840293725802226,"target":19,"hits":0,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":37,"kind":"monster","team":1,"lane":"top","zone":"lane","slot":-1,"uid":"","def":"e04","alive":true,"hp":222.82000000000002,"max_hp":222.82000000000002,"shield":0.0,"x":-21.470657348632813,"y":-29.262495040893555,"facing":-0.9506074275949943,"progress":43.245321393013,"target":19,"hits":1,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":38,"kind":"monster","team":1,"lane":"top","zone":"lane","slot":-1,"uid":"","def":"e03","alive":true,"hp":257.1,"max_hp":257.1,"shield":0.0,"x":-22.54451560974121,"y":-27.546323776245117,"facing":-1.1364016860885364,"progress":44.83561688586266,"target":19,"hits":0,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":39,"kind":"monster","team":1,"lane":"mid","zone":"lane","slot":-1,"uid":"","def":"e01","alive":false,"hp":0.0,"max_hp":154.26000000000002,"shield":0.0,"x":-0.9244003891944885,"y":-1.0517082214355469,"facing":-1.2380182992333388,"progress":30.50312783741925,"target":-1,"hits":3,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":40,"kind":"monster","team":1,"lane":"mid","zone":"lane","slot":-1,"uid":"","def":"e02","alive":false,"hp":0.0,"max_hp":411.36000000000007,"shield":0.0,"x":0.11324281990528107,"y":-1.410296082496643,"facing":1.9035672110802433,"progress":29.691407034272377,"target":-1,"hits":2,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":41,"kind":"monster","team":1,"lane":"mid","zone":"lane","slot":-1,"uid":"","def":"e03","alive":false,"hp":0.0,"max_hp":257.1,"shield":0.0,"x":2.1586954593658447,"y":-1.590934157371521,"facing":0.4251312162350669,"progress":27.919715015764734,"target":-1,"hits":4,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":42,"kind":"monster","team":1,"lane":"mid","zone":"lane","slot":-1,"uid":"","def":"e04","alive":true,"hp":222.82000000000002,"max_hp":222.82000000000002,"shield":0.0,"x":3.1164302825927734,"y":-4.75901460647583,"facing":-0.8004263311991201,"progress":25.05404917733547,"target":25,"hits":5,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":43,"kind":"monster","team":1,"lane":"mid","zone":"lane","slot":-1,"uid":"","def":"e03","alive":true,"hp":186.85000000000002,"max_hp":257.1,"shield":0.0,"x":1.7050559520721436,"y":-2.5930368900299072,"facing":-2.7164614373547264,"progress":27.58184173376899,"target":25,"hits":4,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":44,"kind":"monster","team":1,"lane":"bot","zone":"lane","slot":-1,"uid":"","def":"e01","alive":true,"hp":95.88960000000002,"max_hp":154.26000000000002,"shield":0.0,"x":24.313919067382813,"y":23.674602508544922,"facing":-0.7853981633974483,"progress":48.0619000491272,"target":29,"hits":2,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":45,"kind":"monster","team":1,"lane":"bot","zone":"lane","slot":-1,"uid":"","def":"e02","alive":true,"hp":411.36000000000007,"max_hp":411.36000000000007,"shield":0.0,"x":25.554128646850586,"y":20.59243392944336,"facing":-0.4544038401236915,"progress":42.08134894166333,"target":29,"hits":0,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":46,"kind":"monster","team":1,"lane":"bot","zone":"lane","slot":-1,"uid":"","def":"e03","alive":true,"hp":257.1,"max_hp":257.1,"shield":0.0,"x":26.064674377441406,"y":21.768817901611328,"facing":0.9816268626333905,"progress":45.23375970158394,"target":29,"hits":0,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":47,"kind":"monster","team":1,"lane":"bot","zone":"lane","slot":-1,"uid":"","def":"e04","alive":true,"hp":222.82000000000002,"max_hp":222.82000000000002,"shield":0.0,"x":25.21143341064453,"y":18.534770965576172,"facing":-0.25991692082601037,"progress":40.326850408195746,"target":29,"hits":2,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":48,"kind":"monster","team":1,"lane":"bot","zone":"lane","slot":-1,"uid":"","def":"e03","alive":true,"hp":257.1,"max_hp":257.1,"shield":0.0,"x":25.175628662109375,"y":21.20718765258789,"facing":-0.7449657096508927,"progress":42.540604860876265,"target":29,"hits":0,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":49,"kind":"boss","team":0,"lane":"top","zone":"lane","slot":1,"uid":"boss-7","def":"e10","alive":true,"hp":11655.2,"max_hp":11655.2,"shield":0.0,"x":-28.861160278320313,"y":-17.593067169189453,"facing":-3.1151994397018226,"progress":39.60000000000002,"target":-1,"hits":0,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":50,"kind":"troop","team":0,"lane":"mid","zone":"lane","slot":1,"uid":"p1-1","def":"w04","alive":true,"hp":1560.0,"max_hp":1560.0,"shield":0.0,"x":0.4008648097515106,"y":-3.1159515380859375,"facing":-3.0363860338998183,"progress":33.02062391400798,"target":43,"hits":3,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":51,"kind":"troop","team":0,"lane":"mid","zone":"lane","slot":1,"uid":"p1-2","def":"w04","alive":true,"hp":1560.0,"max_hp":1560.0,"shield":0.0,"x":0.7836339473724365,"y":-1.2852133512496948,"facing":-1.4806436172172062,"progress":32.05114311085708,"target":41,"hits":1,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":52,"kind":"troop","team":0,"lane":"mid","zone":"lane","slot":1,"uid":"p1-3","def":"w04","alive":true,"hp":1560.0,"max_hp":1560.0,"shield":0.0,"x":1.2170830965042114,"y":-0.5420948266983032,"facing":-0.17093759965304972,"progress":31.846585228854398,"target":41,"hits":3,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":53,"kind":"hero","team":0,"lane":"mid","zone":"lane","slot":1,"uid":"h1-8","def":"w04","alive":true,"hp":2462.786,"max_hp":2596.0,"shield":0.0,"x":2.119291067123413,"y":-0.257298082113266,"facing":1.2469233992180253,"progress":32.29159964831486,"target":41,"hits":2,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":54,"kind":"troop","team":0,"lane":"mid","zone":"lane","slot":1,"uid":"p1-4","def":"w02","alive":true,"hp":800.0,"max_hp":800.0,"shield":0.0,"x":0.4987277686595917,"y":-2.1475696563720703,"facing":-2.3649015025852926,"progress":32.423294036262085,"target":43,"hits":1,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":55,"kind":"troop","team":0,"lane":"mid","zone":"lane","slot":1,"uid":"p1-5","def":"w06","alive":true,"hp":630.0,"max_hp":630.0,"shield":0.0,"x":-2.531480073928833,"y":2.1286559104919434,"facing":-1.8816700818164878,"progress":27.298984797238585,"target":41,"hits":3,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":56,"kind":"troop","team":0,"lane":"mid","zone":"lane","slot":1,"uid":"p1-6","def":"w06","alive":true,"hp":630.0,"max_hp":630.0,"shield":0.0,"x":-1.8042478561401367,"y":2.8885161876678467,"facing":2.3312996768508047,"progress":27.23847100841709,"target":41,"hits":2,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":57,"kind":"troop","team":0,"lane":"mid","zone":"lane","slot":1,"uid":"p1-7","def":"w06","alive":true,"hp":630.0,"max_hp":630.0,"shield":0.0,"x":-0.9487517476081848,"y":3.52622389793396,"facing":0.9479622239117398,"progress":27.3731495335385,"target":41,"hits":2,"reached":false,"dormant":false,"effects":[],"dots":[]}]},{"label":"boss_killed","phase":0,"round":8,"winner":-2,"end_note":"","players":[{"gold":1165,"draft_gold":1165,"ready":true,"earned":945,"spent":0,"next_seq":1,"roster":[],"hero":"","bookings":[],"new_bookings":[],"draft_roster":[],"draft_hero":"","boss_lane":"","undo":0},{"gold":5480,"draft_gold":5480,"ready":true,"earned":945,"spent":0,"next_seq":9,"roster":["p1-1|w04|mid|230","p1-2|w04|mid|230","p1-3|w04|mid|230","p1-4|w02|mid|150","p1-5|w06|mid|195","p1-6|w06|mid|195","p1-7|w06|mid|195"],"hero":"h1-8|held_ringborke|533|mid|||260|false|","bookings":[],"new_bookings":[],"draft_roster":["p1-1|w04|mid|230|false","p1-2|w04|mid|230|false","p1-3|w04|mid|230|false","p1-4|w02|mid|150|false","p1-5|w06|mid|195|false","p1-6|w06|mid|195|false","p1-7|w06|mid|195|false"],"draft_hero":"h1-8|held_ringborke|533|mid|||260|false|","boss_lane":"","undo":0},{"gold":1165,"draft_gold":1165,"ready":true,"earned":945,"spent":0,"next_seq":1,"roster":[],"hero":"","bookings":[],"new_bookings":[],"draft_roster":[],"draft_hero":"","boss_lane":"","undo":0},{"gold":1359,"draft_gold":1359,"ready":true,"earned":1139,"spent":0,"next_seq":1,"roster":[],"hero":"","bookings":[],"new_bookings":[],"draft_roster":[],"draft_hero":"","boss_lane":"","undo":0},{"gold":1358,"draft_gold":1358,"ready":true,"earned":1138,"spent":0,"next_seq":1,"roster":[],"hero":"","bookings":[],"new_bookings":[],"draft_roster":[],"draft_hero":"","boss_lane":"","undo":0},{"gold":1358,"draft_gold":1358,"ready":true,"earned":1138,"spent":0,"next_seq":1,"roster":[],"hero":"","bookings":[],"new_bookings":[],"draft_roster":[],"draft_hero":"","boss_lane":"","undo":0}],"buildings":[7500.0,6000.0,7500.0,6000.0,7500.0,6000.0,9000.0,9000.0,12000.0,7500.0,6000.0,0.0,0.0,7500.0,6000.0,4295.5403999999935,3866.1179999999986,12000.0],"boss":{"next":10,"settled":7,"claim":""},"boss_log":["6|won|0||1","7|deployed|0|top|-1"],"announcements":[],"settlement":{"round":7,"gains":[178,178,178,372,371,371],"income":94,"lost":["rot_mid_outer","rot_mid_inner"],"end_reason":"cleared","combat_time":81.99999999999748,"boss":"deployed","lane_kills":{"mid":10,"bot":10,"top":10},"xp":{"h1-8":237}},"combat":{"round":7,"steps":1640,"elapsed":81.99999999999748,"finished":true,"end_reason":"cleared","destroyed":[],"grotto":"none|-1|-1|true","grotto_boss":"","grotto_boss_hp":0.0,"events":41,"mobile":[0,0,0]},"events":[[1,139,6.949999999999983,1,"mid","lane","monster",39,"e01",7,"",19,["h1-8"]],[2,153,7.649999999999981,0,"mid","lane","monster",24,"e01",7,"",19,[]],[3,166,8.299999999999983,1,"mid","lane","monster",40,"e02",15,"",19,["h1-8"]],[4,200,10.000000000000007,1,"mid","lane","monster",41,"e03",12,"",19,["h1-8"]],[5,201,10.050000000000008,0,"top","lane","boss",49,"e10",940,"",220,[]],[6,222,11.100000000000023,1,"mid","lane","monster",43,"e03",12,"",19,["h1-8"]],[7,240,12.000000000000036,0,"bot","lane","monster",29,"e01",7,"",19,[]],[8,240,12.000000000000036,1,"bot","lane","monster",44,"e01",7,"",19,[]],[9,251,12.550000000000043,0,"top","lane","monster",19,"e01",7,"",19,[]],[10,251,12.550000000000043,1,"top","lane","monster",34,"e01",7,"",19,[]],[11,259,12.950000000000049,1,"mid","lane","monster",42,"e04",12,"",19,["h1-8"]],[12,363,18.150000000000123,0,"bot","lane","monster",30,"e02",15,"",19,[]],[13,363,18.150000000000123,1,"bot","lane","monster",45,"e02",15,"",19,[]],[14,373,18.65000000000013,0,"top","lane","monster",20,"e02",15,"",19,[]],[15,373,18.65000000000013,1,"top","lane","monster",35,"e02",15,"",19,[]],[16,471,23.5500000000002,0,"bot","lane","monster",33,"e03",12,"",19,[]],[17,471,23.5500000000002,1,"bot","lane","monster",48,"e03",12,"",19,[]],[18,519,25.950000000000234,0,"top","lane","monster",21,"e03",12,"",19,[]],[19,519,25.950000000000234,1,"top","lane","monster",36,"e03",12,"",19,[]],[20,521,26.050000000000235,1,"mid","lane","tower",13,"rot_mid_outer",150,"rot_mid_outer",60,["h1-8"]],[21,622,31.100000000000307,0,"top","lane","monster",23,"e03",12,"",19,[]],[22,622,31.100000000000307,1,"top","lane","monster",38,"e03",12,"",19,[]],[23,634,31.700000000000315,0,"bot","lane","monster",31,"e03",12,"",19,[]],[24,634,31.700000000000315,1,"bot","lane","monster",46,"e03",12,"",19,[]],[25,745,37.25000000000002,0,"mid","lane","hero",53,"w04",0,"",15,[]],[26,805,40.24999999999985,0,"mid","lane","monster",25,"e02",15,"",19,[]],[27,887,44.34999999999962,0,"top","lane","monster",22,"e04",12,"",19,[]],[28,887,44.34999999999962,1,"top","lane","monster",37,"e04",12,"",19,[]],[29,910,45.49999999999955,1,"mid","lane","tower",12,"rot_mid_inner",210,"rot_mid_inner",60,[]],[30,910,45.49999999999955,0,"bot","lane","monster",32,"e04",12,"",19,[]],[31,910,45.49999999999955,1,"bot","lane","monster",47,"e04",12,"",19,[]],[32,1217,60.84999999999868,0,"mid","lane","troop",50,"w04",0,"",15,[]],[33,1224,61.19999999999866,0,"mid","lane","troop",52,"w04",0,"",15,[]],[34,1257,62.849999999998566,0,"mid","lane","troop",54,"w02",0,"",15,[]],[35,1284,64.1999999999985,0,"mid","lane","monster",26,"e03",12,"",19,[]],[36,1397,69.84999999999818,0,"mid","lane","troop",51,"w04",0,"",15,[]],[37,1437,71.84999999999806,0,"mid","lane","monster",28,"e03",12,"",19,[]],[38,1477,73.84999999999795,0,"mid","lane","monster",27,"e04",12,"",19,[]],[39,1560,77.99999999999771,0,"mid","lane","troop",57,"w06",0,"",15,[]],[40,1597,79.8499999999976,0,"mid","lane","troop",55,"w06",0,"",15,[]],[41,1640,81.99999999999748,0,"mid","lane","troop",56,"w06",0,"",15,[]]]},{"label":"locked_r8","phase":0,"round":8,"winner":-2,"end_note":"","players":[{"gold":1165,"draft_gold":1165,"ready":true,"earned":945,"spent":0,"next_seq":1,"roster":[],"hero":"","bookings":[],"new_bookings":[],"draft_roster":[],"draft_hero":"","boss_lane":"","undo":0},{"gold":5480,"draft_gold":5480,"ready":true,"earned":945,"spent":0,"next_seq":9,"roster":["p1-1|w04|mid|230","p1-2|w04|mid|230","p1-3|w04|mid|230","p1-4|w02|mid|150","p1-5|w06|mid|195","p1-6|w06|mid|195","p1-7|w06|mid|195"],"hero":"h1-8|held_ringborke|533|mid|||260|false|","bookings":[],"new_bookings":[],"draft_roster":["p1-1|w04|mid|230|false","p1-2|w04|mid|230|false","p1-3|w04|mid|230|false","p1-4|w02|mid|150|false","p1-5|w06|mid|195|false","p1-6|w06|mid|195|false","p1-7|w06|mid|195|false"],"draft_hero":"h1-8|held_ringborke|533|mid|||260|false|","boss_lane":"","undo":0},{"gold":1165,"draft_gold":1165,"ready":true,"earned":945,"spent":0,"next_seq":1,"roster":[],"hero":"","bookings":[],"new_bookings":[],"draft_roster":[],"draft_hero":"","boss_lane":"","undo":0},{"gold":1359,"draft_gold":1359,"ready":true,"earned":1139,"spent":0,"next_seq":1,"roster":[],"hero":"","bookings":[],"new_bookings":[],"draft_roster":[],"draft_hero":"","boss_lane":"","undo":0},{"gold":1358,"draft_gold":1358,"ready":true,"earned":1138,"spent":0,"next_seq":1,"roster":[],"hero":"","bookings":[],"new_bookings":[],"draft_roster":[],"draft_hero":"","boss_lane":"","undo":0},{"gold":1358,"draft_gold":1358,"ready":true,"earned":1138,"spent":0,"next_seq":1,"roster":[],"hero":"","bookings":[],"new_bookings":[],"draft_roster":[],"draft_hero":"","boss_lane":"","undo":0}],"buildings":[7500.0,6000.0,7500.0,6000.0,7500.0,6000.0,9000.0,9000.0,12000.0,7500.0,6000.0,7500.0,6000.0,7500.0,6000.0,9000.0,9000.0,12000.0],"boss":{"next":10,"settled":7,"claim":""},"boss_log":["6|won|0||1","7|deployed|0|top|-1"],"announcements":[],"settlement":{"round":7,"gains":[178,178,178,372,371,371],"income":94,"lost":["rot_mid_outer","rot_mid_inner"],"end_reason":"cleared","combat_time":81.99999999999748,"boss":"deployed","lane_kills":{"mid":10,"bot":10,"top":10},"xp":{"h1-8":237}},"combat":{"round":7,"steps":1640,"elapsed":81.99999999999748,"finished":true,"end_reason":"cleared","destroyed":[],"grotto":"none|-1|-1|true","grotto_boss":"","grotto_boss_hp":0.0,"events":41,"mobile":[0,0,0]}},{"label":"round-8","phase":0,"round":9,"winner":-2,"end_note":"","players":[{"gold":1440,"draft_gold":1440,"ready":true,"earned":1220,"spent":0,"next_seq":1,"roster":[],"hero":"","bookings":[],"new_bookings":[],"draft_roster":[],"draft_hero":"","boss_lane":"","undo":0},{"gold":5755,"draft_gold":5755,"ready":true,"earned":1220,"spent":0,"next_seq":9,"roster":["p1-1|w04|mid|230","p1-2|w04|mid|230","p1-3|w04|mid|230","p1-4|w02|mid|150","p1-5|w06|mid|195","p1-6|w06|mid|195","p1-7|w06|mid|195"],"hero":"h1-8|held_ringborke|841|mid|||260|false|","bookings":[],"new_bookings":[],"draft_roster":["p1-1|w04|mid|230|false","p1-2|w04|mid|230|false","p1-3|w04|mid|230|false","p1-4|w02|mid|150|false","p1-5|w06|mid|195|false","p1-6|w06|mid|195|false","p1-7|w06|mid|195|false"],"draft_hero":"h1-8|held_ringborke|841|mid|||260|false|","boss_lane":"","undo":0},{"gold":1440,"draft_gold":1440,"ready":true,"earned":1220,"spent":0,"next_seq":1,"roster":[],"hero":"","bookings":[],"new_bookings":[],"draft_roster":[],"draft_hero":"","boss_lane":"","undo":0},{"gold":1514,"draft_gold":1514,"ready":true,"earned":1294,"spent":0,"next_seq":1,"roster":[],"hero":"","bookings":[],"new_bookings":[],"draft_roster":[],"draft_hero":"","boss_lane":"","undo":0},{"gold":1513,"draft_gold":1513,"ready":true,"earned":1293,"spent":0,"next_seq":1,"roster":[],"hero":"","bookings":[],"new_bookings":[],"draft_roster":[],"draft_hero":"","boss_lane":"","undo":0},{"gold":1513,"draft_gold":1513,"ready":true,"earned":1293,"spent":0,"next_seq":1,"roster":[],"hero":"","bookings":[],"new_bookings":[],"draft_roster":[],"draft_hero":"","boss_lane":"","undo":0}],"buildings":[7500.0,6000.0,7500.0,6000.0,7500.0,6000.0,9000.0,9000.0,12000.0,7500.0,6000.0,0.0,0.0,7500.0,6000.0,4301.625600000002,3699.322499999991,12000.0],"boss":{"next":10,"settled":8,"claim":""},"boss_log":["6|won|0||1","7|deployed|0|top|-1"],"announcements":[],"settlement":{"round":8,"gains":[177,177,177,57,57,57],"income":98,"lost":["rot_mid_outer","rot_mid_inner"],"end_reason":"cleared","combat_time":81.6499999999975,"boss":"none","lane_kills":{"mid":10,"bot":10,"top":10},"xp":{"h1-8":308}},"combat":{"round":8,"steps":1633,"elapsed":81.6499999999975,"finished":true,"end_reason":"cleared","destroyed":[],"grotto":"none|-1|-1|true","grotto_boss":"","grotto_boss_hp":0.0,"events":40,"mobile":[0,0,0]}},{"label":"locked_r9","phase":0,"round":9,"winner":-2,"end_note":"","players":[{"gold":1440,"draft_gold":1440,"ready":true,"earned":1220,"spent":0,"next_seq":1,"roster":[],"hero":"","bookings":[],"new_bookings":[],"draft_roster":[],"draft_hero":"","boss_lane":"","undo":0},{"gold":5755,"draft_gold":5755,"ready":true,"earned":1220,"spent":0,"next_seq":9,"roster":["p1-1|w04|mid|230","p1-2|w04|mid|230","p1-3|w04|mid|230","p1-4|w02|mid|150","p1-5|w06|mid|195","p1-6|w06|mid|195","p1-7|w06|mid|195"],"hero":"h1-8|held_ringborke|841|mid|||260|false|","bookings":[],"new_bookings":[],"draft_roster":["p1-1|w04|mid|230|false","p1-2|w04|mid|230|false","p1-3|w04|mid|230|false","p1-4|w02|mid|150|false","p1-5|w06|mid|195|false","p1-6|w06|mid|195|false","p1-7|w06|mid|195|false"],"draft_hero":"h1-8|held_ringborke|841|mid|||260|false|","boss_lane":"","undo":0},{"gold":1440,"draft_gold":1440,"ready":true,"earned":1220,"spent":0,"next_seq":1,"roster":[],"hero":"","bookings":[],"new_bookings":[],"draft_roster":[],"draft_hero":"","boss_lane":"","undo":0},{"gold":1514,"draft_gold":1514,"ready":true,"earned":1294,"spent":0,"next_seq":1,"roster":[],"hero":"","bookings":[],"new_bookings":[],"draft_roster":[],"draft_hero":"","boss_lane":"","undo":0},{"gold":1513,"draft_gold":1513,"ready":true,"earned":1293,"spent":0,"next_seq":1,"roster":[],"hero":"","bookings":[],"new_bookings":[],"draft_roster":[],"draft_hero":"","boss_lane":"","undo":0},{"gold":1513,"draft_gold":1513,"ready":true,"earned":1293,"spent":0,"next_seq":1,"roster":[],"hero":"","bookings":[],"new_bookings":[],"draft_roster":[],"draft_hero":"","boss_lane":"","undo":0}],"buildings":[7500.0,6000.0,7500.0,6000.0,7500.0,6000.0,9000.0,9000.0,12000.0,7500.0,6000.0,7500.0,6000.0,7500.0,6000.0,9000.0,9000.0,12000.0],"boss":{"next":10,"settled":8,"claim":""},"boss_log":["6|won|0||1","7|deployed|0|top|-1"],"announcements":[],"settlement":{"round":8,"gains":[177,177,177,57,57,57],"income":98,"lost":["rot_mid_outer","rot_mid_inner"],"end_reason":"cleared","combat_time":81.6499999999975,"boss":"none","lane_kills":{"mid":10,"bot":10,"top":10},"xp":{"h1-8":308}},"combat":{"round":8,"steps":1633,"elapsed":81.6499999999975,"finished":true,"end_reason":"cleared","destroyed":[],"grotto":"none|-1|-1|true","grotto_boss":"","grotto_boss_hp":0.0,"events":40,"mobile":[0,0,0]}},{"label":"round-9","phase":0,"round":10,"winner":-2,"end_note":"","players":[{"gold":1728,"draft_gold":1728,"ready":true,"earned":1508,"spent":0,"next_seq":1,"roster":[],"hero":"","bookings":[],"new_bookings":[],"draft_roster":[],"draft_hero":"","boss_lane":"","undo":0},{"gold":6043,"draft_gold":6043,"ready":true,"earned":1508,"spent":0,"next_seq":9,"roster":["p1-1|w04|mid|230","p1-2|w04|mid|230","p1-3|w04|mid|230","p1-4|w02|mid|150","p1-5|w06|mid|195","p1-6|w06|mid|195","p1-7|w06|mid|195"],"hero":"h1-8|held_ringborke|1160|mid|||260|false|","bookings":[],"new_bookings":[],"draft_roster":["p1-1|w04|mid|230|false","p1-2|w04|mid|230|false","p1-3|w04|mid|230|false","p1-4|w02|mid|150|false","p1-5|w06|mid|195|false","p1-6|w06|mid|195|false","p1-7|w06|mid|195|false"],"draft_hero":"h1-8|held_ringborke|1160|mid|||260|false|","boss_lane":"","undo":0},{"gold":1728,"draft_gold":1728,"ready":true,"earned":1508,"spent":0,"next_seq":1,"roster":[],"hero":"","bookings":[],"new_bookings":[],"draft_roster":[],"draft_hero":"","boss_lane":"","undo":0},{"gold":1682,"draft_gold":1682,"ready":true,"earned":1462,"spent":0,"next_seq":1,"roster":[],"hero":"","bookings":[],"new_bookings":[],"draft_roster":[],"draft_hero":"","boss_lane":"","undo":0},{"gold":1681,"draft_gold":1681,"ready":true,"earned":1461,"spent":0,"next_seq":1,"roster":[],"hero":"","bookings":[],"new_bookings":[],"draft_roster":[],"draft_hero":"","boss_lane":"","undo":0},{"gold":1681,"draft_gold":1681,"ready":true,"earned":1461,"spent":0,"next_seq":1,"roster":[],"hero":"","bookings":[],"new_bookings":[],"draft_roster":[],"draft_hero":"","boss_lane":"","undo":0}],"buildings":[7500.0,6000.0,7500.0,6000.0,7500.0,6000.0,9000.0,9000.0,12000.0,7500.0,6000.0,0.0,0.0,7500.0,6000.0,3223.1247999999987,708.7767999999949,12000.0],"boss":{"next":10,"settled":9,"claim":""},"boss_log":["6|won|0||1","7|deployed|0|top|-1"],"announcements":[],"settlement":{"round":9,"gains":[186,186,186,66,66,66],"income":102,"lost":["rot_mid_outer","rot_mid_inner"],"end_reason":"cleared","combat_time":90.39999999999701,"boss":"none","lane_kills":{"mid":10,"bot":10,"top":10},"xp":{"h1-8":319}},"combat":{"round":9,"steps":1808,"elapsed":90.39999999999701,"finished":true,"end_reason":"cleared","destroyed":[],"grotto":"none|-1|-1|true","grotto_boss":"","grotto_boss_hp":0.0,"events":40,"mobile":[0,0,0]}},{"label":"open_r10","phase":0,"round":10,"winner":-2,"end_note":"","players":[{"gold":1728,"draft_gold":1728,"ready":true,"earned":1508,"spent":0,"next_seq":1,"roster":[],"hero":"","bookings":[],"new_bookings":[],"draft_roster":[],"draft_hero":"","boss_lane":"","undo":0},{"gold":6043,"draft_gold":6043,"ready":true,"earned":1508,"spent":0,"next_seq":9,"roster":["p1-1|w04|mid|230","p1-2|w04|mid|230","p1-3|w04|mid|230","p1-4|w02|mid|150","p1-5|w06|mid|195","p1-6|w06|mid|195","p1-7|w06|mid|195"],"hero":"h1-8|held_ringborke|1160|mid|||260|false|","bookings":[],"new_bookings":[],"draft_roster":["p1-1|w04|mid|230|false","p1-2|w04|mid|230|false","p1-3|w04|mid|230|false","p1-4|w02|mid|150|false","p1-5|w06|mid|195|false","p1-6|w06|mid|195|false","p1-7|w06|mid|195|false"],"draft_hero":"h1-8|held_ringborke|1160|mid|||260|false|","boss_lane":"","undo":0},{"gold":1728,"draft_gold":1728,"ready":true,"earned":1508,"spent":0,"next_seq":1,"roster":[],"hero":"","bookings":[],"new_bookings":[],"draft_roster":[],"draft_hero":"","boss_lane":"","undo":0},{"gold":1682,"draft_gold":1682,"ready":true,"earned":1462,"spent":0,"next_seq":1,"roster":[],"hero":"","bookings":[],"new_bookings":[],"draft_roster":[],"draft_hero":"","boss_lane":"","undo":0},{"gold":1681,"draft_gold":1681,"ready":true,"earned":1461,"spent":0,"next_seq":1,"roster":[],"hero":"","bookings":[],"new_bookings":[],"draft_roster":[],"draft_hero":"","boss_lane":"","undo":0},{"gold":1681,"draft_gold":1681,"ready":true,"earned":1461,"spent":0,"next_seq":1,"roster":[],"hero":"","bookings":[],"new_bookings":[],"draft_roster":[],"draft_hero":"","boss_lane":"","undo":0}],"buildings":[7500.0,6000.0,7500.0,6000.0,7500.0,6000.0,9000.0,9000.0,12000.0,7500.0,6000.0,0.0,0.0,7500.0,6000.0,3223.1247999999987,708.7767999999949,12000.0],"boss":{"next":10,"settled":9,"claim":""},"boss_log":["6|won|0||1","7|deployed|0|top|-1"],"announcements":[],"settlement":{"round":9,"gains":[186,186,186,66,66,66],"income":102,"lost":["rot_mid_outer","rot_mid_inner"],"end_reason":"cleared","combat_time":90.39999999999701,"boss":"none","lane_kills":{"mid":10,"bot":10,"top":10},"xp":{"h1-8":319}},"combat":{"round":9,"steps":1808,"elapsed":90.39999999999701,"finished":true,"end_reason":"cleared","destroyed":[],"grotto":"none|-1|-1|true","grotto_boss":"","grotto_boss_hp":0.0,"events":40,"mobile":[0,0,0]}},{"label":"no_second_deployment","phase":1,"round":10,"winner":-2,"end_note":"","players":[{"gold":1728,"draft_gold":1728,"ready":true,"earned":1508,"spent":0,"next_seq":1,"roster":[],"hero":"","bookings":[],"new_bookings":[],"draft_roster":[],"draft_hero":"","boss_lane":"","undo":0},{"gold":6043,"draft_gold":6043,"ready":true,"earned":1508,"spent":0,"next_seq":9,"roster":["p1-1|w04|mid|230","p1-2|w04|mid|230","p1-3|w04|mid|230","p1-4|w02|mid|150","p1-5|w06|mid|195","p1-6|w06|mid|195","p1-7|w06|mid|195"],"hero":"h1-8|held_ringborke|1160|mid|||260|false|","bookings":[],"new_bookings":[],"draft_roster":["p1-1|w04|mid|230|false","p1-2|w04|mid|230|false","p1-3|w04|mid|230|false","p1-4|w02|mid|150|false","p1-5|w06|mid|195|false","p1-6|w06|mid|195|false","p1-7|w06|mid|195|false"],"draft_hero":"h1-8|held_ringborke|1160|mid|||260|false|","boss_lane":"","undo":0},{"gold":1728,"draft_gold":1728,"ready":true,"earned":1508,"spent":0,"next_seq":1,"roster":[],"hero":"","bookings":[],"new_bookings":[],"draft_roster":[],"draft_hero":"","boss_lane":"","undo":0},{"gold":1682,"draft_gold":1682,"ready":true,"earned":1462,"spent":0,"next_seq":1,"roster":[],"hero":"","bookings":[],"new_bookings":[],"draft_roster":[],"draft_hero":"","boss_lane":"","undo":0},{"gold":1681,"draft_gold":1681,"ready":true,"earned":1461,"spent":0,"next_seq":1,"roster":[],"hero":"","bookings":[],"new_bookings":[],"draft_roster":[],"draft_hero":"","boss_lane":"","undo":0},{"gold":1681,"draft_gold":1681,"ready":true,"earned":1461,"spent":0,"next_seq":1,"roster":[],"hero":"","bookings":[],"new_bookings":[],"draft_roster":[],"draft_hero":"","boss_lane":"","undo":0}],"buildings":[7500.0,6000.0,7500.0,6000.0,7500.0,6000.0,9000.0,9000.0,12000.0,7500.0,6000.0,0.0,0.0,7500.0,6000.0,3223.1247999999987,708.7767999999949,12000.0],"boss":{"next":10,"settled":9,"claim":""},"boss_log":["6|won|0||1","7|deployed|0|top|-1"],"announcements":[],"settlement":{"round":9,"gains":[186,186,186,66,66,66],"income":102,"lost":["rot_mid_outer","rot_mid_inner"],"end_reason":"cleared","combat_time":90.39999999999701,"boss":"none","lane_kills":{"mid":10,"bot":10,"top":10},"xp":{"h1-8":319}},"combat":{"round":10,"steps":0,"elapsed":0.0,"finished":false,"end_reason":"","destroyed":[],"grotto":"none|-1|-1|true","grotto_boss":"","grotto_boss_hp":0.0,"events":0,"mobile":[26,18,0]},"units":[{"id":1,"kind":"tower","team":0,"lane":"top","zone":"lane","slot":-1,"uid":"","def":"blau_top_inner","alive":true,"hp":7500.0,"max_hp":7500.0,"shield":0.0,"x":-24.931251525878906,"y":4.5293378829956055,"facing":0.0,"progress":0.0,"target":-1,"hits":0,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":2,"kind":"tower","team":0,"lane":"top","zone":"lane","slot":-1,"uid":"","def":"blau_top_outer","alive":true,"hp":6000.0,"max_hp":6000.0,"shield":0.0,"x":-24.921451568603516,"y":-12.715348243713379,"facing":0.0,"progress":0.0,"target":-1,"hits":0,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":3,"kind":"tower","team":0,"lane":"mid","zone":"lane","slot":-1,"uid":"","def":"blau_mid_inner","alive":true,"hp":7500.0,"max_hp":7500.0,"shield":0.0,"x":-11.427590370178223,"y":17.012392044067383,"facing":0.0,"progress":0.0,"target":-1,"hits":0,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":4,"kind":"tower","team":0,"lane":"mid","zone":"lane","slot":-1,"uid":"","def":"blau_mid_outer","alive":true,"hp":6000.0,"max_hp":6000.0,"shield":0.0,"x":-3.8433847427368164,"y":8.990991592407227,"facing":0.0,"progress":0.0,"target":-1,"hits":0,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":5,"kind":"tower","team":0,"lane":"bot","zone":"lane","slot":-1,"uid":"","def":"blau_bot_inner","alive":true,"hp":7500.0,"max_hp":7500.0,"shield":0.0,"x":-4.349228858947754,"y":31.034507751464844,"facing":0.0,"progress":0.0,"target":-1,"hits":0,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":6,"kind":"tower","team":0,"lane":"bot","zone":"lane","slot":-1,"uid":"","def":"blau_bot_outer","alive":true,"hp":6000.0,"max_hp":6000.0,"shield":0.0,"x":11.117134094238281,"y":28.989334106445313,"facing":0.0,"progress":0.0,"target":-1,"hits":0,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":7,"kind":"tower","team":0,"lane":"base","zone":"lane","slot":-1,"uid":"","def":"blau_base_1","alive":true,"hp":9000.0,"max_hp":9000.0,"shield":0.0,"x":-29.476999282836914,"y":24.023000717163086,"facing":0.0,"progress":0.0,"target":-1,"hits":0,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":8,"kind":"tower","team":0,"lane":"base","zone":"lane","slot":-1,"uid":"","def":"blau_base_2","alive":true,"hp":9000.0,"max_hp":9000.0,"shield":0.0,"x":-24.023000717163086,"y":29.476999282836914,"facing":0.0,"progress":0.0,"target":-1,"hits":0,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":9,"kind":"core","team":0,"lane":"base","zone":"lane","slot":-1,"uid":"","def":"blau_ancient","alive":true,"hp":12000.0,"max_hp":12000.0,"shield":0.0,"x":-30.0,"y":30.0,"facing":0.0,"progress":0.0,"target":-1,"hits":0,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":10,"kind":"tower","team":1,"lane":"top","zone":"lane","slot":-1,"uid":"","def":"rot_top_inner","alive":true,"hp":7500.0,"max_hp":7500.0,"shield":0.0,"x":4.5293378829956055,"y":-24.931251525878906,"facing":0.0,"progress":0.0,"target":-1,"hits":0,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":11,"kind":"tower","team":1,"lane":"top","zone":"lane","slot":-1,"uid":"","def":"rot_top_outer","alive":true,"hp":6000.0,"max_hp":6000.0,"shield":0.0,"x":-12.715348243713379,"y":-24.921451568603516,"facing":0.0,"progress":0.0,"target":-1,"hits":0,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":12,"kind":"tower","team":1,"lane":"bot","zone":"lane","slot":-1,"uid":"","def":"rot_bot_inner","alive":true,"hp":7500.0,"max_hp":7500.0,"shield":0.0,"x":31.034507751464844,"y":-4.349228858947754,"facing":0.0,"progress":0.0,"target":-1,"hits":0,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":13,"kind":"tower","team":1,"lane":"bot","zone":"lane","slot":-1,"uid":"","def":"rot_bot_outer","alive":true,"hp":6000.0,"max_hp":6000.0,"shield":0.0,"x":28.989334106445313,"y":11.117134094238281,"facing":0.0,"progress":0.0,"target":-1,"hits":0,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":14,"kind":"tower","team":1,"lane":"base","zone":"lane","slot":-1,"uid":"","def":"rot_base_1","alive":true,"hp":3223.1247999999987,"max_hp":9000.0,"shield":0.0,"x":24.023000717163086,"y":-29.476999282836914,"facing":0.0,"progress":0.0,"target":-1,"hits":0,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":15,"kind":"tower","team":1,"lane":"base","zone":"lane","slot":-1,"uid":"","def":"rot_base_2","alive":true,"hp":708.7767999999949,"max_hp":9000.0,"shield":0.0,"x":29.476999282836914,"y":-24.023000717163086,"facing":0.0,"progress":0.0,"target":-1,"hits":0,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":16,"kind":"core","team":1,"lane":"base","zone":"lane","slot":-1,"uid":"","def":"rot_ancient","alive":true,"hp":12000.0,"max_hp":12000.0,"shield":0.0,"x":30.0,"y":-30.0,"facing":0.0,"progress":0.0,"target":-1,"hits":0,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":17,"kind":"monster","team":0,"lane":"top","zone":"lane","slot":-1,"uid":"","def":"e01","alive":true,"hp":190.035,"max_hp":190.035,"shield":0.0,"x":-28.243892669677734,"y":10.502157211303711,"facing":-2.864119239296395,"progress":11.0,"target":-1,"hits":0,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":18,"kind":"monster","team":0,"lane":"top","zone":"lane","slot":-1,"uid":"","def":"e02","alive":true,"hp":506.76,"max_hp":506.76,"shield":0.0,"x":-26.993616104125977,"y":10.146052360534668,"facing":-2.864119239296395,"progress":11.0,"target":-1,"hits":0,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":19,"kind":"monster","team":0,"lane":"top","zone":"lane","slot":-1,"uid":"","def":"e01","alive":true,"hp":190.035,"max_hp":190.035,"shield":0.0,"x":-25.74333953857422,"y":9.789947509765625,"facing":-2.864119239296395,"progress":11.0,"target":-1,"hits":0,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":20,"kind":"monster","team":0,"lane":"top","zone":"lane","slot":-1,"uid":"","def":"e04","alive":true,"hp":274.495,"max_hp":274.495,"shield":0.0,"x":-27.921968460083008,"y":11.702203750610352,"facing":-2.9843745641096318,"progress":9.6,"target":-1,"hits":0,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":21,"kind":"monster","team":0,"lane":"top","zone":"lane","slot":-1,"uid":"","def":"e03","alive":true,"hp":316.72499999999997,"max_hp":316.72499999999997,"shield":0.0,"x":-26.638002395629883,"y":11.498661041259766,"facing":-2.9843745641096318,"progress":9.6,"target":-1,"hits":0,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":22,"kind":"monster","team":0,"lane":"top","zone":"lane","slot":-1,"uid":"","def":"e06","alive":true,"hp":401.185,"max_hp":401.185,"shield":0.0,"x":-25.354036331176758,"y":11.29511833190918,"facing":-2.9843745641096318,"progress":9.6,"target":-1,"hits":0,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":23,"kind":"monster","team":0,"lane":"mid","zone":"lane","slot":-1,"uid":"","def":"e01","alive":true,"hp":190.035,"max_hp":190.035,"shield":0.0,"x":-14.408708572387695,"y":13.32747745513916,"facing":2.3870002372622334,"progress":11.0,"target":-1,"hits":0,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":24,"kind":"monster","team":0,"lane":"mid","zone":"lane","slot":-1,"uid":"","def":"e02","alive":true,"hp":506.76,"max_hp":506.76,"shield":0.0,"x":-13.461592674255371,"y":14.21796703338623,"facing":2.3870002372622334,"progress":11.0,"target":-1,"hits":0,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":25,"kind":"monster","team":0,"lane":"mid","zone":"lane","slot":-1,"uid":"","def":"e01","alive":true,"hp":190.035,"max_hp":190.035,"shield":0.0,"x":-12.514476776123047,"y":15.1084566116333,"facing":2.3870002372622334,"progress":11.0,"target":-1,"hits":0,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":26,"kind":"monster","team":0,"lane":"mid","zone":"lane","slot":-1,"uid":"","def":"e04","alive":true,"hp":274.495,"max_hp":274.495,"shield":0.0,"x":-15.366670608520508,"y":14.327392578125,"facing":2.3752783515087157,"progress":9.6,"target":-1,"hits":0,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":27,"kind":"monster","team":0,"lane":"mid","zone":"lane","slot":-1,"uid":"","def":"e03","alive":true,"hp":316.72499999999997,"max_hp":316.72499999999997,"shield":0.0,"x":-14.430057525634766,"y":15.228922843933105,"facing":2.3752783515087157,"progress":9.6,"target":-1,"hits":0,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":28,"kind":"monster","team":0,"lane":"mid","zone":"lane","slot":-1,"uid":"","def":"e06","alive":true,"hp":401.185,"max_hp":401.185,"shield":0.0,"x":-13.493444442749023,"y":16.13045310974121,"facing":2.3752783515087157,"progress":9.6,"target":-1,"hits":0,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":29,"kind":"monster","team":0,"lane":"bot","zone":"lane","slot":-1,"uid":"","def":"e01","alive":true,"hp":190.035,"max_hp":190.035,"shield":0.0,"x":-9.842267036437988,"y":25.94097137451172,"facing":1.4313591016628469,"progress":11.0,"target":-1,"hits":0,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":30,"kind":"monster","team":0,"lane":"bot","zone":"lane","slot":-1,"uid":"","def":"e02","alive":true,"hp":506.76,"max_hp":506.76,"shield":0.0,"x":-10.022948265075684,"y":27.22835350036621,"facing":1.4313591016628469,"progress":11.0,"target":-1,"hits":0,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":31,"kind":"monster","team":0,"lane":"bot","zone":"lane","slot":-1,"uid":"","def":"e01","alive":true,"hp":190.035,"max_hp":190.035,"shield":0.0,"x":-10.203629493713379,"y":28.515735626220703,"facing":1.4313591016628469,"progress":11.0,"target":-1,"hits":0,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":32,"kind":"monster","team":0,"lane":"bot","zone":"lane","slot":-1,"uid":"","def":"e04","alive":true,"hp":274.495,"max_hp":274.495,"shield":0.0,"x":-11.322441101074219,"y":25.77979278564453,"facing":1.5004101357551378,"progress":9.6,"target":-1,"hits":0,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":33,"kind":"monster","team":0,"lane":"bot","zone":"lane","slot":-1,"uid":"","def":"e03","alive":true,"hp":316.72499999999997,"max_hp":316.72499999999997,"shield":0.0,"x":-11.413867950439453,"y":27.076574325561523,"facing":1.5004101357551378,"progress":9.6,"target":-1,"hits":0,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":34,"kind":"monster","team":0,"lane":"bot","zone":"lane","slot":-1,"uid":"","def":"e06","alive":true,"hp":401.185,"max_hp":401.185,"shield":0.0,"x":-11.505294799804688,"y":28.373355865478516,"facing":1.5004101357551378,"progress":9.6,"target":-1,"hits":0,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":35,"kind":"monster","team":1,"lane":"top","zone":"lane","slot":-1,"uid":"","def":"e01","alive":true,"hp":190.035,"max_hp":190.035,"shield":0.0,"x":10.502157211303711,"y":-28.243892669677734,"facing":-1.8482697410882951,"progress":11.0,"target":-1,"hits":0,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":36,"kind":"monster","team":1,"lane":"top","zone":"lane","slot":-1,"uid":"","def":"e02","alive":true,"hp":506.76,"max_hp":506.76,"shield":0.0,"x":10.146052360534668,"y":-26.993616104125977,"facing":-1.8482697410882951,"progress":11.0,"target":-1,"hits":0,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":37,"kind":"monster","team":1,"lane":"top","zone":"lane","slot":-1,"uid":"","def":"e01","alive":true,"hp":190.035,"max_hp":190.035,"shield":0.0,"x":9.789947509765625,"y":-25.74333953857422,"facing":-1.8482697410882951,"progress":11.0,"target":-1,"hits":0,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":38,"kind":"monster","team":1,"lane":"top","zone":"lane","slot":-1,"uid":"","def":"e04","alive":true,"hp":274.495,"max_hp":274.495,"shield":0.0,"x":11.702203750610352,"y":-27.921968460083008,"facing":-1.7280144162750581,"progress":9.6,"target":-1,"hits":0,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":39,"kind":"monster","team":1,"lane":"top","zone":"lane","slot":-1,"uid":"","def":"e03","alive":true,"hp":316.72499999999997,"max_hp":316.72499999999997,"shield":0.0,"x":11.498661041259766,"y":-26.638002395629883,"facing":-1.7280144162750581,"progress":9.6,"target":-1,"hits":0,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":40,"kind":"monster","team":1,"lane":"top","zone":"lane","slot":-1,"uid":"","def":"e06","alive":true,"hp":401.185,"max_hp":401.185,"shield":0.0,"x":11.29511833190918,"y":-25.354036331176758,"facing":-1.7280144162750581,"progress":9.6,"target":-1,"hits":0,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":41,"kind":"monster","team":1,"lane":"mid","zone":"lane","slot":-1,"uid":"","def":"e01","alive":true,"hp":190.035,"max_hp":190.035,"shield":0.0,"x":13.32747745513916,"y":-14.408708572387695,"facing":-0.816203910467337,"progress":11.0,"target":-1,"hits":0,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":42,"kind":"monster","team":1,"lane":"mid","zone":"lane","slot":-1,"uid":"","def":"e02","alive":true,"hp":506.76,"max_hp":506.76,"shield":0.0,"x":14.21796703338623,"y":-13.461592674255371,"facing":-0.816203910467337,"progress":11.0,"target":-1,"hits":0,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":43,"kind":"monster","team":1,"lane":"mid","zone":"lane","slot":-1,"uid":"","def":"e01","alive":true,"hp":190.035,"max_hp":190.035,"shield":0.0,"x":15.1084566116333,"y":-12.514476776123047,"facing":-0.816203910467337,"progress":11.0,"target":-1,"hits":0,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":44,"kind":"monster","team":1,"lane":"mid","zone":"lane","slot":-1,"uid":"","def":"e04","alive":true,"hp":274.495,"max_hp":274.495,"shield":0.0,"x":14.327392578125,"y":-15.366670608520508,"facing":-0.804482024713819,"progress":9.6,"target":-1,"hits":0,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":45,"kind":"monster","team":1,"lane":"mid","zone":"lane","slot":-1,"uid":"","def":"e03","alive":true,"hp":316.72499999999997,"max_hp":316.72499999999997,"shield":0.0,"x":15.228922843933105,"y":-14.430057525634766,"facing":-0.804482024713819,"progress":9.6,"target":-1,"hits":0,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":46,"kind":"monster","team":1,"lane":"mid","zone":"lane","slot":-1,"uid":"","def":"e06","alive":true,"hp":401.185,"max_hp":401.185,"shield":0.0,"x":16.13045310974121,"y":-13.493444442749023,"facing":-0.804482024713819,"progress":9.6,"target":-1,"hits":0,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":47,"kind":"monster","team":1,"lane":"bot","zone":"lane","slot":-1,"uid":"","def":"e01","alive":true,"hp":190.035,"max_hp":190.035,"shield":0.0,"x":25.94097137451172,"y":-9.842267036437988,"facing":0.13943722513204979,"progress":11.0,"target":-1,"hits":0,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":48,"kind":"monster","team":1,"lane":"bot","zone":"lane","slot":-1,"uid":"","def":"e02","alive":true,"hp":506.76,"max_hp":506.76,"shield":0.0,"x":27.22835350036621,"y":-10.022948265075684,"facing":0.13943722513204979,"progress":11.0,"target":-1,"hits":0,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":49,"kind":"monster","team":1,"lane":"bot","zone":"lane","slot":-1,"uid":"","def":"e01","alive":true,"hp":190.035,"max_hp":190.035,"shield":0.0,"x":28.515735626220703,"y":-10.203629493713379,"facing":0.13943722513204979,"progress":11.0,"target":-1,"hits":0,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":50,"kind":"monster","team":1,"lane":"bot","zone":"lane","slot":-1,"uid":"","def":"e04","alive":true,"hp":274.495,"max_hp":274.495,"shield":0.0,"x":25.77979278564453,"y":-11.322441101074219,"facing":0.07038619103975874,"progress":9.6,"target":-1,"hits":0,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":51,"kind":"monster","team":1,"lane":"bot","zone":"lane","slot":-1,"uid":"","def":"e03","alive":true,"hp":316.72499999999997,"max_hp":316.72499999999997,"shield":0.0,"x":27.076574325561523,"y":-11.413867950439453,"facing":0.07038619103975874,"progress":9.6,"target":-1,"hits":0,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":52,"kind":"monster","team":1,"lane":"bot","zone":"lane","slot":-1,"uid":"","def":"e06","alive":true,"hp":401.185,"max_hp":401.185,"shield":0.0,"x":28.373355865478516,"y":-11.505294799804688,"facing":0.07038619103975874,"progress":9.6,"target":-1,"hits":0,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":53,"kind":"troop","team":0,"lane":"mid","zone":"lane","slot":1,"uid":"p1-1","def":"w04","alive":true,"hp":1560.0,"max_hp":1560.0,"shield":0.0,"x":-17.386140823364258,"y":15.645247459411621,"facing":2.347786769279204,"progress":7.2,"target":-1,"hits":0,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":54,"kind":"troop","team":0,"lane":"mid","zone":"lane","slot":1,"uid":"p1-2","def":"w04","alive":true,"hp":1560.0,"max_hp":1560.0,"shield":0.0,"x":-16.544776916503906,"y":16.500879287719727,"facing":2.347786769279204,"progress":7.2,"target":-1,"hits":0,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":55,"kind":"troop","team":0,"lane":"mid","zone":"lane","slot":1,"uid":"p1-3","def":"w04","alive":true,"hp":1560.0,"max_hp":1560.0,"shield":0.0,"x":-15.703412055969238,"y":17.35651206970215,"facing":2.347786769279204,"progress":7.2,"target":-1,"hits":0,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":56,"kind":"hero","team":0,"lane":"mid","zone":"lane","slot":1,"uid":"h1-8","def":"w04","alive":true,"hp":3190.0,"max_hp":3190.0,"shield":0.0,"x":-14.862048149108887,"y":18.21214485168457,"facing":2.347786769279204,"progress":7.2,"target":-1,"hits":0,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":57,"kind":"troop","team":0,"lane":"mid","zone":"lane","slot":1,"uid":"p1-4","def":"w02","alive":true,"hp":800.0,"max_hp":800.0,"shield":0.0,"x":-18.432058334350586,"y":16.60871696472168,"facing":2.3046223302823,"progress":5.7,"target":-1,"hits":0,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":58,"kind":"troop","team":0,"lane":"mid","zone":"lane","slot":1,"uid":"p1-5","def":"w06","alive":true,"hp":630.0,"max_hp":630.0,"shield":0.0,"x":-17.628398895263672,"y":17.499858856201172,"facing":2.3046223302823,"progress":5.7,"target":-1,"hits":0,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":59,"kind":"troop","team":0,"lane":"mid","zone":"lane","slot":1,"uid":"p1-6","def":"w06","alive":true,"hp":630.0,"max_hp":630.0,"shield":0.0,"x":-16.82474136352539,"y":18.39099884033203,"facing":2.3046223302823,"progress":5.7,"target":-1,"hits":0,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":60,"kind":"troop","team":0,"lane":"mid","zone":"lane","slot":1,"uid":"p1-7","def":"w06","alive":true,"hp":630.0,"max_hp":630.0,"shield":0.0,"x":-16.021081924438477,"y":19.282140731811523,"facing":2.3046223302823,"progress":5.7,"target":-1,"hits":0,"reached":false,"dormant":false,"effects":[],"dots":[]}]}],"results":[["cmd",1,"buy",true,"Korkrücken gekauft."],["cmd",1,"upgrade",true,"Zu Ringborke aufgewertet."],["cmd",1,"assign",true,"In die Bossgrotte entsandt."],["cmd",1,"buy",true,"Korkrücken gekauft."],["cmd",1,"upgrade",true,"Zu Ringborke aufgewertet."],["cmd",1,"assign",true,"In die Bossgrotte entsandt."],["cmd",1,"buy",true,"Korkrücken gekauft."],["cmd",1,"upgrade",true,"Zu Ringborke aufgewertet."],["cmd",1,"assign",true,"In die Bossgrotte entsandt."],["cmd",1,"buy",true,"Dornhopser gekauft."],["cmd",1,"upgrade",true,"Zu Rankenschnapper aufgewertet."],["cmd",1,"assign",true,"In die Bossgrotte entsandt."],["cmd",1,"buy",true,"Samenschleuder gekauft."],["cmd",1,"upgrade",true,"Zu Zapfenkrone aufgewertet."],["cmd",1,"assign",true,"In die Bossgrotte entsandt."],["cmd",1,"buy",true,"Samenschleuder gekauft."],["cmd",1,"upgrade",true,"Zu Zapfenkrone aufgewertet."],["cmd",1,"assign",true,"In die Bossgrotte entsandt."],["cmd",1,"buy",true,"Samenschleuder gekauft."],["cmd",1,"upgrade",true,"Zu Zapfenkrone aufgewertet."],["cmd",1,"assign",true,"In die Bossgrotte entsandt."],["cmd",1,"hero_buy",true,"Ringborke angeworben."],["cmd",1,"assign",true,"In die Bossgrotte entsandt."],["begin",-1,"",true,""],["settle_boss",-1,"",true,"repeat"],["cmd",4,"boss_lane",false,"Du bestimmst die Boss-Lane nicht."],["cmd",1,"boss_lane",true,"Der Boss greift über Top an."],["cmd",1,"assign",false,"Die Grotte ist bis Runde 10 gesperrt."],["cmd",1,"assign",true,"Auf Mid eingeteilt."],["begin",-1,"",true,""],["begin",-1,"",true,""]]},"boss_failure":{"title":"Bossversuch gescheitert: keine Belohnung, keine Sperre, Boss beim nächsten Versuch voll","snapshots":[{"label":"attempt","phase":1,"round":1,"winner":-2,"end_note":"","players":[{"gold":220,"draft_gold":220,"ready":true,"earned":0,"spent":0,"next_seq":1,"roster":[],"hero":"","bookings":[],"new_bookings":[],"draft_roster":[],"draft_hero":"","boss_lane":"","undo":0},{"gold":220,"draft_gold":220,"ready":true,"earned":0,"spent":0,"next_seq":1,"roster":[],"hero":"","bookings":[],"new_bookings":[],"draft_roster":[],"draft_hero":"","boss_lane":"","undo":0},{"gold":375,"draft_gold":375,"ready":true,"earned":0,"spent":0,"next_seq":2,"roster":["p2-1|g01|grotto|45"],"hero":"","bookings":[],"new_bookings":[],"draft_roster":["p2-1|g01|grotto|45|true"],"draft_hero":"","boss_lane":"","undo":0},{"gold":220,"draft_gold":220,"ready":true,"earned":0,"spent":0,"next_seq":1,"roster":[],"hero":"","bookings":[],"new_bookings":[],"draft_roster":[],"draft_hero":"","boss_lane":"","undo":0},{"gold":220,"draft_gold":220,"ready":true,"earned":0,"spent":0,"next_seq":1,"roster":[],"hero":"","bookings":[],"new_bookings":[],"draft_roster":[],"draft_hero":"","boss_lane":"","undo":0},{"gold":220,"draft_gold":220,"ready":true,"earned":0,"spent":0,"next_seq":1,"roster":[],"hero":"","bookings":[],"new_bookings":[],"draft_roster":[],"draft_hero":"","boss_lane":"","undo":0}],"buildings":[7500.0,6000.0,7500.0,6000.0,7500.0,6000.0,9000.0,9000.0,12000.0,7500.0,6000.0,7500.0,6000.0,7500.0,6000.0,9000.0,9000.0,12000.0],"boss":{"next":1,"settled":0,"claim":""},"boss_log":[],"announcements":[],"settlement":null,"combat":{"round":1,"steps":0,"elapsed":0.0,"finished":false,"end_reason":"","destroyed":[],"grotto":"none|-1|-1|false","grotto_boss":"true|true|38","grotto_boss_hp":3600.0,"events":0,"mobile":[10,9,1]},"units":[{"id":1,"kind":"tower","team":0,"lane":"top","zone":"lane","slot":-1,"uid":"","def":"blau_top_inner","alive":true,"hp":7500.0,"max_hp":7500.0,"shield":0.0,"x":-24.931251525878906,"y":4.5293378829956055,"facing":0.0,"progress":0.0,"target":-1,"hits":0,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":2,"kind":"tower","team":0,"lane":"top","zone":"lane","slot":-1,"uid":"","def":"blau_top_outer","alive":true,"hp":6000.0,"max_hp":6000.0,"shield":0.0,"x":-24.921451568603516,"y":-12.715348243713379,"facing":0.0,"progress":0.0,"target":-1,"hits":0,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":3,"kind":"tower","team":0,"lane":"mid","zone":"lane","slot":-1,"uid":"","def":"blau_mid_inner","alive":true,"hp":7500.0,"max_hp":7500.0,"shield":0.0,"x":-11.427590370178223,"y":17.012392044067383,"facing":0.0,"progress":0.0,"target":-1,"hits":0,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":4,"kind":"tower","team":0,"lane":"mid","zone":"lane","slot":-1,"uid":"","def":"blau_mid_outer","alive":true,"hp":6000.0,"max_hp":6000.0,"shield":0.0,"x":-3.8433847427368164,"y":8.990991592407227,"facing":0.0,"progress":0.0,"target":-1,"hits":0,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":5,"kind":"tower","team":0,"lane":"bot","zone":"lane","slot":-1,"uid":"","def":"blau_bot_inner","alive":true,"hp":7500.0,"max_hp":7500.0,"shield":0.0,"x":-4.349228858947754,"y":31.034507751464844,"facing":0.0,"progress":0.0,"target":-1,"hits":0,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":6,"kind":"tower","team":0,"lane":"bot","zone":"lane","slot":-1,"uid":"","def":"blau_bot_outer","alive":true,"hp":6000.0,"max_hp":6000.0,"shield":0.0,"x":11.117134094238281,"y":28.989334106445313,"facing":0.0,"progress":0.0,"target":-1,"hits":0,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":7,"kind":"tower","team":0,"lane":"base","zone":"lane","slot":-1,"uid":"","def":"blau_base_1","alive":true,"hp":9000.0,"max_hp":9000.0,"shield":0.0,"x":-29.476999282836914,"y":24.023000717163086,"facing":0.0,"progress":0.0,"target":-1,"hits":0,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":8,"kind":"tower","team":0,"lane":"base","zone":"lane","slot":-1,"uid":"","def":"blau_base_2","alive":true,"hp":9000.0,"max_hp":9000.0,"shield":0.0,"x":-24.023000717163086,"y":29.476999282836914,"facing":0.0,"progress":0.0,"target":-1,"hits":0,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":9,"kind":"core","team":0,"lane":"base","zone":"lane","slot":-1,"uid":"","def":"blau_ancient","alive":true,"hp":12000.0,"max_hp":12000.0,"shield":0.0,"x":-30.0,"y":30.0,"facing":0.0,"progress":0.0,"target":-1,"hits":0,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":10,"kind":"tower","team":1,"lane":"top","zone":"lane","slot":-1,"uid":"","def":"rot_top_inner","alive":true,"hp":7500.0,"max_hp":7500.0,"shield":0.0,"x":4.5293378829956055,"y":-24.931251525878906,"facing":0.0,"progress":0.0,"target":-1,"hits":0,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":11,"kind":"tower","team":1,"lane":"top","zone":"lane","slot":-1,"uid":"","def":"rot_top_outer","alive":true,"hp":6000.0,"max_hp":6000.0,"shield":0.0,"x":-12.715348243713379,"y":-24.921451568603516,"facing":0.0,"progress":0.0,"target":-1,"hits":0,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":12,"kind":"tower","team":1,"lane":"mid","zone":"lane","slot":-1,"uid":"","def":"rot_mid_inner","alive":true,"hp":7500.0,"max_hp":7500.0,"shield":0.0,"x":17.012392044067383,"y":-11.427590370178223,"facing":0.0,"progress":0.0,"target":-1,"hits":0,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":13,"kind":"tower","team":1,"lane":"mid","zone":"lane","slot":-1,"uid":"","def":"rot_mid_outer","alive":true,"hp":6000.0,"max_hp":6000.0,"shield":0.0,"x":8.990991592407227,"y":-3.8433847427368164,"facing":0.0,"progress":0.0,"target":-1,"hits":0,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":14,"kind":"tower","team":1,"lane":"bot","zone":"lane","slot":-1,"uid":"","def":"rot_bot_inner","alive":true,"hp":7500.0,"max_hp":7500.0,"shield":0.0,"x":31.034507751464844,"y":-4.349228858947754,"facing":0.0,"progress":0.0,"target":-1,"hits":0,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":15,"kind":"tower","team":1,"lane":"bot","zone":"lane","slot":-1,"uid":"","def":"rot_bot_outer","alive":true,"hp":6000.0,"max_hp":6000.0,"shield":0.0,"x":28.989334106445313,"y":11.117134094238281,"facing":0.0,"progress":0.0,"target":-1,"hits":0,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":16,"kind":"tower","team":1,"lane":"base","zone":"lane","slot":-1,"uid":"","def":"rot_base_1","alive":true,"hp":9000.0,"max_hp":9000.0,"shield":0.0,"x":24.023000717163086,"y":-29.476999282836914,"facing":0.0,"progress":0.0,"target":-1,"hits":0,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":17,"kind":"tower","team":1,"lane":"base","zone":"lane","slot":-1,"uid":"","def":"rot_base_2","alive":true,"hp":9000.0,"max_hp":9000.0,"shield":0.0,"x":29.476999282836914,"y":-24.023000717163086,"facing":0.0,"progress":0.0,"target":-1,"hits":0,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":18,"kind":"core","team":1,"lane":"base","zone":"lane","slot":-1,"uid":"","def":"rot_ancient","alive":true,"hp":12000.0,"max_hp":12000.0,"shield":0.0,"x":30.0,"y":-30.0,"facing":0.0,"progress":0.0,"target":-1,"hits":0,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":19,"kind":"monster","team":0,"lane":"top","zone":"lane","slot":-1,"uid":"","def":"e01","alive":true,"hp":90.0,"max_hp":90.0,"shield":0.0,"x":-28.243892669677734,"y":10.502157211303711,"facing":-2.864119239296395,"progress":11.0,"target":-1,"hits":0,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":20,"kind":"monster","team":0,"lane":"top","zone":"lane","slot":-1,"uid":"","def":"e01","alive":true,"hp":90.0,"max_hp":90.0,"shield":0.0,"x":-26.993616104125977,"y":10.146052360534668,"facing":-2.864119239296395,"progress":11.0,"target":-1,"hits":0,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":21,"kind":"monster","team":0,"lane":"top","zone":"lane","slot":-1,"uid":"","def":"e01","alive":true,"hp":90.0,"max_hp":90.0,"shield":0.0,"x":-25.74333953857422,"y":9.789947509765625,"facing":-2.864119239296395,"progress":11.0,"target":-1,"hits":0,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":22,"kind":"monster","team":0,"lane":"mid","zone":"lane","slot":-1,"uid":"","def":"e01","alive":true,"hp":90.0,"max_hp":90.0,"shield":0.0,"x":-14.408708572387695,"y":13.32747745513916,"facing":2.3870002372622334,"progress":11.0,"target":-1,"hits":0,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":23,"kind":"monster","team":0,"lane":"mid","zone":"lane","slot":-1,"uid":"","def":"e01","alive":true,"hp":90.0,"max_hp":90.0,"shield":0.0,"x":-13.461592674255371,"y":14.21796703338623,"facing":2.3870002372622334,"progress":11.0,"target":-1,"hits":0,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":24,"kind":"monster","team":0,"lane":"mid","zone":"lane","slot":-1,"uid":"","def":"e01","alive":true,"hp":90.0,"max_hp":90.0,"shield":0.0,"x":-12.514476776123047,"y":15.1084566116333,"facing":2.3870002372622334,"progress":11.0,"target":-1,"hits":0,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":25,"kind":"monster","team":0,"lane":"bot","zone":"lane","slot":-1,"uid":"","def":"e01","alive":true,"hp":90.0,"max_hp":90.0,"shield":0.0,"x":-9.842267036437988,"y":25.94097137451172,"facing":1.4313591016628469,"progress":11.0,"target":-1,"hits":0,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":26,"kind":"monster","team":0,"lane":"bot","zone":"lane","slot":-1,"uid":"","def":"e01","alive":true,"hp":90.0,"max_hp":90.0,"shield":0.0,"x":-10.022948265075684,"y":27.22835350036621,"facing":1.4313591016628469,"progress":11.0,"target":-1,"hits":0,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":27,"kind":"monster","team":0,"lane":"bot","zone":"lane","slot":-1,"uid":"","def":"e01","alive":true,"hp":90.0,"max_hp":90.0,"shield":0.0,"x":-10.203629493713379,"y":28.515735626220703,"facing":1.4313591016628469,"progress":11.0,"target":-1,"hits":0,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":28,"kind":"monster","team":1,"lane":"top","zone":"lane","slot":-1,"uid":"","def":"e01","alive":true,"hp":90.0,"max_hp":90.0,"shield":0.0,"x":10.502157211303711,"y":-28.243892669677734,"facing":-1.8482697410882951,"progress":11.0,"target":-1,"hits":0,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":29,"kind":"monster","team":1,"lane":"top","zone":"lane","slot":-1,"uid":"","def":"e01","alive":true,"hp":90.0,"max_hp":90.0,"shield":0.0,"x":10.146052360534668,"y":-26.993616104125977,"facing":-1.8482697410882951,"progress":11.0,"target":-1,"hits":0,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":30,"kind":"monster","team":1,"lane":"top","zone":"lane","slot":-1,"uid":"","def":"e01","alive":true,"hp":90.0,"max_hp":90.0,"shield":0.0,"x":9.789947509765625,"y":-25.74333953857422,"facing":-1.8482697410882951,"progress":11.0,"target":-1,"hits":0,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":31,"kind":"monster","team":1,"lane":"mid","zone":"lane","slot":-1,"uid":"","def":"e01","alive":true,"hp":90.0,"max_hp":90.0,"shield":0.0,"x":13.32747745513916,"y":-14.408708572387695,"facing":-0.816203910467337,"progress":11.0,"target":-1,"hits":0,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":32,"kind":"monster","team":1,"lane":"mid","zone":"lane","slot":-1,"uid":"","def":"e01","alive":true,"hp":90.0,"max_hp":90.0,"shield":0.0,"x":14.21796703338623,"y":-13.461592674255371,"facing":-0.816203910467337,"progress":11.0,"target":-1,"hits":0,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":33,"kind":"monster","team":1,"lane":"mid","zone":"lane","slot":-1,"uid":"","def":"e01","alive":true,"hp":90.0,"max_hp":90.0,"shield":0.0,"x":15.1084566116333,"y":-12.514476776123047,"facing":-0.816203910467337,"progress":11.0,"target":-1,"hits":0,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":34,"kind":"monster","team":1,"lane":"bot","zone":"lane","slot":-1,"uid":"","def":"e01","alive":true,"hp":90.0,"max_hp":90.0,"shield":0.0,"x":25.94097137451172,"y":-9.842267036437988,"facing":0.13943722513204979,"progress":11.0,"target":-1,"hits":0,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":35,"kind":"monster","team":1,"lane":"bot","zone":"lane","slot":-1,"uid":"","def":"e01","alive":true,"hp":90.0,"max_hp":90.0,"shield":0.0,"x":27.22835350036621,"y":-10.022948265075684,"facing":0.13943722513204979,"progress":11.0,"target":-1,"hits":0,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":36,"kind":"monster","team":1,"lane":"bot","zone":"lane","slot":-1,"uid":"","def":"e01","alive":true,"hp":90.0,"max_hp":90.0,"shield":0.0,"x":28.515735626220703,"y":-10.203629493713379,"facing":0.13943722513204979,"progress":11.0,"target":-1,"hits":0,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":37,"kind":"troop","team":0,"lane":"grotto","zone":"grotto","slot":2,"uid":"p2-1","def":"g01","alive":true,"hp":260.0,"max_hp":260.0,"shield":0.0,"x":-13.305871963500977,"y":-8.454777717590332,"facing":2.261898072281642,"progress":0.0,"target":-1,"hits":0,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":38,"kind":"boss","team":2,"lane":"grotto","zone":"grotto","slot":-1,"uid":"","def":"e10","alive":true,"hp":3600.0,"max_hp":3600.0,"shield":0.0,"x":-15.0,"y":-15.0,"facing":-0.6911017454867453,"progress":0.0,"target":-1,"hits":0,"reached":false,"dormant":true,"effects":[],"dots":[]}]},{"label":"failed","phase":0,"round":2,"winner":-2,"end_note":"","players":[{"gold":308,"draft_gold":308,"ready":true,"earned":88,"spent":0,"next_seq":1,"roster":[],"hero":"","bookings":[],"new_bookings":[],"draft_roster":[],"draft_hero":"","boss_lane":"","undo":0},{"gold":308,"draft_gold":308,"ready":true,"earned":88,"spent":0,"next_seq":1,"roster":[],"hero":"","bookings":[],"new_bookings":[],"draft_roster":[],"draft_hero":"","boss_lane":"","undo":0},{"gold":463,"draft_gold":463,"ready":true,"earned":88,"spent":0,"next_seq":2,"roster":["p2-1|g01|bot|45"],"hero":"","bookings":[],"new_bookings":[],"draft_roster":["p2-1|g01|bot|45|false"],"draft_hero":"","boss_lane":"","undo":0},{"gold":308,"draft_gold":308,"ready":true,"earned":88,"spent":0,"next_seq":1,"roster":[],"hero":"","bookings":[],"new_bookings":[],"draft_roster":[],"draft_hero":"","boss_lane":"","undo":0},{"gold":308,"draft_gold":308,"ready":true,"earned":88,"spent":0,"next_seq":1,"roster":[],"hero":"","bookings":[],"new_bookings":[],"draft_roster":[],"draft_hero":"","boss_lane":"","undo":0},{"gold":308,"draft_gold":308,"ready":true,"earned":88,"spent":0,"next_seq":1,"roster":[],"hero":"","bookings":[],"new_bookings":[],"draft_roster":[],"draft_hero":"","boss_lane":"","undo":0}],"buildings":[7500.0,6000.0,7500.0,6000.0,7500.0,6000.0,9000.0,9000.0,12000.0,7500.0,6000.0,7500.0,6000.0,7500.0,6000.0,9000.0,9000.0,12000.0],"boss":{"next":1,"settled":1,"claim":""},"boss_log":["1|failed|-1||-1"],"announcements":[],"settlement":{"round":1,"gains":[18,18,18,18,18,18],"income":70,"lost":[],"end_reason":"cleared","combat_time":26.050000000000235,"boss":"failed","lane_kills":{"bot":6,"top":6,"mid":6},"xp":{}},"combat":{"round":1,"steps":521,"elapsed":26.050000000000235,"finished":true,"end_reason":"cleared","destroyed":[],"grotto":"failed|-1|0|true","grotto_boss":"true|false|38","grotto_boss_hp":3540.0,"events":19,"mobile":[0,0,1]},"events":[[1,117,5.849999999999987,0,"grotto","grotto","troop",37,"g01",0,"",15,[]],[2,248,12.400000000000041,0,"bot","lane","monster",25,"e01",6,"",13,[]],[3,248,12.400000000000041,1,"bot","lane","monster",34,"e01",6,"",13,[]],[4,278,13.900000000000063,0,"top","lane","monster",21,"e01",6,"",13,[]],[5,278,13.900000000000063,1,"top","lane","monster",30,"e01",6,"",13,[]],[6,319,15.950000000000092,0,"mid","lane","monster",22,"e01",6,"",13,[]],[7,319,15.950000000000092,0,"mid","lane","monster",23,"e01",6,"",13,[]],[8,319,15.950000000000092,0,"mid","lane","monster",24,"e01",6,"",13,[]],[9,319,15.950000000000092,1,"mid","lane","monster",31,"e01",6,"",13,[]],[10,319,15.950000000000092,1,"mid","lane","monster",32,"e01",6,"",13,[]],[11,319,15.950000000000092,1,"mid","lane","monster",33,"e01",6,"",13,[]],[12,393,19.650000000000144,0,"top","lane","monster",19,"e01",6,"",13,[]],[13,393,19.650000000000144,1,"top","lane","monster",28,"e01",6,"",13,[]],[14,490,24.500000000000213,0,"bot","lane","monster",26,"e01",6,"",13,[]],[15,490,24.500000000000213,1,"bot","lane","monster",35,"e01",6,"",13,[]],[16,510,25.500000000000227,0,"bot","lane","monster",27,"e01",6,"",13,[]],[17,510,25.500000000000227,1,"bot","lane","monster",36,"e01",6,"",13,[]],[18,521,26.050000000000235,0,"top","lane","monster",20,"e01",6,"",13,[]],[19,521,26.050000000000235,1,"top","lane","monster",29,"e01",6,"",13,[]]]},{"label":"second_attempt","phase":1,"round":2,"winner":-2,"end_note":"","players":[{"gold":308,"draft_gold":308,"ready":true,"earned":88,"spent":0,"next_seq":1,"roster":[],"hero":"","bookings":[],"new_bookings":[],"draft_roster":[],"draft_hero":"","boss_lane":"","undo":0},{"gold":308,"draft_gold":308,"ready":true,"earned":88,"spent":0,"next_seq":1,"roster":[],"hero":"","bookings":[],"new_bookings":[],"draft_roster":[],"draft_hero":"","boss_lane":"","undo":0},{"gold":463,"draft_gold":463,"ready":true,"earned":88,"spent":0,"next_seq":2,"roster":["p2-1|g01|grotto|45"],"hero":"","bookings":[],"new_bookings":[],"draft_roster":["p2-1|g01|grotto|45|false"],"draft_hero":"","boss_lane":"","undo":0},{"gold":308,"draft_gold":308,"ready":true,"earned":88,"spent":0,"next_seq":1,"roster":[],"hero":"","bookings":[],"new_bookings":[],"draft_roster":[],"draft_hero":"","boss_lane":"","undo":0},{"gold":308,"draft_gold":308,"ready":true,"earned":88,"spent":0,"next_seq":1,"roster":[],"hero":"","bookings":[],"new_bookings":[],"draft_roster":[],"draft_hero":"","boss_lane":"","undo":0},{"gold":308,"draft_gold":308,"ready":true,"earned":88,"spent":0,"next_seq":1,"roster":[],"hero":"","bookings":[],"new_bookings":[],"draft_roster":[],"draft_hero":"","boss_lane":"","undo":0}],"buildings":[7500.0,6000.0,7500.0,6000.0,7500.0,6000.0,9000.0,9000.0,12000.0,7500.0,6000.0,7500.0,6000.0,7500.0,6000.0,9000.0,9000.0,12000.0],"boss":{"next":1,"settled":1,"claim":""},"boss_log":["1|failed|-1||-1"],"announcements":[],"settlement":{"round":1,"gains":[18,18,18,18,18,18],"income":70,"lost":[],"end_reason":"cleared","combat_time":26.050000000000235,"boss":"failed","lane_kills":{"bot":6,"top":6,"mid":6},"xp":{}},"combat":{"round":2,"steps":0,"elapsed":0.0,"finished":false,"end_reason":"","destroyed":[],"grotto":"none|-1|-1|false","grotto_boss":"true|true|38","grotto_boss_hp":4001.4000000000005,"events":0,"mobile":[10,9,1]},"units":[{"id":1,"kind":"tower","team":0,"lane":"top","zone":"lane","slot":-1,"uid":"","def":"blau_top_inner","alive":true,"hp":7500.0,"max_hp":7500.0,"shield":0.0,"x":-24.931251525878906,"y":4.5293378829956055,"facing":0.0,"progress":0.0,"target":-1,"hits":0,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":2,"kind":"tower","team":0,"lane":"top","zone":"lane","slot":-1,"uid":"","def":"blau_top_outer","alive":true,"hp":6000.0,"max_hp":6000.0,"shield":0.0,"x":-24.921451568603516,"y":-12.715348243713379,"facing":0.0,"progress":0.0,"target":-1,"hits":0,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":3,"kind":"tower","team":0,"lane":"mid","zone":"lane","slot":-1,"uid":"","def":"blau_mid_inner","alive":true,"hp":7500.0,"max_hp":7500.0,"shield":0.0,"x":-11.427590370178223,"y":17.012392044067383,"facing":0.0,"progress":0.0,"target":-1,"hits":0,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":4,"kind":"tower","team":0,"lane":"mid","zone":"lane","slot":-1,"uid":"","def":"blau_mid_outer","alive":true,"hp":6000.0,"max_hp":6000.0,"shield":0.0,"x":-3.8433847427368164,"y":8.990991592407227,"facing":0.0,"progress":0.0,"target":-1,"hits":0,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":5,"kind":"tower","team":0,"lane":"bot","zone":"lane","slot":-1,"uid":"","def":"blau_bot_inner","alive":true,"hp":7500.0,"max_hp":7500.0,"shield":0.0,"x":-4.349228858947754,"y":31.034507751464844,"facing":0.0,"progress":0.0,"target":-1,"hits":0,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":6,"kind":"tower","team":0,"lane":"bot","zone":"lane","slot":-1,"uid":"","def":"blau_bot_outer","alive":true,"hp":6000.0,"max_hp":6000.0,"shield":0.0,"x":11.117134094238281,"y":28.989334106445313,"facing":0.0,"progress":0.0,"target":-1,"hits":0,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":7,"kind":"tower","team":0,"lane":"base","zone":"lane","slot":-1,"uid":"","def":"blau_base_1","alive":true,"hp":9000.0,"max_hp":9000.0,"shield":0.0,"x":-29.476999282836914,"y":24.023000717163086,"facing":0.0,"progress":0.0,"target":-1,"hits":0,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":8,"kind":"tower","team":0,"lane":"base","zone":"lane","slot":-1,"uid":"","def":"blau_base_2","alive":true,"hp":9000.0,"max_hp":9000.0,"shield":0.0,"x":-24.023000717163086,"y":29.476999282836914,"facing":0.0,"progress":0.0,"target":-1,"hits":0,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":9,"kind":"core","team":0,"lane":"base","zone":"lane","slot":-1,"uid":"","def":"blau_ancient","alive":true,"hp":12000.0,"max_hp":12000.0,"shield":0.0,"x":-30.0,"y":30.0,"facing":0.0,"progress":0.0,"target":-1,"hits":0,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":10,"kind":"tower","team":1,"lane":"top","zone":"lane","slot":-1,"uid":"","def":"rot_top_inner","alive":true,"hp":7500.0,"max_hp":7500.0,"shield":0.0,"x":4.5293378829956055,"y":-24.931251525878906,"facing":0.0,"progress":0.0,"target":-1,"hits":0,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":11,"kind":"tower","team":1,"lane":"top","zone":"lane","slot":-1,"uid":"","def":"rot_top_outer","alive":true,"hp":6000.0,"max_hp":6000.0,"shield":0.0,"x":-12.715348243713379,"y":-24.921451568603516,"facing":0.0,"progress":0.0,"target":-1,"hits":0,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":12,"kind":"tower","team":1,"lane":"mid","zone":"lane","slot":-1,"uid":"","def":"rot_mid_inner","alive":true,"hp":7500.0,"max_hp":7500.0,"shield":0.0,"x":17.012392044067383,"y":-11.427590370178223,"facing":0.0,"progress":0.0,"target":-1,"hits":0,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":13,"kind":"tower","team":1,"lane":"mid","zone":"lane","slot":-1,"uid":"","def":"rot_mid_outer","alive":true,"hp":6000.0,"max_hp":6000.0,"shield":0.0,"x":8.990991592407227,"y":-3.8433847427368164,"facing":0.0,"progress":0.0,"target":-1,"hits":0,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":14,"kind":"tower","team":1,"lane":"bot","zone":"lane","slot":-1,"uid":"","def":"rot_bot_inner","alive":true,"hp":7500.0,"max_hp":7500.0,"shield":0.0,"x":31.034507751464844,"y":-4.349228858947754,"facing":0.0,"progress":0.0,"target":-1,"hits":0,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":15,"kind":"tower","team":1,"lane":"bot","zone":"lane","slot":-1,"uid":"","def":"rot_bot_outer","alive":true,"hp":6000.0,"max_hp":6000.0,"shield":0.0,"x":28.989334106445313,"y":11.117134094238281,"facing":0.0,"progress":0.0,"target":-1,"hits":0,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":16,"kind":"tower","team":1,"lane":"base","zone":"lane","slot":-1,"uid":"","def":"rot_base_1","alive":true,"hp":9000.0,"max_hp":9000.0,"shield":0.0,"x":24.023000717163086,"y":-29.476999282836914,"facing":0.0,"progress":0.0,"target":-1,"hits":0,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":17,"kind":"tower","team":1,"lane":"base","zone":"lane","slot":-1,"uid":"","def":"rot_base_2","alive":true,"hp":9000.0,"max_hp":9000.0,"shield":0.0,"x":29.476999282836914,"y":-24.023000717163086,"facing":0.0,"progress":0.0,"target":-1,"hits":0,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":18,"kind":"core","team":1,"lane":"base","zone":"lane","slot":-1,"uid":"","def":"rot_ancient","alive":true,"hp":12000.0,"max_hp":12000.0,"shield":0.0,"x":30.0,"y":-30.0,"facing":0.0,"progress":0.0,"target":-1,"hits":0,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":19,"kind":"monster","team":0,"lane":"top","zone":"lane","slot":-1,"uid":"","def":"e01","alive":true,"hp":100.03500000000001,"max_hp":100.03500000000001,"shield":0.0,"x":-28.243892669677734,"y":10.502157211303711,"facing":-2.864119239296395,"progress":11.0,"target":-1,"hits":0,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":20,"kind":"monster","team":0,"lane":"top","zone":"lane","slot":-1,"uid":"","def":"e01","alive":true,"hp":100.03500000000001,"max_hp":100.03500000000001,"shield":0.0,"x":-26.993616104125977,"y":10.146052360534668,"facing":-2.864119239296395,"progress":11.0,"target":-1,"hits":0,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":21,"kind":"monster","team":0,"lane":"top","zone":"lane","slot":-1,"uid":"","def":"e01","alive":true,"hp":100.03500000000001,"max_hp":100.03500000000001,"shield":0.0,"x":-25.74333953857422,"y":9.789947509765625,"facing":-2.864119239296395,"progress":11.0,"target":-1,"hits":0,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":22,"kind":"monster","team":0,"lane":"mid","zone":"lane","slot":-1,"uid":"","def":"e01","alive":true,"hp":100.03500000000001,"max_hp":100.03500000000001,"shield":0.0,"x":-14.408708572387695,"y":13.32747745513916,"facing":2.3870002372622334,"progress":11.0,"target":-1,"hits":0,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":23,"kind":"monster","team":0,"lane":"mid","zone":"lane","slot":-1,"uid":"","def":"e01","alive":true,"hp":100.03500000000001,"max_hp":100.03500000000001,"shield":0.0,"x":-13.461592674255371,"y":14.21796703338623,"facing":2.3870002372622334,"progress":11.0,"target":-1,"hits":0,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":24,"kind":"monster","team":0,"lane":"mid","zone":"lane","slot":-1,"uid":"","def":"e01","alive":true,"hp":100.03500000000001,"max_hp":100.03500000000001,"shield":0.0,"x":-12.514476776123047,"y":15.1084566116333,"facing":2.3870002372622334,"progress":11.0,"target":-1,"hits":0,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":25,"kind":"monster","team":0,"lane":"bot","zone":"lane","slot":-1,"uid":"","def":"e01","alive":true,"hp":100.03500000000001,"max_hp":100.03500000000001,"shield":0.0,"x":-9.842267036437988,"y":25.94097137451172,"facing":1.4313591016628469,"progress":11.0,"target":-1,"hits":0,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":26,"kind":"monster","team":0,"lane":"bot","zone":"lane","slot":-1,"uid":"","def":"e01","alive":true,"hp":100.03500000000001,"max_hp":100.03500000000001,"shield":0.0,"x":-10.022948265075684,"y":27.22835350036621,"facing":1.4313591016628469,"progress":11.0,"target":-1,"hits":0,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":27,"kind":"monster","team":0,"lane":"bot","zone":"lane","slot":-1,"uid":"","def":"e01","alive":true,"hp":100.03500000000001,"max_hp":100.03500000000001,"shield":0.0,"x":-10.203629493713379,"y":28.515735626220703,"facing":1.4313591016628469,"progress":11.0,"target":-1,"hits":0,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":28,"kind":"monster","team":1,"lane":"top","zone":"lane","slot":-1,"uid":"","def":"e01","alive":true,"hp":100.03500000000001,"max_hp":100.03500000000001,"shield":0.0,"x":10.502157211303711,"y":-28.243892669677734,"facing":-1.8482697410882951,"progress":11.0,"target":-1,"hits":0,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":29,"kind":"monster","team":1,"lane":"top","zone":"lane","slot":-1,"uid":"","def":"e01","alive":true,"hp":100.03500000000001,"max_hp":100.03500000000001,"shield":0.0,"x":10.146052360534668,"y":-26.993616104125977,"facing":-1.8482697410882951,"progress":11.0,"target":-1,"hits":0,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":30,"kind":"monster","team":1,"lane":"top","zone":"lane","slot":-1,"uid":"","def":"e01","alive":true,"hp":100.03500000000001,"max_hp":100.03500000000001,"shield":0.0,"x":9.789947509765625,"y":-25.74333953857422,"facing":-1.8482697410882951,"progress":11.0,"target":-1,"hits":0,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":31,"kind":"monster","team":1,"lane":"mid","zone":"lane","slot":-1,"uid":"","def":"e01","alive":true,"hp":100.03500000000001,"max_hp":100.03500000000001,"shield":0.0,"x":13.32747745513916,"y":-14.408708572387695,"facing":-0.816203910467337,"progress":11.0,"target":-1,"hits":0,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":32,"kind":"monster","team":1,"lane":"mid","zone":"lane","slot":-1,"uid":"","def":"e01","alive":true,"hp":100.03500000000001,"max_hp":100.03500000000001,"shield":0.0,"x":14.21796703338623,"y":-13.461592674255371,"facing":-0.816203910467337,"progress":11.0,"target":-1,"hits":0,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":33,"kind":"monster","team":1,"lane":"mid","zone":"lane","slot":-1,"uid":"","def":"e01","alive":true,"hp":100.03500000000001,"max_hp":100.03500000000001,"shield":0.0,"x":15.1084566116333,"y":-12.514476776123047,"facing":-0.816203910467337,"progress":11.0,"target":-1,"hits":0,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":34,"kind":"monster","team":1,"lane":"bot","zone":"lane","slot":-1,"uid":"","def":"e01","alive":true,"hp":100.03500000000001,"max_hp":100.03500000000001,"shield":0.0,"x":25.94097137451172,"y":-9.842267036437988,"facing":0.13943722513204979,"progress":11.0,"target":-1,"hits":0,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":35,"kind":"monster","team":1,"lane":"bot","zone":"lane","slot":-1,"uid":"","def":"e01","alive":true,"hp":100.03500000000001,"max_hp":100.03500000000001,"shield":0.0,"x":27.22835350036621,"y":-10.022948265075684,"facing":0.13943722513204979,"progress":11.0,"target":-1,"hits":0,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":36,"kind":"monster","team":1,"lane":"bot","zone":"lane","slot":-1,"uid":"","def":"e01","alive":true,"hp":100.03500000000001,"max_hp":100.03500000000001,"shield":0.0,"x":28.515735626220703,"y":-10.203629493713379,"facing":0.13943722513204979,"progress":11.0,"target":-1,"hits":0,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":37,"kind":"troop","team":0,"lane":"grotto","zone":"grotto","slot":2,"uid":"p2-1","def":"g01","alive":true,"hp":260.0,"max_hp":260.0,"shield":0.0,"x":-13.305871963500977,"y":-8.454777717590332,"facing":2.261898072281642,"progress":0.0,"target":-1,"hits":0,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":38,"kind":"boss","team":2,"lane":"grotto","zone":"grotto","slot":-1,"uid":"","def":"e10","alive":true,"hp":4001.4000000000005,"max_hp":4001.4000000000005,"shield":0.0,"x":-15.0,"y":-15.0,"facing":-0.6911017454867453,"progress":0.0,"target":-1,"hits":0,"reached":false,"dormant":true,"effects":[],"dots":[]}]},{"label":"failed_again","phase":0,"round":3,"winner":-2,"end_note":"","players":[{"gold":400,"draft_gold":400,"ready":true,"earned":180,"spent":0,"next_seq":1,"roster":[],"hero":"","bookings":[],"new_bookings":[],"draft_roster":[],"draft_hero":"","boss_lane":"","undo":0},{"gold":400,"draft_gold":400,"ready":true,"earned":180,"spent":0,"next_seq":1,"roster":[],"hero":"","bookings":[],"new_bookings":[],"draft_roster":[],"draft_hero":"","boss_lane":"","undo":0},{"gold":555,"draft_gold":555,"ready":true,"earned":180,"spent":0,"next_seq":2,"roster":["p2-1|g01|bot|45"],"hero":"","bookings":[],"new_bookings":[],"draft_roster":["p2-1|g01|bot|45|false"],"draft_hero":"","boss_lane":"","undo":0},{"gold":400,"draft_gold":400,"ready":true,"earned":180,"spent":0,"next_seq":1,"roster":[],"hero":"","bookings":[],"new_bookings":[],"draft_roster":[],"draft_hero":"","boss_lane":"","undo":0},{"gold":400,"draft_gold":400,"ready":true,"earned":180,"spent":0,"next_seq":1,"roster":[],"hero":"","bookings":[],"new_bookings":[],"draft_roster":[],"draft_hero":"","boss_lane":"","undo":0},{"gold":400,"draft_gold":400,"ready":true,"earned":180,"spent":0,"next_seq":1,"roster":[],"hero":"","bookings":[],"new_bookings":[],"draft_roster":[],"draft_hero":"","boss_lane":"","undo":0}],"buildings":[7500.0,6000.0,7500.0,6000.0,7500.0,6000.0,9000.0,9000.0,12000.0,7500.0,6000.0,7500.0,6000.0,7500.0,6000.0,9000.0,9000.0,12000.0],"boss":{"next":1,"settled":2,"claim":""},"boss_log":["1|failed|-1||-1","2|failed|-1||-1"],"announcements":[],"settlement":{"round":2,"gains":[18,18,18,18,18,18],"income":74,"lost":[],"end_reason":"cleared","combat_time":26.050000000000235,"boss":"failed","lane_kills":{"bot":6,"top":6,"mid":6},"xp":{}},"combat":{"round":2,"steps":521,"elapsed":26.050000000000235,"finished":true,"end_reason":"cleared","destroyed":[],"grotto":"failed|-1|0|true","grotto_boss":"true|false|38","grotto_boss_hp":3941.4000000000005,"events":19,"mobile":[0,0,1]},"events":[[1,117,5.849999999999987,0,"grotto","grotto","troop",37,"g01",0,"",15,[]],[2,248,12.400000000000041,0,"bot","lane","monster",25,"e01",6,"",14,[]],[3,248,12.400000000000041,1,"bot","lane","monster",34,"e01",6,"",14,[]],[4,278,13.900000000000063,0,"top","lane","monster",21,"e01",6,"",14,[]],[5,278,13.900000000000063,1,"top","lane","monster",30,"e01",6,"",14,[]],[6,319,15.950000000000092,0,"mid","lane","monster",22,"e01",6,"",14,[]],[7,319,15.950000000000092,0,"mid","lane","monster",23,"e01",6,"",14,[]],[8,319,15.950000000000092,0,"mid","lane","monster",24,"e01",6,"",14,[]],[9,319,15.950000000000092,1,"mid","lane","monster",31,"e01",6,"",14,[]],[10,319,15.950000000000092,1,"mid","lane","monster",32,"e01",6,"",14,[]],[11,319,15.950000000000092,1,"mid","lane","monster",33,"e01",6,"",14,[]],[12,393,19.650000000000144,0,"top","lane","monster",19,"e01",6,"",14,[]],[13,393,19.650000000000144,1,"top","lane","monster",28,"e01",6,"",14,[]],[14,490,24.500000000000213,0,"bot","lane","monster",26,"e01",6,"",14,[]],[15,490,24.500000000000213,1,"bot","lane","monster",35,"e01",6,"",14,[]],[16,510,25.500000000000227,0,"bot","lane","monster",27,"e01",6,"",14,[]],[17,510,25.500000000000227,1,"bot","lane","monster",36,"e01",6,"",14,[]],[18,521,26.050000000000235,0,"top","lane","monster",20,"e01",6,"",14,[]],[19,521,26.050000000000235,1,"top","lane","monster",29,"e01",6,"",14,[]]]}],"results":[["cmd",2,"buy",true,"Kohlenbeißer gekauft."],["cmd",2,"assign",true,"In die Bossgrotte entsandt."],["begin",-1,"",true,""],["cmd",2,"assign",true,"In die Bossgrotte entsandt."],["begin",-1,"",true,""]]},"grotto_contested":{"title":"Umkämpfte Grotte: zwei Expeditionen, Boss ruht, erwacht unberührt, Sieger erhält Anspruch","snapshots":[{"label":"dormant","phase":1,"round":1,"winner":-2,"end_note":"","players":[{"gold":220,"draft_gold":220,"ready":true,"earned":0,"spent":0,"next_seq":1,"roster":[],"hero":"","bookings":[],"new_bookings":[],"draft_roster":[],"draft_hero":"","boss_lane":"","undo":0},{"gold":5365,"draft_gold":5365,"ready":true,"earned":0,"spent":0,"next_seq":6,"roster":["p1-1|w04|grotto|230","p1-2|w04|grotto|230","p1-3|w02|grotto|150","p1-4|w06|grotto|195","p1-5|w01|mid|50"],"hero":"","bookings":[],"new_bookings":[],"draft_roster":["p1-1|w04|grotto|230|true","p1-2|w04|grotto|230|true","p1-3|w02|grotto|150|true","p1-4|w06|grotto|195|true","p1-5|w01|mid|50|true"],"draft_hero":"","boss_lane":"","undo":0},{"gold":220,"draft_gold":220,"ready":true,"earned":0,"spent":0,"next_seq":1,"roster":[],"hero":"","bookings":[],"new_bookings":[],"draft_roster":[],"draft_hero":"","boss_lane":"","undo":0},{"gold":220,"draft_gold":220,"ready":true,"earned":0,"spent":0,"next_seq":1,"roster":[],"hero":"","bookings":[],"new_bookings":[],"draft_roster":[],"draft_hero":"","boss_lane":"","undo":0},{"gold":6000,"draft_gold":6000,"ready":true,"earned":0,"spent":0,"next_seq":2,"roster":["p4-1|g04|grotto|220"],"hero":"","bookings":[],"new_bookings":[],"draft_roster":["p4-1|g04|grotto|220|true"],"draft_hero":"","boss_lane":"","undo":0},{"gold":220,"draft_gold":220,"ready":true,"earned":0,"spent":0,"next_seq":1,"roster":[],"hero":"","bookings":[],"new_bookings":[],"draft_roster":[],"draft_hero":"","boss_lane":"","undo":0}],"buildings":[7500.0,6000.0,7500.0,6000.0,7500.0,6000.0,9000.0,9000.0,12000.0,7500.0,6000.0,7500.0,6000.0,7500.0,6000.0,9000.0,9000.0,12000.0],"boss":{"next":1,"settled":0,"claim":""},"boss_log":[],"announcements":[],"settlement":null,"combat":{"round":1,"steps":0,"elapsed":0.0,"finished":false,"end_reason":"","destroyed":[],"grotto":"none|-1|-1|false","grotto_boss":"true|true|43","grotto_boss_hp":3600.0,"events":0,"mobile":[14,10,1]},"units":[{"id":1,"kind":"tower","team":0,"lane":"top","zone":"lane","slot":-1,"uid":"","def":"blau_top_inner","alive":true,"hp":7500.0,"max_hp":7500.0,"shield":0.0,"x":-24.931251525878906,"y":4.5293378829956055,"facing":0.0,"progress":0.0,"target":-1,"hits":0,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":2,"kind":"tower","team":0,"lane":"top","zone":"lane","slot":-1,"uid":"","def":"blau_top_outer","alive":true,"hp":6000.0,"max_hp":6000.0,"shield":0.0,"x":-24.921451568603516,"y":-12.715348243713379,"facing":0.0,"progress":0.0,"target":-1,"hits":0,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":3,"kind":"tower","team":0,"lane":"mid","zone":"lane","slot":-1,"uid":"","def":"blau_mid_inner","alive":true,"hp":7500.0,"max_hp":7500.0,"shield":0.0,"x":-11.427590370178223,"y":17.012392044067383,"facing":0.0,"progress":0.0,"target":-1,"hits":0,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":4,"kind":"tower","team":0,"lane":"mid","zone":"lane","slot":-1,"uid":"","def":"blau_mid_outer","alive":true,"hp":6000.0,"max_hp":6000.0,"shield":0.0,"x":-3.8433847427368164,"y":8.990991592407227,"facing":0.0,"progress":0.0,"target":-1,"hits":0,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":5,"kind":"tower","team":0,"lane":"bot","zone":"lane","slot":-1,"uid":"","def":"blau_bot_inner","alive":true,"hp":7500.0,"max_hp":7500.0,"shield":0.0,"x":-4.349228858947754,"y":31.034507751464844,"facing":0.0,"progress":0.0,"target":-1,"hits":0,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":6,"kind":"tower","team":0,"lane":"bot","zone":"lane","slot":-1,"uid":"","def":"blau_bot_outer","alive":true,"hp":6000.0,"max_hp":6000.0,"shield":0.0,"x":11.117134094238281,"y":28.989334106445313,"facing":0.0,"progress":0.0,"target":-1,"hits":0,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":7,"kind":"tower","team":0,"lane":"base","zone":"lane","slot":-1,"uid":"","def":"blau_base_1","alive":true,"hp":9000.0,"max_hp":9000.0,"shield":0.0,"x":-29.476999282836914,"y":24.023000717163086,"facing":0.0,"progress":0.0,"target":-1,"hits":0,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":8,"kind":"tower","team":0,"lane":"base","zone":"lane","slot":-1,"uid":"","def":"blau_base_2","alive":true,"hp":9000.0,"max_hp":9000.0,"shield":0.0,"x":-24.023000717163086,"y":29.476999282836914,"facing":0.0,"progress":0.0,"target":-1,"hits":0,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":9,"kind":"core","team":0,"lane":"base","zone":"lane","slot":-1,"uid":"","def":"blau_ancient","alive":true,"hp":12000.0,"max_hp":12000.0,"shield":0.0,"x":-30.0,"y":30.0,"facing":0.0,"progress":0.0,"target":-1,"hits":0,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":10,"kind":"tower","team":1,"lane":"top","zone":"lane","slot":-1,"uid":"","def":"rot_top_inner","alive":true,"hp":7500.0,"max_hp":7500.0,"shield":0.0,"x":4.5293378829956055,"y":-24.931251525878906,"facing":0.0,"progress":0.0,"target":-1,"hits":0,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":11,"kind":"tower","team":1,"lane":"top","zone":"lane","slot":-1,"uid":"","def":"rot_top_outer","alive":true,"hp":6000.0,"max_hp":6000.0,"shield":0.0,"x":-12.715348243713379,"y":-24.921451568603516,"facing":0.0,"progress":0.0,"target":-1,"hits":0,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":12,"kind":"tower","team":1,"lane":"mid","zone":"lane","slot":-1,"uid":"","def":"rot_mid_inner","alive":true,"hp":7500.0,"max_hp":7500.0,"shield":0.0,"x":17.012392044067383,"y":-11.427590370178223,"facing":0.0,"progress":0.0,"target":-1,"hits":0,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":13,"kind":"tower","team":1,"lane":"mid","zone":"lane","slot":-1,"uid":"","def":"rot_mid_outer","alive":true,"hp":6000.0,"max_hp":6000.0,"shield":0.0,"x":8.990991592407227,"y":-3.8433847427368164,"facing":0.0,"progress":0.0,"target":-1,"hits":0,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":14,"kind":"tower","team":1,"lane":"bot","zone":"lane","slot":-1,"uid":"","def":"rot_bot_inner","alive":true,"hp":7500.0,"max_hp":7500.0,"shield":0.0,"x":31.034507751464844,"y":-4.349228858947754,"facing":0.0,"progress":0.0,"target":-1,"hits":0,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":15,"kind":"tower","team":1,"lane":"bot","zone":"lane","slot":-1,"uid":"","def":"rot_bot_outer","alive":true,"hp":6000.0,"max_hp":6000.0,"shield":0.0,"x":28.989334106445313,"y":11.117134094238281,"facing":0.0,"progress":0.0,"target":-1,"hits":0,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":16,"kind":"tower","team":1,"lane":"base","zone":"lane","slot":-1,"uid":"","def":"rot_base_1","alive":true,"hp":9000.0,"max_hp":9000.0,"shield":0.0,"x":24.023000717163086,"y":-29.476999282836914,"facing":0.0,"progress":0.0,"target":-1,"hits":0,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":17,"kind":"tower","team":1,"lane":"base","zone":"lane","slot":-1,"uid":"","def":"rot_base_2","alive":true,"hp":9000.0,"max_hp":9000.0,"shield":0.0,"x":29.476999282836914,"y":-24.023000717163086,"facing":0.0,"progress":0.0,"target":-1,"hits":0,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":18,"kind":"core","team":1,"lane":"base","zone":"lane","slot":-1,"uid":"","def":"rot_ancient","alive":true,"hp":12000.0,"max_hp":12000.0,"shield":0.0,"x":30.0,"y":-30.0,"facing":0.0,"progress":0.0,"target":-1,"hits":0,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":19,"kind":"monster","team":0,"lane":"top","zone":"lane","slot":-1,"uid":"","def":"e01","alive":true,"hp":90.0,"max_hp":90.0,"shield":0.0,"x":-28.243892669677734,"y":10.502157211303711,"facing":-2.864119239296395,"progress":11.0,"target":-1,"hits":0,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":20,"kind":"monster","team":0,"lane":"top","zone":"lane","slot":-1,"uid":"","def":"e01","alive":true,"hp":90.0,"max_hp":90.0,"shield":0.0,"x":-26.993616104125977,"y":10.146052360534668,"facing":-2.864119239296395,"progress":11.0,"target":-1,"hits":0,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":21,"kind":"monster","team":0,"lane":"top","zone":"lane","slot":-1,"uid":"","def":"e01","alive":true,"hp":90.0,"max_hp":90.0,"shield":0.0,"x":-25.74333953857422,"y":9.789947509765625,"facing":-2.864119239296395,"progress":11.0,"target":-1,"hits":0,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":22,"kind":"monster","team":0,"lane":"mid","zone":"lane","slot":-1,"uid":"","def":"e01","alive":true,"hp":90.0,"max_hp":90.0,"shield":0.0,"x":-14.408708572387695,"y":13.32747745513916,"facing":2.3870002372622334,"progress":11.0,"target":-1,"hits":0,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":23,"kind":"monster","team":0,"lane":"mid","zone":"lane","slot":-1,"uid":"","def":"e01","alive":true,"hp":90.0,"max_hp":90.0,"shield":0.0,"x":-13.461592674255371,"y":14.21796703338623,"facing":2.3870002372622334,"progress":11.0,"target":-1,"hits":0,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":24,"kind":"monster","team":0,"lane":"mid","zone":"lane","slot":-1,"uid":"","def":"e01","alive":true,"hp":90.0,"max_hp":90.0,"shield":0.0,"x":-12.514476776123047,"y":15.1084566116333,"facing":2.3870002372622334,"progress":11.0,"target":-1,"hits":0,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":25,"kind":"monster","team":0,"lane":"bot","zone":"lane","slot":-1,"uid":"","def":"e01","alive":true,"hp":90.0,"max_hp":90.0,"shield":0.0,"x":-9.842267036437988,"y":25.94097137451172,"facing":1.4313591016628469,"progress":11.0,"target":-1,"hits":0,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":26,"kind":"monster","team":0,"lane":"bot","zone":"lane","slot":-1,"uid":"","def":"e01","alive":true,"hp":90.0,"max_hp":90.0,"shield":0.0,"x":-10.022948265075684,"y":27.22835350036621,"facing":1.4313591016628469,"progress":11.0,"target":-1,"hits":0,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":27,"kind":"monster","team":0,"lane":"bot","zone":"lane","slot":-1,"uid":"","def":"e01","alive":true,"hp":90.0,"max_hp":90.0,"shield":0.0,"x":-10.203629493713379,"y":28.515735626220703,"facing":1.4313591016628469,"progress":11.0,"target":-1,"hits":0,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":28,"kind":"monster","team":1,"lane":"top","zone":"lane","slot":-1,"uid":"","def":"e01","alive":true,"hp":90.0,"max_hp":90.0,"shield":0.0,"x":10.502157211303711,"y":-28.243892669677734,"facing":-1.8482697410882951,"progress":11.0,"target":-1,"hits":0,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":29,"kind":"monster","team":1,"lane":"top","zone":"lane","slot":-1,"uid":"","def":"e01","alive":true,"hp":90.0,"max_hp":90.0,"shield":0.0,"x":10.146052360534668,"y":-26.993616104125977,"facing":-1.8482697410882951,"progress":11.0,"target":-1,"hits":0,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":30,"kind":"monster","team":1,"lane":"top","zone":"lane","slot":-1,"uid":"","def":"e01","alive":true,"hp":90.0,"max_hp":90.0,"shield":0.0,"x":9.789947509765625,"y":-25.74333953857422,"facing":-1.8482697410882951,"progress":11.0,"target":-1,"hits":0,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":31,"kind":"monster","team":1,"lane":"mid","zone":"lane","slot":-1,"uid":"","def":"e01","alive":true,"hp":90.0,"max_hp":90.0,"shield":0.0,"x":13.32747745513916,"y":-14.408708572387695,"facing":-0.816203910467337,"progress":11.0,"target":-1,"hits":0,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":32,"kind":"monster","team":1,"lane":"mid","zone":"lane","slot":-1,"uid":"","def":"e01","alive":true,"hp":90.0,"max_hp":90.0,"shield":0.0,"x":14.21796703338623,"y":-13.461592674255371,"facing":-0.816203910467337,"progress":11.0,"target":-1,"hits":0,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":33,"kind":"monster","team":1,"lane":"mid","zone":"lane","slot":-1,"uid":"","def":"e01","alive":true,"hp":90.0,"max_hp":90.0,"shield":0.0,"x":15.1084566116333,"y":-12.514476776123047,"facing":-0.816203910467337,"progress":11.0,"target":-1,"hits":0,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":34,"kind":"monster","team":1,"lane":"bot","zone":"lane","slot":-1,"uid":"","def":"e01","alive":true,"hp":90.0,"max_hp":90.0,"shield":0.0,"x":25.94097137451172,"y":-9.842267036437988,"facing":0.13943722513204979,"progress":11.0,"target":-1,"hits":0,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":35,"kind":"monster","team":1,"lane":"bot","zone":"lane","slot":-1,"uid":"","def":"e01","alive":true,"hp":90.0,"max_hp":90.0,"shield":0.0,"x":27.22835350036621,"y":-10.022948265075684,"facing":0.13943722513204979,"progress":11.0,"target":-1,"hits":0,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":36,"kind":"monster","team":1,"lane":"bot","zone":"lane","slot":-1,"uid":"","def":"e01","alive":true,"hp":90.0,"max_hp":90.0,"shield":0.0,"x":28.515735626220703,"y":-10.203629493713379,"facing":0.13943722513204979,"progress":11.0,"target":-1,"hits":0,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":37,"kind":"troop","team":0,"lane":"mid","zone":"lane","slot":1,"uid":"p1-5","def":"w01","alive":true,"hp":290.0,"max_hp":290.0,"shield":0.0,"x":-17.386140823364258,"y":15.645247459411621,"facing":2.347786769279204,"progress":7.2,"target":-1,"hits":0,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":38,"kind":"troop","team":0,"lane":"grotto","zone":"grotto","slot":1,"uid":"p1-1","def":"w04","alive":true,"hp":1560.0,"max_hp":1560.0,"shield":0.0,"x":-13.305871963500977,"y":-8.454777717590332,"facing":2.261898072281642,"progress":0.0,"target":-1,"hits":0,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":39,"kind":"troop","team":0,"lane":"grotto","zone":"grotto","slot":1,"uid":"p1-2","def":"w04","alive":true,"hp":1560.0,"max_hp":1560.0,"shield":0.0,"x":-12.300000190734863,"y":-8.899999618530273,"facing":2.261898072281642,"progress":0.0,"target":-1,"hits":0,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":40,"kind":"troop","team":0,"lane":"grotto","zone":"grotto","slot":1,"uid":"p1-3","def":"w02","alive":true,"hp":800.0,"max_hp":800.0,"shield":0.0,"x":-11.29412841796875,"y":-9.345221519470215,"facing":2.261898072281642,"progress":0.0,"target":-1,"hits":0,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":41,"kind":"troop","team":0,"lane":"grotto","zone":"grotto","slot":1,"uid":"p1-4","def":"w06","alive":true,"hp":630.0,"max_hp":630.0,"shield":0.0,"x":-12.820175170898438,"y":-7.357463359832764,"facing":2.261898072281642,"progress":0.0,"target":-1,"hits":0,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":42,"kind":"troop","team":1,"lane":"grotto","zone":"grotto","slot":4,"uid":"p4-1","def":"g04","alive":true,"hp":1650.0,"max_hp":1650.0,"shield":0.0,"x":-8.454777717590332,"y":-13.305871963500977,"facing":-0.6911017454867453,"progress":0.0,"target":-1,"hits":0,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":43,"kind":"boss","team":2,"lane":"grotto","zone":"grotto","slot":-1,"uid":"","def":"e10","alive":true,"hp":3600.0,"max_hp":3600.0,"shield":0.0,"x":-15.0,"y":-15.0,"facing":-0.6911017454867453,"progress":0.0,"target":-1,"hits":0,"reached":false,"dormant":true,"effects":[],"dots":[]}]},{"label":"t15","phase":1,"round":1,"winner":-2,"end_note":"","players":[{"gold":220,"draft_gold":220,"ready":true,"earned":0,"spent":0,"next_seq":1,"roster":[],"hero":"","bookings":[],"new_bookings":[],"draft_roster":[],"draft_hero":"","boss_lane":"","undo":0},{"gold":5365,"draft_gold":5365,"ready":true,"earned":0,"spent":0,"next_seq":6,"roster":["p1-1|w04|grotto|230","p1-2|w04|grotto|230","p1-3|w02|grotto|150","p1-4|w06|grotto|195","p1-5|w01|mid|50"],"hero":"","bookings":[],"new_bookings":[],"draft_roster":["p1-1|w04|grotto|230|true","p1-2|w04|grotto|230|true","p1-3|w02|grotto|150|true","p1-4|w06|grotto|195|true","p1-5|w01|mid|50|true"],"draft_hero":"","boss_lane":"","undo":0},{"gold":220,"draft_gold":220,"ready":true,"earned":0,"spent":0,"next_seq":1,"roster":[],"hero":"","bookings":[],"new_bookings":[],"draft_roster":[],"draft_hero":"","boss_lane":"","undo":0},{"gold":220,"draft_gold":220,"ready":true,"earned":0,"spent":0,"next_seq":1,"roster":[],"hero":"","bookings":[],"new_bookings":[],"draft_roster":[],"draft_hero":"","boss_lane":"","undo":0},{"gold":6000,"draft_gold":6000,"ready":true,"earned":0,"spent":0,"next_seq":2,"roster":["p4-1|g04|grotto|220"],"hero":"","bookings":[],"new_bookings":[],"draft_roster":["p4-1|g04|grotto|220|true"],"draft_hero":"","boss_lane":"","undo":0},{"gold":220,"draft_gold":220,"ready":true,"earned":0,"spent":0,"next_seq":1,"roster":[],"hero":"","bookings":[],"new_bookings":[],"draft_roster":[],"draft_hero":"","boss_lane":"","undo":0}],"buildings":[7500.0,6000.0,7500.0,6000.0,7500.0,6000.0,9000.0,9000.0,12000.0,7500.0,6000.0,7500.0,6000.0,7500.0,6000.0,9000.0,9000.0,12000.0],"boss":{"next":1,"settled":0,"claim":""},"boss_log":[],"announcements":[],"settlement":null,"combat":{"round":1,"steps":300,"elapsed":15.000000000000078,"finished":false,"end_reason":"","destroyed":[],"grotto":"none|-1|0|false","grotto_boss":"true|false|43","grotto_boss_hp":3104.3999999999987,"events":10,"mobile":[10,4,1]},"units":[{"id":1,"kind":"tower","team":0,"lane":"top","zone":"lane","slot":-1,"uid":"","def":"blau_top_inner","alive":true,"hp":7500.0,"max_hp":7500.0,"shield":0.0,"x":-24.931251525878906,"y":4.5293378829956055,"facing":0.0,"progress":0.0,"target":-1,"hits":0,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":2,"kind":"tower","team":0,"lane":"top","zone":"lane","slot":-1,"uid":"","def":"blau_top_outer","alive":true,"hp":6000.0,"max_hp":6000.0,"shield":0.0,"x":-24.921451568603516,"y":-12.715348243713379,"facing":0.0,"progress":0.0,"target":-1,"hits":0,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":3,"kind":"tower","team":0,"lane":"mid","zone":"lane","slot":-1,"uid":"","def":"blau_mid_inner","alive":true,"hp":7500.0,"max_hp":7500.0,"shield":0.0,"x":-11.427590370178223,"y":17.012392044067383,"facing":0.0,"progress":0.0,"target":-1,"hits":0,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":4,"kind":"tower","team":0,"lane":"mid","zone":"lane","slot":-1,"uid":"","def":"blau_mid_outer","alive":true,"hp":6000.0,"max_hp":6000.0,"shield":0.0,"x":-3.8433847427368164,"y":8.990991592407227,"facing":0.0,"progress":0.0,"target":-1,"hits":0,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":5,"kind":"tower","team":0,"lane":"bot","zone":"lane","slot":-1,"uid":"","def":"blau_bot_inner","alive":true,"hp":7500.0,"max_hp":7500.0,"shield":0.0,"x":-4.349228858947754,"y":31.034507751464844,"facing":0.0,"progress":0.0,"target":-1,"hits":0,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":6,"kind":"tower","team":0,"lane":"bot","zone":"lane","slot":-1,"uid":"","def":"blau_bot_outer","alive":true,"hp":6000.0,"max_hp":6000.0,"shield":0.0,"x":11.117134094238281,"y":28.989334106445313,"facing":0.0,"progress":0.0,"target":-1,"hits":0,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":7,"kind":"tower","team":0,"lane":"base","zone":"lane","slot":-1,"uid":"","def":"blau_base_1","alive":true,"hp":9000.0,"max_hp":9000.0,"shield":0.0,"x":-29.476999282836914,"y":24.023000717163086,"facing":0.0,"progress":0.0,"target":-1,"hits":0,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":8,"kind":"tower","team":0,"lane":"base","zone":"lane","slot":-1,"uid":"","def":"blau_base_2","alive":true,"hp":9000.0,"max_hp":9000.0,"shield":0.0,"x":-24.023000717163086,"y":29.476999282836914,"facing":0.0,"progress":0.0,"target":-1,"hits":0,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":9,"kind":"core","team":0,"lane":"base","zone":"lane","slot":-1,"uid":"","def":"blau_ancient","alive":true,"hp":12000.0,"max_hp":12000.0,"shield":0.0,"x":-30.0,"y":30.0,"facing":0.0,"progress":0.0,"target":-1,"hits":0,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":10,"kind":"tower","team":1,"lane":"top","zone":"lane","slot":-1,"uid":"","def":"rot_top_inner","alive":true,"hp":7500.0,"max_hp":7500.0,"shield":0.0,"x":4.5293378829956055,"y":-24.931251525878906,"facing":0.0,"progress":0.0,"target":-1,"hits":0,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":11,"kind":"tower","team":1,"lane":"top","zone":"lane","slot":-1,"uid":"","def":"rot_top_outer","alive":true,"hp":6000.0,"max_hp":6000.0,"shield":0.0,"x":-12.715348243713379,"y":-24.921451568603516,"facing":0.0,"progress":0.0,"target":-1,"hits":0,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":12,"kind":"tower","team":1,"lane":"mid","zone":"lane","slot":-1,"uid":"","def":"rot_mid_inner","alive":true,"hp":7500.0,"max_hp":7500.0,"shield":0.0,"x":17.012392044067383,"y":-11.427590370178223,"facing":0.0,"progress":0.0,"target":-1,"hits":0,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":13,"kind":"tower","team":1,"lane":"mid","zone":"lane","slot":-1,"uid":"","def":"rot_mid_outer","alive":true,"hp":6000.0,"max_hp":6000.0,"shield":0.0,"x":8.990991592407227,"y":-3.8433847427368164,"facing":0.0,"progress":0.0,"target":23,"hits":2,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":14,"kind":"tower","team":1,"lane":"bot","zone":"lane","slot":-1,"uid":"","def":"rot_bot_inner","alive":true,"hp":7500.0,"max_hp":7500.0,"shield":0.0,"x":31.034507751464844,"y":-4.349228858947754,"facing":0.0,"progress":0.0,"target":-1,"hits":0,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":15,"kind":"tower","team":1,"lane":"bot","zone":"lane","slot":-1,"uid":"","def":"rot_bot_outer","alive":true,"hp":6000.0,"max_hp":6000.0,"shield":0.0,"x":28.989334106445313,"y":11.117134094238281,"facing":0.0,"progress":0.0,"target":-1,"hits":0,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":16,"kind":"tower","team":1,"lane":"base","zone":"lane","slot":-1,"uid":"","def":"rot_base_1","alive":true,"hp":9000.0,"max_hp":9000.0,"shield":0.0,"x":24.023000717163086,"y":-29.476999282836914,"facing":0.0,"progress":0.0,"target":-1,"hits":0,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":17,"kind":"tower","team":1,"lane":"base","zone":"lane","slot":-1,"uid":"","def":"rot_base_2","alive":true,"hp":9000.0,"max_hp":9000.0,"shield":0.0,"x":29.476999282836914,"y":-24.023000717163086,"facing":0.0,"progress":0.0,"target":-1,"hits":0,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":18,"kind":"core","team":1,"lane":"base","zone":"lane","slot":-1,"uid":"","def":"rot_ancient","alive":true,"hp":12000.0,"max_hp":12000.0,"shield":0.0,"x":30.0,"y":-30.0,"facing":0.0,"progress":0.0,"target":-1,"hits":0,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":19,"kind":"monster","team":0,"lane":"top","zone":"lane","slot":-1,"uid":"","def":"e01","alive":true,"hp":35.40000000000002,"max_hp":90.0,"shield":0.0,"x":-26.336877822875977,"y":-25.78684425354004,"facing":2.356194490192345,"progress":47.90360550768908,"target":28,"hits":7,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":20,"kind":"monster","team":0,"lane":"top","zone":"lane","slot":-1,"uid":"","def":"e01","alive":true,"hp":90.0,"max_hp":90.0,"shield":0.0,"x":-24.334409713745117,"y":-24.494911193847656,"facing":-2.930499320367047,"progress":48.45789523532882,"target":29,"hits":6,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":21,"kind":"monster","team":0,"lane":"top","zone":"lane","slot":-1,"uid":"","def":"e01","alive":false,"hp":0.0,"max_hp":90.0,"shield":0.0,"x":-24.103269577026367,"y":-23.419477462768555,"facing":0.21109333322274654,"progress":48.119907427881714,"target":-1,"hits":6,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":22,"kind":"monster","team":0,"lane":"mid","zone":"lane","slot":-1,"uid":"","def":"e01","alive":false,"hp":0.0,"max_hp":90.0,"shield":0.0,"x":6.740538120269775,"y":-3.936915397644043,"facing":1.951030464007805,"progress":38.18801245193652,"target":-1,"hits":8,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":23,"kind":"monster","team":0,"lane":"mid","zone":"lane","slot":-1,"uid":"","def":"e01","alive":true,"hp":35.40000000000002,"max_hp":90.0,"shield":0.0,"x":6.9257683753967285,"y":-2.8329102993011475,"facing":0.33914687771028884,"progress":37.630489397074406,"target":13,"hits":8,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":24,"kind":"monster","team":0,"lane":"mid","zone":"lane","slot":-1,"uid":"","def":"e01","alive":false,"hp":0.0,"max_hp":90.0,"shield":0.0,"x":6.0965986251831055,"y":-2.2348999977111816,"facing":2.025978282458253,"progress":36.562612563231326,"target":-1,"hits":8,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":25,"kind":"monster","team":0,"lane":"bot","zone":"lane","slot":-1,"uid":"","def":"e01","alive":false,"hp":0.0,"max_hp":90.0,"shield":0.0,"x":22.507102966308594,"y":22.51051139831543,"facing":-2.359400689128409,"progress":48.4104163646698,"target":-1,"hits":5,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":26,"kind":"monster","team":0,"lane":"bot","zone":"lane","slot":-1,"uid":"","def":"e01","alive":true,"hp":74.4,"max_hp":90.0,"shield":0.0,"x":22.728078842163086,"y":23.4947566986084,"facing":-0.7792177723742313,"progress":48.11259454169054,"target":36,"hits":5,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":27,"kind":"monster","team":0,"lane":"bot","zone":"lane","slot":-1,"uid":"","def":"e01","alive":true,"hp":74.4,"max_hp":90.0,"shield":0.0,"x":23.500873565673828,"y":22.71196174621582,"facing":2.362374881215562,"progress":48.782345006484604,"target":35,"hits":6,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":28,"kind":"monster","team":1,"lane":"top","zone":"lane","slot":-1,"uid":"","def":"e01","alive":true,"hp":35.40000000000002,"max_hp":90.0,"shield":0.0,"x":-25.78684425354004,"y":-26.336877822875977,"facing":-0.7853981633974483,"progress":47.90360550768908,"target":19,"hits":7,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":29,"kind":"monster","team":1,"lane":"top","zone":"lane","slot":-1,"uid":"","def":"e01","alive":true,"hp":90.0,"max_hp":90.0,"shield":0.0,"x":-24.494911193847656,"y":-24.334409713745117,"facing":-1.7818896600176433,"progress":48.45789523532882,"target":20,"hits":6,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":30,"kind":"monster","team":1,"lane":"top","zone":"lane","slot":-1,"uid":"","def":"e01","alive":false,"hp":0.0,"max_hp":90.0,"shield":0.0,"x":-23.419477462768555,"y":-24.103269577026367,"facing":1.35970299357215,"progress":48.119907427881714,"target":-1,"hits":6,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":31,"kind":"monster","team":1,"lane":"mid","zone":"lane","slot":-1,"uid":"","def":"e01","alive":false,"hp":0.0,"max_hp":90.0,"shield":0.0,"x":-0.6025248169898987,"y":-1.183314561843872,"facing":-0.7853981633974483,"progress":30.181223480769713,"target":-1,"hits":5,"reached":false,"dormant":false,"effects":[["root_grasp","movement_slow",0.2,2.0]],"dots":[]},{"id":32,"kind":"monster","team":1,"lane":"mid","zone":"lane","slot":-1,"uid":"","def":"e01","alive":false,"hp":0.0,"max_hp":90.0,"shield":0.0,"x":0.2985708713531494,"y":-0.23837746679782867,"facing":-0.785398207300417,"progress":30.20001472364576,"target":-1,"hits":7,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":33,"kind":"monster","team":1,"lane":"mid","zone":"lane","slot":-1,"uid":"","def":"e01","alive":false,"hp":0.0,"max_hp":90.0,"shield":0.0,"x":1.2298187017440796,"y":0.6764076948165894,"facing":-0.7853983769520584,"progress":30.176166371817065,"target":-1,"hits":8,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":34,"kind":"monster","team":1,"lane":"bot","zone":"lane","slot":-1,"uid":"","def":"e01","alive":false,"hp":0.0,"max_hp":90.0,"shield":0.0,"x":22.51051139831543,"y":22.507102966308594,"facing":-2.3529882912562807,"progress":48.4104163646698,"target":-1,"hits":5,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":35,"kind":"monster","team":1,"lane":"bot","zone":"lane","slot":-1,"uid":"","def":"e01","alive":true,"hp":74.4,"max_hp":90.0,"shield":0.0,"x":23.4947566986084,"y":22.728078842163086,"facing":2.350014099169128,"progress":48.11259454169054,"target":27,"hits":5,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":36,"kind":"monster","team":1,"lane":"bot","zone":"lane","slot":-1,"uid":"","def":"e01","alive":true,"hp":74.4,"max_hp":90.0,"shield":0.0,"x":22.71196174621582,"y":23.500873565673828,"facing":-0.7915785544206653,"progress":48.782345006484604,"target":26,"hits":6,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":37,"kind":"troop","team":0,"lane":"mid","zone":"lane","slot":1,"uid":"p1-5","def":"w01","alive":true,"hp":290.0,"max_hp":290.0,"shield":0.0,"x":6.602329730987549,"y":-3.749763011932373,"facing":-2.8024457758795043,"progress":37.959121037149615,"target":13,"hits":5,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":38,"kind":"troop","team":0,"lane":"grotto","zone":"grotto","slot":1,"uid":"p1-1","def":"w04","alive":true,"hp":1560.0,"max_hp":1560.0,"shield":0.0,"x":-13.57522201538086,"y":-12.767837524414063,"facing":-0.824539772559586,"progress":0.0,"target":43,"hits":12,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":39,"kind":"troop","team":0,"lane":"grotto","zone":"grotto","slot":1,"uid":"p1-2","def":"w04","alive":true,"hp":1488.5,"max_hp":1560.0,"shield":0.0,"x":-13.504572868347168,"y":-14.303034782409668,"facing":-2.393490620412012,"progress":0.0,"target":43,"hits":12,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":40,"kind":"troop","team":0,"lane":"grotto","zone":"grotto","slot":1,"uid":"p1-3","def":"w02","alive":true,"hp":597.5,"max_hp":800.0,"shield":0.0,"x":-12.76172924041748,"y":-13.503556251525879,"facing":1.0972262209581138,"progress":0.0,"target":43,"hits":13,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":41,"kind":"troop","team":0,"lane":"grotto","zone":"grotto","slot":1,"uid":"p1-4","def":"w06","alive":true,"hp":630.0,"max_hp":630.0,"shield":0.0,"x":-13.131528854370117,"y":-8.779524803161621,"facing":-2.9107643285244613,"progress":0.0,"target":43,"hits":14,"reached":false,"dormant":false,"effects":[],"dots":[]},{"id":42,"kind":"troop","team":1,"lane":"grotto","zone":"grotto","slot":4,"uid":"p4-1","def":"g04","alive":false,"hp":0.0,"max_hp":1650.0,"shield":0.0,"x":-9.694496154785156,"y":-11.984691619873047,"facing":-0.6572056176650801,"progress":0.0,"target":-1,"hits":10,"reached":false,"dormant":false,"effects":[["root_grasp","movement_slow",0.3,1.0000000000000027],["root_grasp_attack","attack_slow",0.1,1.0000000000000027]],"dots":[["seed_burn",10.0,0.750000000000006,0.7499999999999988,1]]},{"id":43,"kind":"boss","team":2,"lane":"grotto","zone":"grotto","slot":-1,"uid":"","def":"e10","alive":true,"hp":3104.3999999999987,"max_hp":3600.0,"shield":0.0,"x":-13.89926528930664,"y":-14.122014999389648,"facing":0.8975005509812763,"progress":0.0,"target":39,"hits":2,"reached":false,"dormant":false,"effects":[["root_grasp","movement_slow",0.3,1.6500000000000032],["root_grasp_attack","attack_slow",0.1,1.6500000000000032]],"dots":[["seed_burn",10.0,1.800000000000007,0.7999999999999992,1]]}]},{"label":"settled","phase":0,"round":2,"winner":-2,"end_note":"","players":[{"gold":308,"draft_gold":308,"ready":true,"earned":88,"spent":0,"next_seq":1,"roster":[],"hero":"","bookings":[],"new_bookings":[],"draft_roster":[],"draft_hero":"","boss_lane":"","undo":0},{"gold":5453,"draft_gold":5453,"ready":true,"earned":88,"spent":0,"next_seq":6,"roster":["p1-1|w04|mid|230","p1-2|w04|mid|230","p1-3|w02|mid|150","p1-4|w06|mid|195","p1-5|w01|mid|50"],"hero":"","bookings":[],"new_bookings":[],"draft_roster":["p1-1|w04|mid|230|false","p1-2|w04|mid|230|false","p1-3|w02|mid|150|false","p1-4|w06|mid|195|false","p1-5|w01|mid|50|false"],"draft_hero":"","boss_lane":"","undo":0},{"gold":308,"draft_gold":308,"ready":true,"earned":88,"spent":0,"next_seq":1,"roster":[],"hero":"","bookings":[],"new_bookings":[],"draft_roster":[],"draft_hero":"","boss_lane":"","undo":0},{"gold":308,"draft_gold":308,"ready":true,"earned":88,"spent":0,"next_seq":1,"roster":[],"hero":"","bookings":[],"new_bookings":[],"draft_roster":[],"draft_hero":"","boss_lane":"","undo":0},{"gold":6088,"draft_gold":6088,"ready":true,"earned":88,"spent":0,"next_seq":2,"roster":["p4-1|g04|mid|220"],"hero":"","bookings":[],"new_bookings":[],"draft_roster":["p4-1|g04|mid|220|false"],"draft_hero":"","boss_lane":"","undo":0},{"gold":308,"draft_gold":308,"ready":true,"earned":88,"spent":0,"next_seq":1,"roster":[],"hero":"","bookings":[],"new_bookings":[],"draft_roster":[],"draft_hero":"","boss_lane":"","undo":0}],"buildings":[7500.0,6000.0,7500.0,6000.0,7500.0,6000.0,9000.0,9000.0,12000.0,7500.0,6000.0,7500.0,5941.5,7500.0,6000.0,9000.0,9000.0,12000.0],"boss":{"next":5,"settled":1,"claim":"0|1|2|1|mid"},"boss_log":["1|won|0||1"],"announcements":["boss|0|1|mid||640"],"settlement":{"round":1,"gains":[18,18,18,18,18,18],"income":70,"lost":[],"end_reason":"cleared","combat_time":29.80000000000029,"boss":"won","lane_kills":{"mid":6,"bot":6,"top":6},"xp":{}},"combat":{"round":1,"steps":596,"elapsed":29.80000000000029,"finished":true,"end_reason":"cleared","destroyed":[],"grotto":"success|0|0|true","grotto_boss":"false|false|43","grotto_boss_hp":0.0,"events":21,"mobile":[4,0,0]},"events":[[1,179,8.949999999999992,1,"mid","lane","monster",31,"e01",6,"",13,[]],[2,219,10.95000000000002,1,"mid","lane","monster",32,"e01",6,"",13,[]],[3,230,11.500000000000028,1,"grotto","grotto","troop",42,"g04",0,"",15,[]],[4,247,12.35000000000004,1,"mid","lane","monster",33,"e01",6,"",13,[]],[5,248,12.400000000000041,0,"bot","lane","monster",25,"e01",6,"",13,[]],[6,248,12.400000000000041,1,"bot","lane","monster",34,"e01",6,"",13,[]],[7,276,13.800000000000061,0,"mid","lane","monster",24,"e01",6,"",13,[]],[8,278,13.900000000000063,0,"top","lane","monster",21,"e01",6,"",13,[]],[9,278,13.900000000000063,1,"top","lane","monster",30,"e01",6,"",13,[]],[10,296,14.800000000000075,0,"mid","lane","monster",22,"e01",6,"",13,[]],[11,316,15.80000000000009,0,"mid","lane","monster",23,"e01",6,"",13,[]],[12,393,19.650000000000144,0,"top","lane","monster",19,"e01",6,"",13,[]],[13,393,19.650000000000144,1,"top","lane","monster",28,"e01",6,"",13,[]],[14,396,19.800000000000146,0,"mid","lane","troop",37,"w01",0,"",15,[]],[15,490,24.500000000000213,0,"bot","lane","monster",26,"e01",6,"",13,[]],[16,490,24.500000000000213,1,"bot","lane","monster",35,"e01",6,"",13,[]],[17,510,25.500000000000227,0,"bot","lane","monster",27,"e01",6,"",13,[]],[18,510,25.500000000000227,1,"bot","lane","monster",36,"e01",6,"",13,[]],[19,521,26.050000000000235,0,"top","lane","monster",20,"e01",6,"",13,[]],[20,521,26.050000000000235,1,"top","lane","monster",29,"e01",6,"",13,[]],[21,596,29.80000000000029,2,"grotto","grotto","boss",43,"e10",0,"",220,[]]]}],"results":[["cmd",1,"buy",true,"Korkrücken gekauft."],["cmd",1,"upgrade",true,"Zu Ringborke aufgewertet."],["cmd",1,"assign",true,"In die Bossgrotte entsandt."],["cmd",1,"buy",true,"Korkrücken gekauft."],["cmd",1,"upgrade",true,"Zu Ringborke aufgewertet."],["cmd",1,"assign",true,"In die Bossgrotte entsandt."],["cmd",1,"buy",true,"Dornhopser gekauft."],["cmd",1,"upgrade",true,"Zu Rankenschnapper aufgewertet."],["cmd",1,"assign",true,"In die Bossgrotte entsandt."],["cmd",1,"buy",true,"Samenschleuder gekauft."],["cmd",1,"upgrade",true,"Zu Zapfenkrone aufgewertet."],["cmd",1,"assign",true,"In die Bossgrotte entsandt."],["cmd",1,"buy",true,"Dornhopser gekauft."],["cmd",4,"buy",true,"Schlackenwacht gekauft."],["cmd",4,"upgrade",true,"Zu Basaltbastion aufgewertet."],["cmd",4,"assign",true,"In die Bossgrotte entsandt."],["begin",-1,"",true,""]]},"mirror_match":{"title":"Spiegelpartie: gleicher Bund und gleiches Profil auf allen Plätzen bleibt exakt symmetrisch","snapshots":[{"label":"round-1","phase":0,"round":2,"winner":-2,"end_note":"","players":[{"gold":128,"draft_gold":128,"ready":true,"earned":88,"spent":180,"next_seq":4,"roster":["p0-1|g03|top|70","p0-2|g05|top|65","p0-3|g01|top|45"],"hero":"","bookings":[],"new_bookings":[],"draft_roster":["p0-1|g03|top|70|false","p0-2|g05|top|65|false","p0-3|g01|top|45|false"],"draft_hero":"","boss_lane":"","undo":0},{"gold":128,"draft_gold":128,"ready":true,"earned":88,"spent":180,"next_seq":4,"roster":["p1-1|g03|mid|70","p1-2|g05|mid|65","p1-3|g01|mid|45"],"hero":"","bookings":[],"new_bookings":[],"draft_roster":["p1-1|g03|mid|70|false","p1-2|g05|mid|65|false","p1-3|g01|mid|45|false"],"draft_hero":"","boss_lane":"","undo":0},{"gold":128,"draft_gold":128,"ready":true,"earned":88,"spent":180,"next_seq":4,"roster":["p2-1|g03|bot|70","p2-2|g05|bot|65","p2-3|g01|bot|45"],"hero":"","bookings":[],"new_bookings":[],"draft_roster":["p2-1|g03|bot|70|false","p2-2|g05|bot|65|false","p2-3|g01|bot|45|false"],"draft_hero":"","boss_lane":"","undo":0},{"gold":128,"draft_gold":128,"ready":true,"earned":88,"spent":180,"next_seq":4,"roster":["p3-1|g03|top|70","p3-2|g05|top|65","p3-3|g01|top|45"],"hero":"","bookings":[],"new_bookings":[],"draft_roster":["p3-1|g03|top|70|false","p3-2|g05|top|65|false","p3-3|g01|top|45|false"],"draft_hero":"","boss_lane":"","undo":0},{"gold":128,"draft_gold":128,"ready":true,"earned":88,"spent":180,"next_seq":4,"roster":["p4-1|g03|mid|70","p4-2|g05|mid|65","p4-3|g01|mid|45"],"hero":"","bookings":[],"new_bookings":[],"draft_roster":["p4-1|g03|mid|70|false","p4-2|g05|mid|65|false","p4-3|g01|mid|45|false"],"draft_hero":"","boss_lane":"","undo":0},{"gold":128,"draft_gold":128,"ready":true,"earned":88,"spent":180,"next_seq":4,"roster":["p5-1|g03|bot|70","p5-2|g05|bot|65","p5-3|g01|bot|45"],"hero":"","bookings":[],"new_bookings":[],"draft_roster":["p5-1|g03|bot|70|false","p5-2|g05|bot|65|false","p5-3|g01|bot|45|false"],"draft_hero":"","boss_lane":"","undo":0}],"buildings":[7500.0,6000.0,7500.0,6000.0,7500.0,6000.0,9000.0,9000.0,12000.0,7500.0,6000.0,7500.0,6000.0,7500.0,6000.0,9000.0,9000.0,12000.0],"boss":{"next":1,"settled":1,"claim":""},"boss_log":[],"announcements":[],"settlement":{"round":1,"gains":[18,18,18,18,18,18],"income":70,"lost":[],"end_reason":"cleared","combat_time":43.04999999999969,"boss":"none","lane_kills":{"mid":6,"bot":6,"top":6},"xp":{}},"combat":{"round":1,"steps":861,"elapsed":43.04999999999969,"finished":true,"end_reason":"cleared","destroyed":[],"grotto":"none|-1|-1|true","grotto_boss":"","grotto_boss_hp":0.0,"events":36,"mobile":[0,0,0]}},{"label":"round-2","phase":0,"round":3,"winner":-2,"end_note":"","players":[{"gold":150,"draft_gold":150,"ready":true,"earned":180,"spent":250,"next_seq":5,"roster":["p0-1|g03|top|70","p0-2|g05|top|65","p0-3|g01|top|45","p0-4|g03|top|70"],"hero":"","bookings":[],"new_bookings":[],"draft_roster":["p0-1|g03|top|70|false","p0-2|g05|top|65|false","p0-3|g01|top|45|false","p0-4|g03|top|70|false"],"draft_hero":"","boss_lane":"","undo":0},{"gold":150,"draft_gold":150,"ready":true,"earned":180,"spent":250,"next_seq":5,"roster":["p1-1|g03|mid|70","p1-2|g05|mid|65","p1-3|g01|mid|45","p1-4|g03|mid|70"],"hero":"","bookings":[],"new_bookings":[],"draft_roster":["p1-1|g03|mid|70|false","p1-2|g05|mid|65|false","p1-3|g01|mid|45|false","p1-4|g03|mid|70|false"],"draft_hero":"","boss_lane":"","undo":0},{"gold":150,"draft_gold":150,"ready":true,"earned":180,"spent":250,"next_seq":5,"roster":["p2-1|g03|bot|70","p2-2|g05|bot|65","p2-3|g01|bot|45","p2-4|g03|bot|70"],"hero":"","bookings":[],"new_bookings":[],"draft_roster":["p2-1|g03|bot|70|false","p2-2|g05|bot|65|false","p2-3|g01|bot|45|false","p2-4|g03|bot|70|false"],"draft_hero":"","boss_lane":"","undo":0},{"gold":150,"draft_gold":150,"ready":true,"earned":180,"spent":250,"next_seq":5,"roster":["p3-1|g03|top|70","p3-2|g05|top|65","p3-3|g01|top|45","p3-4|g03|top|70"],"hero":"","bookings":[],"new_bookings":[],"draft_roster":["p3-1|g03|top|70|false","p3-2|g05|top|65|false","p3-3|g01|top|45|false","p3-4|g03|top|70|false"],"draft_hero":"","boss_lane":"","undo":0},{"gold":150,"draft_gold":150,"ready":true,"earned":180,"spent":250,"next_seq":5,"roster":["p4-1|g03|mid|70","p4-2|g05|mid|65","p4-3|g01|mid|45","p4-4|g03|mid|70"],"hero":"","bookings":[],"new_bookings":[],"draft_roster":["p4-1|g03|mid|70|false","p4-2|g05|mid|65|false","p4-3|g01|mid|45|false","p4-4|g03|mid|70|false"],"draft_hero":"","boss_lane":"","undo":0},{"gold":150,"draft_gold":150,"ready":true,"earned":180,"spent":250,"next_seq":5,"roster":["p5-1|g03|bot|70","p5-2|g05|bot|65","p5-3|g01|bot|45","p5-4|g03|bot|70"],"hero":"","bookings":[],"new_bookings":[],"draft_roster":["p5-1|g03|bot|70|false","p5-2|g05|bot|65|false","p5-3|g01|bot|45|false","p5-4|g03|bot|70|false"],"draft_hero":"","boss_lane":"","undo":0}],"buildings":[7500.0,6000.0,7500.0,6000.0,7500.0,6000.0,9000.0,9000.0,12000.0,7500.0,6000.0,7500.0,6000.0,7500.0,6000.0,9000.0,9000.0,12000.0],"boss":{"next":1,"settled":2,"claim":""},"boss_log":[],"announcements":[],"settlement":{"round":2,"gains":[18,18,18,18,18,18],"income":74,"lost":[],"end_reason":"cleared","combat_time":56.549999999998924,"boss":"none","lane_kills":{"mid":6,"bot":6,"top":6},"xp":{}},"combat":{"round":2,"steps":1131,"elapsed":56.549999999998924,"finished":true,"end_reason":"cleared","destroyed":[],"grotto":"none|-1|-1|true","grotto_boss":"","grotto_boss_hp":0.0,"events":42,"mobile":[0,0,0]}},{"label":"round-3","phase":0,"round":4,"winner":-2,"end_note":"","players":[{"gold":165,"draft_gold":165,"ready":true,"earned":290,"spent":345,"next_seq":6,"roster":["p0-1|g03|top|70","p0-2|g05|top|65","p0-3|g01|top|45","p0-4|g03|top|70","p0-5|g07|top|95"],"hero":"","bookings":[],"new_bookings":[],"draft_roster":["p0-1|g03|top|70|false","p0-2|g05|top|65|false","p0-3|g01|top|45|false","p0-4|g03|top|70|false","p0-5|g07|top|95|false"],"draft_hero":"","boss_lane":"","undo":0},{"gold":165,"draft_gold":165,"ready":true,"earned":290,"spent":345,"next_seq":6,"roster":["p1-1|g03|mid|70","p1-2|g05|mid|65","p1-3|g01|mid|45","p1-4|g03|mid|70","p1-5|g07|mid|95"],"hero":"","bookings":[],"new_bookings":[],"draft_roster":["p1-1|g03|mid|70|false","p1-2|g05|mid|65|false","p1-3|g01|mid|45|false","p1-4|g03|mid|70|false","p1-5|g07|mid|95|false"],"draft_hero":"","boss_lane":"","undo":0},{"gold":165,"draft_gold":165,"ready":true,"earned":290,"spent":345,"next_seq":6,"roster":["p2-1|g03|bot|70","p2-2|g05|bot|65","p2-3|g01|bot|45","p2-4|g03|bot|70","p2-5|g07|bot|95"],"hero":"","bookings":[],"new_bookings":[],"draft_roster":["p2-1|g03|bot|70|false","p2-2|g05|bot|65|false","p2-3|g01|bot|45|false","p2-4|g03|bot|70|false","p2-5|g07|bot|95|false"],"draft_hero":"","boss_lane":"","undo":0},{"gold":165,"draft_gold":165,"ready":true,"earned":290,"spent":345,"next_seq":6,"roster":["p3-1|g03|top|70","p3-2|g05|top|65","p3-3|g01|top|45","p3-4|g03|top|70","p3-5|g07|top|95"],"hero":"","bookings":[],"new_bookings":[],"draft_roster":["p3-1|g03|top|70|false","p3-2|g05|top|65|false","p3-3|g01|top|45|false","p3-4|g03|top|70|false","p3-5|g07|top|95|false"],"draft_hero":"","boss_lane":"","undo":0},{"gold":165,"draft_gold":165,"ready":true,"earned":290,"spent":345,"next_seq":6,"roster":["p4-1|g03|mid|70","p4-2|g05|mid|65","p4-3|g01|mid|45","p4-4|g03|mid|70","p4-5|g07|mid|95"],"hero":"","bookings":[],"new_bookings":[],"draft_roster":["p4-1|g03|mid|70|false","p4-2|g05|mid|65|false","p4-3|g01|mid|45|false","p4-4|g03|mid|70|false","p4-5|g07|mid|95|false"],"draft_hero":"","boss_lane":"","undo":0},{"gold":165,"draft_gold":165,"ready":true,"earned":290,"spent":345,"next_seq":6,"roster":["p5-1|g03|bot|70","p5-2|g05|bot|65","p5-3|g01|bot|45","p5-4|g03|bot|70","p5-5|g07|bot|95"],"hero":"","bookings":[],"new_bookings":[],"draft_roster":["p5-1|g03|bot|70|false","p5-2|g05|bot|65|false","p5-3|g01|bot|45|false","p5-4|g03|bot|70|false","p5-5|g07|bot|95|false"],"draft_hero":"","boss_lane":"","undo":0}],"buildings":[7500.0,6000.0,7500.0,6000.0,7500.0,6000.0,9000.0,9000.0,12000.0,7500.0,6000.0,7500.0,6000.0,7500.0,6000.0,9000.0,9000.0,12000.0],"boss":{"next":1,"settled":3,"claim":""},"boss_log":[],"announcements":[],"settlement":{"round":3,"gains":[32,32,32,32,32,32],"income":78,"lost":[],"end_reason":"cleared","combat_time":53.699999999999086,"boss":"none","lane_kills":{"mid":6,"bot":6,"top":6},"xp":{}},"combat":{"round":3,"steps":1074,"elapsed":53.699999999999086,"finished":true,"end_reason":"cleared","destroyed":[],"grotto":"none|-1|-1|true","grotto_boss":"","grotto_boss_hp":0.0,"events":48,"mobile":[0,0,0]}},{"label":"round-4","phase":0,"round":5,"winner":-2,"end_note":"","players":[{"gold":137,"draft_gold":137,"ready":true,"earned":412,"spent":495,"next_seq":8,"roster":["p0-1|g03|top|70","p0-2|g05|top|65","p0-3|g01|top|45","p0-4|g03|top|70","p0-5|g07|top|95","p0-6|g09|top|85","p0-7|g05|top|65"],"hero":"","bookings":[],"new_bookings":[],"draft_roster":["p0-1|g03|top|70|false","p0-2|g05|top|65|false","p0-3|g01|top|45|false","p0-4|g03|top|70|false","p0-5|g07|top|95|false","p0-6|g09|top|85|false","p0-7|g05|top|65|false"],"draft_hero":"","boss_lane":"","undo":0},{"gold":137,"draft_gold":137,"ready":true,"earned":412,"spent":495,"next_seq":8,"roster":["p1-1|g03|mid|70","p1-2|g05|mid|65","p1-3|g01|mid|45","p1-4|g03|mid|70","p1-5|g07|mid|95","p1-6|g09|mid|85","p1-7|g05|mid|65"],"hero":"","bookings":[],"new_bookings":[],"draft_roster":["p1-1|g03|mid|70|false","p1-2|g05|mid|65|false","p1-3|g01|mid|45|false","p1-4|g03|mid|70|false","p1-5|g07|mid|95|false","p1-6|g09|mid|85|false","p1-7|g05|mid|65|false"],"draft_hero":"","boss_lane":"","undo":0},{"gold":137,"draft_gold":137,"ready":true,"earned":412,"spent":495,"next_seq":8,"roster":["p2-1|g03|bot|70","p2-2|g05|bot|65","p2-3|g01|bot|45","p2-4|g03|bot|70","p2-5|g07|bot|95","p2-6|g09|bot|85","p2-7|g05|bot|65"],"hero":"","bookings":[],"new_bookings":[],"draft_roster":["p2-1|g03|bot|70|false","p2-2|g05|bot|65|false","p2-3|g01|bot|45|false","p2-4|g03|bot|70|false","p2-5|g07|bot|95|false","p2-6|g09|bot|85|false","p2-7|g05|bot|65|false"],"draft_hero":"","boss_lane":"","undo":0},{"gold":137,"draft_gold":137,"ready":true,"earned":412,"spent":495,"next_seq":8,"roster":["p3-1|g03|top|70","p3-2|g05|top|65","p3-3|g01|top|45","p3-4|g03|top|70","p3-5|g07|top|95","p3-6|g09|top|85","p3-7|g05|top|65"],"hero":"","bookings":[],"new_bookings":[],"draft_roster":["p3-1|g03|top|70|false","p3-2|g05|top|65|false","p3-3|g01|top|45|false","p3-4|g03|top|70|false","p3-5|g07|top|95|false","p3-6|g09|top|85|false","p3-7|g05|top|65|false"],"draft_hero":"","boss_lane":"","undo":0},{"gold":137,"draft_gold":137,"ready":true,"earned":412,"spent":495,"next_seq":8,"roster":["p4-1|g03|mid|70","p4-2|g05|mid|65","p4-3|g01|mid|45","p4-4|g03|mid|70","p4-5|g07|mid|95","p4-6|g09|mid|85","p4-7|g05|mid|65"],"hero":"","bookings":[],"new_bookings":[],"draft_roster":["p4-1|g03|mid|70|false","p4-2|g05|mid|65|false","p4-3|g01|mid|45|false","p4-4|g03|mid|70|false","p4-5|g07|mid|95|false","p4-6|g09|mid|85|false","p4-7|g05|mid|65|false"],"draft_hero":"","boss_lane":"","undo":0},{"gold":137,"draft_gold":137,"ready":true,"earned":412,"spent":495,"next_seq":8,"roster":["p5-1|g03|bot|70","p5-2|g05|bot|65","p5-3|g01|bot|45","p5-4|g03|bot|70","p5-5|g07|bot|95","p5-6|g09|bot|85","p5-7|g05|bot|65"],"hero":"","bookings":[],"new_bookings":[],"draft_roster":["p5-1|g03|bot|70|false","p5-2|g05|bot|65|false","p5-3|g01|bot|45|false","p5-4|g03|bot|70|false","p5-5|g07|bot|95|false","p5-6|g09|bot|85|false","p5-7|g05|bot|65|false"],"draft_hero":"","boss_lane":"","undo":0}],"buildings":[7500.0,6000.0,7500.0,6000.0,7500.0,6000.0,9000.0,9000.0,12000.0,7500.0,6000.0,7500.0,6000.0,7500.0,6000.0,9000.0,9000.0,12000.0],"boss":{"next":1,"settled":4,"claim":""},"boss_log":[],"announcements":[],"settlement":{"round":4,"gains":[40,40,40,40,40,40],"income":82,"lost":[],"end_reason":"cleared","combat_time":53.64999999999909,"boss":"none","lane_kills":{"mid":8,"bot":8,"top":8},"xp":{}},"combat":{"round":4,"steps":1073,"elapsed":53.64999999999909,"finished":true,"end_reason":"cleared","destroyed":[],"grotto":"none|-1|-1|true","grotto_boss":"","grotto_boss_hp":0.0,"events":66,"mobile":[0,0,0]}},{"label":"round-5","phase":0,"round":6,"winner":-2,"end_note":"","players":[{"gold":178,"draft_gold":178,"ready":true,"earned":543,"spent":585,"next_seq":8,"roster":["p0-1|g03|top|70","p0-2|g05|top|65","p0-3|g02|top|135","p0-4|g03|top|70","p0-5|g07|top|95","p0-6|g09|top|85","p0-7|g05|top|65"],"hero":"","bookings":[],"new_bookings":[],"draft_roster":["p0-1|g03|top|70|false","p0-2|g05|top|65|false","p0-3|g02|top|135|false","p0-4|g03|top|70|false","p0-5|g07|top|95|false","p0-6|g09|top|85|false","p0-7|g05|top|65|false"],"draft_hero":"","boss_lane":"","undo":0},{"gold":178,"draft_gold":178,"ready":true,"earned":543,"spent":585,"next_seq":8,"roster":["p1-1|g03|mid|70","p1-2|g05|mid|65","p1-3|g02|mid|135","p1-4|g03|mid|70","p1-5|g07|mid|95","p1-6|g09|mid|85","p1-7|g05|mid|65"],"hero":"","bookings":[],"new_bookings":[],"draft_roster":["p1-1|g03|mid|70|false","p1-2|g05|mid|65|false","p1-3|g02|mid|135|false","p1-4|g03|mid|70|false","p1-5|g07|mid|95|false","p1-6|g09|mid|85|false","p1-7|g05|mid|65|false"],"draft_hero":"","boss_lane":"","undo":0},{"gold":178,"draft_gold":178,"ready":true,"earned":543,"spent":585,"next_seq":8,"roster":["p2-1|g03|bot|70","p2-2|g05|bot|65","p2-3|g02|bot|135","p2-4|g03|bot|70","p2-5|g07|bot|95","p2-6|g09|bot|85","p2-7|g05|bot|65"],"hero":"","bookings":[],"new_bookings":[],"draft_roster":["p2-1|g03|bot|70|false","p2-2|g05|bot|65|false","p2-3|g02|bot|135|false","p2-4|g03|bot|70|false","p2-5|g07|bot|95|false","p2-6|g09|bot|85|false","p2-7|g05|bot|65|false"],"draft_hero":"","boss_lane":"","undo":0},{"gold":178,"draft_gold":178,"ready":true,"earned":543,"spent":585,"next_seq":8,"roster":["p3-1|g03|top|70","p3-2|g05|top|65","p3-3|g02|top|135","p3-4|g03|top|70","p3-5|g07|top|95","p3-6|g09|top|85","p3-7|g05|top|65"],"hero":"","bookings":[],"new_bookings":[],"draft_roster":["p3-1|g03|top|70|false","p3-2|g05|top|65|false","p3-3|g02|top|135|false","p3-4|g03|top|70|false","p3-5|g07|top|95|false","p3-6|g09|top|85|false","p3-7|g05|top|65|false"],"draft_hero":"","boss_lane":"","undo":0},{"gold":178,"draft_gold":178,"ready":true,"earned":543,"spent":585,"next_seq":8,"roster":["p4-1|g03|mid|70","p4-2|g05|mid|65","p4-3|g02|mid|135","p4-4|g03|mid|70","p4-5|g07|mid|95","p4-6|g09|mid|85","p4-7|g05|mid|65"],"hero":"","bookings":[],"new_bookings":[],"draft_roster":["p4-1|g03|mid|70|false","p4-2|g05|mid|65|false","p4-3|g02|mid|135|false","p4-4|g03|mid|70|false","p4-5|g07|mid|95|false","p4-6|g09|mid|85|false","p4-7|g05|mid|65|false"],"draft_hero":"","boss_lane":"","undo":0},{"gold":178,"draft_gold":178,"ready":true,"earned":543,"spent":585,"next_seq":8,"roster":["p5-1|g03|bot|70","p5-2|g05|bot|65","p5-3|g02|bot|135","p5-4|g03|bot|70","p5-5|g07|bot|95","p5-6|g09|bot|85","p5-7|g05|bot|65"],"hero":"","bookings":[],"new_bookings":[],"draft_roster":["p5-1|g03|bot|70|false","p5-2|g05|bot|65|false","p5-3|g02|bot|135|false","p5-4|g03|bot|70|false","p5-5|g07|bot|95|false","p5-6|g09|bot|85|false","p5-7|g05|bot|65|false"],"draft_hero":"","boss_lane":"","undo":0}],"buildings":[7500.0,6000.0,7500.0,6000.0,7500.0,6000.0,9000.0,9000.0,12000.0,7500.0,6000.0,7500.0,6000.0,7500.0,6000.0,9000.0,9000.0,12000.0],"boss":{"next":1,"settled":5,"claim":""},"boss_log":[],"announcements":[],"settlement":{"round":5,"gains":[45,45,45,45,45,45],"income":86,"lost":[],"end_reason":"cleared","combat_time":56.14999999999895,"boss":"none","lane_kills":{"mid":8,"bot":8,"top":8},"xp":{}},"combat":{"round":5,"steps":1123,"elapsed":56.14999999999895,"finished":true,"end_reason":"cleared","destroyed":[],"grotto":"none|-1|-1|true","grotto_boss":"","grotto_boss_hp":0.0,"events":66,"mobile":[0,0,0]}},{"label":"round-6","phase":0,"round":7,"winner":-2,"end_note":"","players":[{"gold":168,"draft_gold":168,"ready":true,"earned":673,"spent":725,"next_seq":8,"roster":["p0-1|g03|top|70","p0-2|g06|top|205","p0-3|g02|top|135","p0-4|g03|top|70","p0-5|g07|top|95","p0-6|g09|top|85","p0-7|g05|top|65"],"hero":"","bookings":[],"new_bookings":[],"draft_roster":["p0-1|g03|top|70|false","p0-2|g06|top|205|false","p0-3|g02|top|135|false","p0-4|g03|top|70|false","p0-5|g07|top|95|false","p0-6|g09|top|85|false","p0-7|g05|top|65|false"],"draft_hero":"","boss_lane":"","undo":0},{"gold":168,"draft_gold":168,"ready":true,"earned":673,"spent":725,"next_seq":8,"roster":["p1-1|g03|mid|70","p1-2|g06|mid|205","p1-3|g02|mid|135","p1-4|g03|mid|70","p1-5|g07|mid|95","p1-6|g09|mid|85","p1-7|g05|mid|65"],"hero":"","bookings":[],"new_bookings":[],"draft_roster":["p1-1|g03|mid|70|false","p1-2|g06|mid|205|false","p1-3|g02|mid|135|false","p1-4|g03|mid|70|false","p1-5|g07|mid|95|false","p1-6|g09|mid|85|false","p1-7|g05|mid|65|false"],"draft_hero":"","boss_lane":"","undo":0},{"gold":168,"draft_gold":168,"ready":true,"earned":673,"spent":725,"next_seq":8,"roster":["p2-1|g03|bot|70","p2-2|g06|bot|205","p2-3|g02|bot|135","p2-4|g03|bot|70","p2-5|g07|bot|95","p2-6|g09|bot|85","p2-7|g05|bot|65"],"hero":"","bookings":[],"new_bookings":[],"draft_roster":["p2-1|g03|bot|70|false","p2-2|g06|bot|205|false","p2-3|g02|bot|135|false","p2-4|g03|bot|70|false","p2-5|g07|bot|95|false","p2-6|g09|bot|85|false","p2-7|g05|bot|65|false"],"draft_hero":"","boss_lane":"","undo":0},{"gold":168,"draft_gold":168,"ready":true,"earned":673,"spent":725,"next_seq":8,"roster":["p3-1|g03|top|70","p3-2|g06|top|205","p3-3|g02|top|135","p3-4|g03|top|70","p3-5|g07|top|95","p3-6|g09|top|85","p3-7|g05|top|65"],"hero":"","bookings":[],"new_bookings":[],"draft_roster":["p3-1|g03|top|70|false","p3-2|g06|top|205|false","p3-3|g02|top|135|false","p3-4|g03|top|70|false","p3-5|g07|top|95|false","p3-6|g09|top|85|false","p3-7|g05|top|65|false"],"draft_hero":"","boss_lane":"","undo":0},{"gold":168,"draft_gold":168,"ready":true,"earned":673,"spent":725,"next_seq":8,"roster":["p4-1|g03|mid|70","p4-2|g06|mid|205","p4-3|g02|mid|135","p4-4|g03|mid|70","p4-5|g07|mid|95","p4-6|g09|mid|85","p4-7|g05|mid|65"],"hero":"","bookings":[],"new_bookings":[],"draft_roster":["p4-1|g03|mid|70|false","p4-2|g06|mid|205|false","p4-3|g02|mid|135|false","p4-4|g03|mid|70|false","p4-5|g07|mid|95|false","p4-6|g09|mid|85|false","p4-7|g05|mid|65|false"],"draft_hero":"","boss_lane":"","undo":0},{"gold":168,"draft_gold":168,"ready":true,"earned":673,"spent":725,"next_seq":8,"roster":["p5-1|g03|bot|70","p5-2|g06|bot|205","p5-3|g02|bot|135","p5-4|g03|bot|70","p5-5|g07|bot|95","p5-6|g09|bot|85","p5-7|g05|bot|65"],"hero":"","bookings":[],"new_bookings":[],"draft_roster":["p5-1|g03|bot|70|false","p5-2|g06|bot|205|false","p5-3|g02|bot|135|false","p5-4|g03|bot|70|false","p5-5|g07|bot|95|false","p5-6|g09|bot|85|false","p5-7|g05|bot|65|false"],"draft_hero":"","boss_lane":"","undo":0}],"buildings":[7500.0,6000.0,7500.0,6000.0,7500.0,6000.0,9000.0,9000.0,12000.0,7500.0,6000.0,7500.0,6000.0,7500.0,6000.0,9000.0,9000.0,12000.0],"boss":{"next":1,"settled":6,"claim":""},"boss_log":[],"announcements":[],"settlement":{"round":6,"gains":[40,40,40,40,40,40],"income":90,"lost":[],"end_reason":"cleared","combat_time":43.19999999999968,"boss":"none","lane_kills":{"mid":8,"bot":8,"top":8},"xp":{}},"combat":{"round":6,"steps":864,"elapsed":43.19999999999968,"finished":true,"end_reason":"cleared","destroyed":[],"grotto":"none|-1|-1|true","grotto_boss":"","grotto_boss_hp":0.0,"events":66,"mobile":[0,0,0]}},{"label":"round-7","phase":0,"round":8,"winner":-2,"end_note":"","players":[{"gold":180,"draft_gold":180,"ready":true,"earned":825,"spent":865,"next_seq":8,"roster":["p0-1|g03|top|70","p0-2|g06|top|205","p0-3|g02|top|135","p0-4|g03|top|70","p0-5|g07|top|95","p0-6|g09|top|85","p0-7|g06|top|205"],"hero":"","bookings":[],"new_bookings":[],"draft_roster":["p0-1|g03|top|70|false","p0-2|g06|top|205|false","p0-3|g02|top|135|false","p0-4|g03|top|70|false","p0-5|g07|top|95|false","p0-6|g09|top|85|false","p0-7|g06|top|205|false"],"draft_hero":"","boss_lane":"","undo":0},{"gold":180,"draft_gold":180,"ready":true,"earned":825,"spent":865,"next_seq":8,"roster":["p1-1|g03|mid|70","p1-2|g06|mid|205","p1-3|g02|mid|135","p1-4|g03|mid|70","p1-5|g07|mid|95","p1-6|g09|mid|85","p1-7|g06|mid|205"],"hero":"","bookings":[],"new_bookings":[],"draft_roster":["p1-1|g03|mid|70|false","p1-2|g06|mid|205|false","p1-3|g02|mid|135|false","p1-4|g03|mid|70|false","p1-5|g07|mid|95|false","p1-6|g09|mid|85|false","p1-7|g06|mid|205|false"],"draft_hero":"","boss_lane":"","undo":0},{"gold":180,"draft_gold":180,"ready":true,"earned":825,"spent":865,"next_seq":8,"roster":["p2-1|g03|bot|70","p2-2|g06|bot|205","p2-3|g02|bot|135","p2-4|g03|bot|70","p2-5|g07|bot|95","p2-6|g09|bot|85","p2-7|g06|bot|205"],"hero":"","bookings":[],"new_bookings":[],"draft_roster":["p2-1|g03|bot|70|false","p2-2|g06|bot|205|false","p2-3|g02|bot|135|false","p2-4|g03|bot|70|false","p2-5|g07|bot|95|false","p2-6|g09|bot|85|false","p2-7|g06|bot|205|false"],"draft_hero":"","boss_lane":"","undo":0},{"gold":180,"draft_gold":180,"ready":true,"earned":825,"spent":865,"next_seq":8,"roster":["p3-1|g03|top|70","p3-2|g06|top|205","p3-3|g02|top|135","p3-4|g03|top|70","p3-5|g07|top|95","p3-6|g09|top|85","p3-7|g06|top|205"],"hero":"","bookings":[],"new_bookings":[],"draft_roster":["p3-1|g03|top|70|false","p3-2|g06|top|205|false","p3-3|g02|top|135|false","p3-4|g03|top|70|false","p3-5|g07|top|95|false","p3-6|g09|top|85|false","p3-7|g06|top|205|false"],"draft_hero":"","boss_lane":"","undo":0},{"gold":180,"draft_gold":180,"ready":true,"earned":825,"spent":865,"next_seq":8,"roster":["p4-1|g03|mid|70","p4-2|g06|mid|205","p4-3|g02|mid|135","p4-4|g03|mid|70","p4-5|g07|mid|95","p4-6|g09|mid|85","p4-7|g06|mid|205"],"hero":"","bookings":[],"new_bookings":[],"draft_roster":["p4-1|g03|mid|70|false","p4-2|g06|mid|205|false","p4-3|g02|mid|135|false","p4-4|g03|mid|70|false","p4-5|g07|mid|95|false","p4-6|g09|mid|85|false","p4-7|g06|mid|205|false"],"draft_hero":"","boss_lane":"","undo":0},{"gold":180,"draft_gold":180,"ready":true,"earned":825,"spent":865,"next_seq":8,"roster":["p5-1|g03|bot|70","p5-2|g06|bot|205","p5-3|g02|bot|135","p5-4|g03|bot|70","p5-5|g07|bot|95","p5-6|g09|bot|85","p5-7|g06|bot|205"],"hero":"","bookings":[],"new_bookings":[],"draft_roster":["p5-1|g03|bot|70|false","p5-2|g06|bot|205|false","p5-3|g02|bot|135|false","p5-4|g03|bot|70|false","p5-5|g07|bot|95|false","p5-6|g09|bot|85|false","p5-7|g06|bot|205|false"],"draft_hero":"","boss_lane":"","undo":0}],"buildings":[7500.0,6000.0,7500.0,6000.0,7500.0,6000.0,9000.0,9000.0,12000.0,7500.0,6000.0,7500.0,6000.0,7500.0,6000.0,9000.0,9000.0,12000.0],"boss":{"next":1,"settled":7,"claim":""},"boss_log":[],"announcements":[],"settlement":{"round":7,"gains":[58,58,58,58,58,58],"income":94,"lost":[],"end_reason":"cleared","combat_time":41.29999999999979,"boss":"none","lane_kills":{"mid":10,"bot":10,"top":10},"xp":{}},"combat":{"round":7,"steps":826,"elapsed":41.29999999999979,"finished":true,"end_reason":"cleared","destroyed":[],"grotto":"none|-1|-1|true","grotto_boss":"","grotto_boss_hp":0.0,"events":72,"mobile":[0,0,0]}},{"label":"round-8","phase":0,"round":9,"winner":-2,"end_note":"","players":[{"gold":185,"draft_gold":185,"ready":true,"earned":980,"spent":1015,"next_seq":8,"roster":["p0-1|g04|top|220","p0-2|g06|top|205","p0-3|g02|top|135","p0-4|g03|top|70","p0-5|g07|top|95","p0-6|g09|top|85","p0-7|g06|top|205"],"hero":"","bookings":[],"new_bookings":[],"draft_roster":["p0-1|g04|top|220|false","p0-2|g06|top|205|false","p0-3|g02|top|135|false","p0-4|g03|top|70|false","p0-5|g07|top|95|false","p0-6|g09|top|85|false","p0-7|g06|top|205|false"],"draft_hero":"","boss_lane":"","undo":0},{"gold":185,"draft_gold":185,"ready":true,"earned":980,"spent":1015,"next_seq":8,"roster":["p1-1|g04|mid|220","p1-2|g06|mid|205","p1-3|g02|mid|135","p1-4|g03|mid|70","p1-5|g07|mid|95","p1-6|g09|mid|85","p1-7|g06|mid|205"],"hero":"","bookings":[],"new_bookings":[],"draft_roster":["p1-1|g04|mid|220|false","p1-2|g06|mid|205|false","p1-3|g02|mid|135|false","p1-4|g03|mid|70|false","p1-5|g07|mid|95|false","p1-6|g09|mid|85|false","p1-7|g06|mid|205|false"],"draft_hero":"","boss_lane":"","undo":0},{"gold":185,"draft_gold":185,"ready":true,"earned":980,"spent":1015,"next_seq":8,"roster":["p2-1|g04|bot|220","p2-2|g06|bot|205","p2-3|g02|bot|135","p2-4|g03|bot|70","p2-5|g07|bot|95","p2-6|g09|bot|85","p2-7|g06|bot|205"],"hero":"","bookings":[],"new_bookings":[],"draft_roster":["p2-1|g04|bot|220|false","p2-2|g06|bot|205|false","p2-3|g02|bot|135|false","p2-4|g03|bot|70|false","p2-5|g07|bot|95|false","p2-6|g09|bot|85|false","p2-7|g06|bot|205|false"],"draft_hero":"","boss_lane":"","undo":0},{"gold":185,"draft_gold":185,"ready":true,"earned":980,"spent":1015,"next_seq":8,"roster":["p3-1|g04|top|220","p3-2|g06|top|205","p3-3|g02|top|135","p3-4|g03|top|70","p3-5|g07|top|95","p3-6|g09|top|85","p3-7|g06|top|205"],"hero":"","bookings":[],"new_bookings":[],"draft_roster":["p3-1|g04|top|220|false","p3-2|g06|top|205|false","p3-3|g02|top|135|false","p3-4|g03|top|70|false","p3-5|g07|top|95|false","p3-6|g09|top|85|false","p3-7|g06|top|205|false"],"draft_hero":"","boss_lane":"","undo":0},{"gold":185,"draft_gold":185,"ready":true,"earned":980,"spent":1015,"next_seq":8,"roster":["p4-1|g04|mid|220","p4-2|g06|mid|205","p4-3|g02|mid|135","p4-4|g03|mid|70","p4-5|g07|mid|95","p4-6|g09|mid|85","p4-7|g06|mid|205"],"hero":"","bookings":[],"new_bookings":[],"draft_roster":["p4-1|g04|mid|220|false","p4-2|g06|mid|205|false","p4-3|g02|mid|135|false","p4-4|g03|mid|70|false","p4-5|g07|mid|95|false","p4-6|g09|mid|85|false","p4-7|g06|mid|205|false"],"draft_hero":"","boss_lane":"","undo":0},{"gold":185,"draft_gold":185,"ready":true,"earned":980,"spent":1015,"next_seq":8,"roster":["p5-1|g04|bot|220","p5-2|g06|bot|205","p5-3|g02|bot|135","p5-4|g03|bot|70","p5-5|g07|bot|95","p5-6|g09|bot|85","p5-7|g06|bot|205"],"hero":"","bookings":[],"new_bookings":[],"draft_roster":["p5-1|g04|bot|220|false","p5-2|g06|bot|205|false","p5-3|g02|bot|135|false","p5-4|g03|bot|70|false","p5-5|g07|bot|95|false","p5-6|g09|bot|85|false","p5-7|g06|bot|205|false"],"draft_hero":"","boss_lane":"","undo":0}],"buildings":[7500.0,6000.0,7500.0,6000.0,7500.0,6000.0,9000.0,9000.0,12000.0,7500.0,6000.0,7500.0,6000.0,7500.0,6000.0,9000.0,9000.0,12000.0],"boss":{"next":1,"settled":8,"claim":""},"boss_log":[],"announcements":[],"settlement":{"round":8,"gains":[57,57,57,57,57,57],"income":98,"lost":[],"end_reason":"cleared","combat_time":46.64999999999949,"boss":"none","lane_kills":{"mid":10,"bot":10,"top":10},"xp":{}},"combat":{"round":8,"steps":933,"elapsed":46.64999999999949,"finished":true,"end_reason":"cleared","destroyed":[],"grotto":"none|-1|-1|true","grotto_boss":"","grotto_boss_hp":0.0,"events":72,"mobile":[0,0,0]}}],"results":[]},"bot_match_1":{"title":"Vollständige Bot-Partie Seed 1 bis zum Ancient-Fall","snapshots":[{"label":"round-1","phase":0,"round":2,"winner":-2,"end_note":"","players":[{"gold":123,"draft_gold":123,"ready":true,"earned":88,"spent":185,"next_seq":4,"roster":["p0-1|w03|top|75","p0-2|w05|top|60","p0-3|w01|top|50"],"hero":"","bookings":[],"new_bookings":[],"draft_roster":["p0-1|w03|top|75|false","p0-2|w05|top|60|false","p0-3|w01|top|50|false"],"draft_hero":"","boss_lane":"","undo":0},{"gold":128,"draft_gold":128,"ready":true,"earned":88,"spent":180,"next_seq":4,"roster":["p1-1|g01|mid|45","p1-2|g05|mid|65","p1-3|g03|mid|70"],"hero":"","bookings":[],"new_bookings":[],"draft_roster":["p1-1|g01|mid|45|false","p1-2|g05|mid|65|false","p1-3|g03|mid|70|false"],"draft_hero":"","boss_lane":"","undo":0},{"gold":173,"draft_gold":173,"ready":true,"earned":88,"spent":135,"next_seq":3,"roster":["p2-1|w05|bot|60","p2-2|w03|bot|75"],"hero":"","bookings":[],"new_bookings":[],"draft_roster":["p2-1|w05|bot|60|false","p2-2|w03|bot|75|false"],"draft_hero":"","boss_lane":"","undo":0},{"gold":128,"draft_gold":128,"ready":true,"earned":88,"spent":180,"next_seq":4,"roster":["p3-1|g03|top|70","p3-2|g05|top|65","p3-3|g01|top|45"],"hero":"","bookings":[],"new_bookings":[],"draft_roster":["p3-1|g03|top|70|false","p3-2|g05|top|65|false","p3-3|g01|top|45|false"],"draft_hero":"","boss_lane":"","undo":0},{"gold":123,"draft_gold":123,"ready":true,"earned":88,"spent":185,"next_seq":4,"roster":["p4-1|w03|mid|75","p4-2|w01|mid|50","p4-3|w05|mid|60"],"hero":"","bookings":[],"new_bookings":[],"draft_roster":["p4-1|w03|mid|75|false","p4-2|w01|mid|50|false","p4-3|w05|mid|60|false"],"draft_hero":"","boss_lane":"","undo":0},{"gold":128,"draft_gold":128,"ready":true,"earned":88,"spent":180,"next_seq":4,"roster":["p5-1|g03|bot|70","p5-2|g01|bot|45","p5-3|g05|bot|65"],"hero":"","bookings":[],"new_bookings":[],"draft_roster":["p5-1|g03|bot|70|false","p5-2|g01|bot|45|false","p5-3|g05|bot|65|false"],"draft_hero":"","boss_lane":"","undo":0}],"buildings":[7500.0,6000.0,7500.0,6000.0,7500.0,5882.55,9000.0,9000.0,12000.0,7500.0,5970.1,7500.0,6000.0,7500.0,6000.0,9000.0,9000.0,12000.0],"boss":{"next":1,"settled":1,"claim":""},"boss_log":[],"announcements":[],"settlement":{"round":1,"gains":[18,18,18,18,18,18],"income":70,"lost":[],"end_reason":"cleared","combat_time":44.89999999999959,"boss":"none","lane_kills":{"mid":6,"bot":6,"top":6},"xp":{}},"combat":{"round":1,"steps":898,"elapsed":44.89999999999959,"finished":true,"end_reason":"cleared","destroyed":[],"grotto":"none|-1|-1|true","grotto_boss":"","grotto_boss_hp":0.0,"events":35,"mobile":[0,0,0]}},{"label":"round-2","phase":0,"round":3,"winner":-2,"end_note":"","players":[{"gold":140,"draft_gold":140,"ready":true,"earned":180,"spent":260,"next_seq":5,"roster":["p0-1|w03|top|75","p0-2|w05|top|60","p0-3|w01|top|50","p0-4|w03|top|75"],"hero":"","bookings":[],"new_bookings":[],"draft_roster":["p0-1|w03|top|75|false","p0-2|w05|top|60|false","p0-3|w01|top|50|false","p0-4|w03|top|75|false"],"draft_hero":"","boss_lane":"","undo":0},{"gold":125,"draft_gold":125,"ready":true,"earned":180,"spent":275,"next_seq":5,"roster":["p1-1|g01|mid|45","p1-2|g05|mid|65","p1-3|g03|mid|70","p1-4|g07|mid|95"],"hero":"","bookings":[],"new_bookings":[],"draft_roster":["p1-1|g01|mid|45|false","p1-2|g05|mid|65|false","p1-3|g03|mid|70|false","p1-4|g07|mid|95|false"],"draft_hero":"","boss_lane":"","undo":0},{"gold":105,"draft_gold":105,"ready":true,"earned":180,"spent":295,"next_seq":5,"roster":["p2-1|w05|bot|60","p2-2|w03|bot|75","p2-3|w07|bot|100","p2-4|w05|bot|60"],"hero":"","bookings":[],"new_bookings":[],"draft_roster":["p2-1|w05|bot|60|false","p2-2|w03|bot|75|false","p2-3|w07|bot|100|false","p2-4|w05|bot|60|false"],"draft_hero":"","boss_lane":"","undo":0},{"gold":135,"draft_gold":135,"ready":true,"earned":180,"spent":265,"next_seq":5,"roster":["p3-1|g03|top|70","p3-2|g05|top|65","p3-3|g01|top|45","p3-4|g09|top|85"],"hero":"","bookings":[],"new_bookings":[],"draft_roster":["p3-1|g03|top|70|false","p3-2|g05|top|65|false","p3-3|g01|top|45|false","p3-4|g09|top|85|false"],"draft_hero":"","boss_lane":"","undo":0},{"gold":140,"draft_gold":140,"ready":true,"earned":180,"spent":260,"next_seq":5,"roster":["p4-1|w03|mid|75","p4-2|w01|mid|50","p4-3|w05|mid|60","p4-4|w03|mid|75"],"hero":"","bookings":[],"new_bookings":[],"draft_roster":["p4-1|w03|mid|75|false","p4-2|w01|mid|50|false","p4-3|w05|mid|60|false","p4-4|w03|mid|75|false"],"draft_hero":"","boss_lane":"","undo":0},{"gold":125,"draft_gold":125,"ready":true,"earned":180,"spent":275,"next_seq":5,"roster":["p5-1|g03|bot|70","p5-2|g01|bot|45","p5-3|g05|bot|65","p5-4|g07|bot|95"],"hero":"","bookings":[],"new_bookings":[],"draft_roster":["p5-1|g03|bot|70|false","p5-2|g01|bot|45|false","p5-3|g05|bot|65|false","p5-4|g07|bot|95|false"],"draft_hero":"","boss_lane":"","undo":0}],"buildings":[7500.0,6000.0,7500.0,6000.0,7500.0,5882.55,9000.0,9000.0,12000.0,7500.0,5970.1,7500.0,5890.8,7500.0,5790.700000000003,9000.0,9000.0,12000.0],"boss":{"next":1,"settled":2,"claim":""},"boss_log":[],"announcements":[],"settlement":{"round":2,"gains":[18,18,18,18,18,18],"income":74,"lost":[],"end_reason":"cleared","combat_time":54.69999999999903,"boss":"none","lane_kills":{"mid":6,"bot":6,"top":6},"xp":{}},"combat":{"round":2,"steps":1094,"elapsed":54.69999999999903,"finished":true,"end_reason":"cleared","destroyed":[],"grotto":"none|-1|-1|true","grotto_boss":"","grotto_boss_hp":0.0,"events":42,"mobile":[0,0,0]}},{"label":"round-3","phase":0,"round":4,"winner":-2,"end_note":"","players":[{"gold":150,"draft_gold":150,"ready":true,"earned":290,"spent":360,"next_seq":6,"roster":["p0-1|w03|top|75","p0-2|w05|top|60","p0-3|w01|top|50","p0-4|w03|top|75","p0-5|w07|top|100"],"hero":"","bookings":[],"new_bookings":[],"draft_roster":["p0-1|w03|top|75|false","p0-2|w05|top|60|false","p0-3|w01|top|50|false","p0-4|w03|top|75|false","p0-5|w07|top|100|false"],"draft_hero":"","boss_lane":"","undo":0},{"gold":125,"draft_gold":125,"ready":true,"earned":290,"spent":385,"next_seq":7,"roster":["p1-1|g01|mid|45","p1-2|g05|mid|65","p1-3|g03|mid|70","p1-4|g07|mid|95","p1-5|g01|mid|45","p1-6|g05|mid|65"],"hero":"","bookings":[],"new_bookings":[],"draft_roster":["p1-1|g01|mid|45|false","p1-2|g05|mid|65|false","p1-3|g03|mid|70|false","p1-4|g07|mid|95|false","p1-5|g01|mid|45|false","p1-6|g05|mid|65|false"],"draft_hero":"","boss_lane":"","undo":0},{"gold":165,"draft_gold":165,"ready":true,"earned":290,"spent":345,"next_seq":6,"roster":["p2-1|w05|bot|60","p2-2|w03|bot|75","p2-3|w07|bot|100","p2-4|w05|bot|60","p2-5|w01|bot|50"],"hero":"","bookings":[],"new_bookings":[],"draft_roster":["p2-1|w05|bot|60|false","p2-2|w03|bot|75|false","p2-3|w07|bot|100|false","p2-4|w05|bot|60|false","p2-5|w01|bot|50|false"],"draft_hero":"","boss_lane":"","undo":0},{"gold":175,"draft_gold":175,"ready":true,"earned":290,"spent":335,"next_seq":6,"roster":["p3-1|g03|top|70","p3-2|g05|top|65","p3-3|g01|top|45","p3-4|g09|top|85","p3-5|g03|top|70"],"hero":"","bookings":[],"new_bookings":[],"draft_roster":["p3-1|g03|top|70|false","p3-2|g05|top|65|false","p3-3|g01|top|45|false","p3-4|g09|top|85|false","p3-5|g03|top|70|false"],"draft_hero":"","boss_lane":"","undo":0},{"gold":150,"draft_gold":150,"ready":true,"earned":290,"spent":360,"next_seq":6,"roster":["p4-1|w03|mid|75","p4-2|w01|mid|50","p4-3|w05|mid|60","p4-4|w03|mid|75","p4-5|w07|mid|100"],"hero":"","bookings":[],"new_bookings":[],"draft_roster":["p4-1|w03|mid|75|false","p4-2|w01|mid|50|false","p4-3|w05|mid|60|false","p4-4|w03|mid|75|false","p4-5|w07|mid|100|false"],"draft_hero":"","boss_lane":"","undo":0},{"gold":165,"draft_gold":165,"ready":true,"earned":290,"spent":345,"next_seq":6,"roster":["p5-1|g03|bot|70","p5-2|g01|bot|45","p5-3|g05|bot|65","p5-4|g07|bot|95","p5-5|g03|bot|70"],"hero":"","bookings":[],"new_bookings":[],"draft_roster":["p5-1|g03|bot|70|false","p5-2|g01|bot|45|false","p5-3|g05|bot|65|false","p5-4|g07|bot|95|false","p5-5|g03|bot|70|false"],"draft_hero":"","boss_lane":"","undo":0}],"buildings":[7500.0,6000.0,7500.0,6000.0,7500.0,5882.55,9000.0,9000.0,12000.0,7500.0,5497.4000000000015,7500.0,5579.6,7500.0,5641.200000000004,9000.0,9000.0,12000.0],"boss":{"next":1,"settled":3,"claim":""},"boss_log":[],"announcements":[],"settlement":{"round":3,"gains":[32,32,32,32,32,32],"income":78,"lost":[],"end_reason":"cleared","combat_time":60.29999999999871,"boss":"none","lane_kills":{"mid":6,"bot":6,"top":6},"xp":{}},"combat":{"round":3,"steps":1206,"elapsed":60.29999999999871,"finished":true,"end_reason":"cleared","destroyed":[],"grotto":"none|-1|-1|true","grotto_boss":"","grotto_boss_hp":0.0,"events":49,"mobile":[0,0,0]}},{"label":"round-4","phase":0,"round":5,"winner":-2,"end_note":"","players":[{"gold":122,"draft_gold":122,"ready":true,"earned":412,"spent":510,"next_seq":8,"roster":["p0-1|w03|top|75","p0-2|w05|top|60","p0-3|w01|top|50","p0-4|w03|top|75","p0-5|w07|top|100","p0-6|w09|top|90","p0-7|w05|top|60"],"hero":"","bookings":[],"new_bookings":[],"draft_roster":["p0-1|w03|top|75|false","p0-2|w05|top|60|false","p0-3|w01|top|50|false","p0-4|w03|top|75|false","p0-5|w07|top|100|false","p0-6|w09|top|90|false","p0-7|w05|top|60|false"],"draft_hero":"","boss_lane":"","undo":0},{"gold":132,"draft_gold":132,"ready":true,"earned":412,"spent":500,"next_seq":9,"roster":["p1-1|g01|mid|45","p1-2|g05|mid|65","p1-3|g03|mid|70","p1-4|g07|mid|95","p1-5|g01|mid|45","p1-6|g05|mid|65","p1-7|g01|mid|45","p1-8|g03|mid|70"],"hero":"","bookings":[],"new_bookings":[],"draft_roster":["p1-1|g01|mid|45|false","p1-2|g05|mid|65|false","p1-3|g03|mid|70|false","p1-4|g07|mid|95|false","p1-5|g01|mid|45|false","p1-6|g05|mid|65|false","p1-7|g01|mid|45|false","p1-8|g03|mid|70|false"],"draft_hero":"","boss_lane":"","undo":0},{"gold":137,"draft_gold":137,"ready":true,"earned":412,"spent":495,"next_seq":8,"roster":["p2-1|w05|bot|60","p2-2|w03|bot|75","p2-3|w07|bot|100","p2-4|w05|bot|60","p2-5|w01|bot|50","p2-6|w09|bot|90","p2-7|w05|bot|60"],"hero":"","bookings":[],"new_bookings":[],"draft_roster":["p2-1|w05|bot|60|false","p2-2|w03|bot|75|false","p2-3|w07|bot|100|false","p2-4|w05|bot|60|false","p2-5|w01|bot|50|false","p2-6|w09|bot|90|false","p2-7|w05|bot|60|false"],"draft_hero":"","boss_lane":"","undo":0},{"gold":137,"draft_gold":137,"ready":true,"earned":412,"spent":495,"next_seq":8,"roster":["p3-1|g03|top|70","p3-2|g05|top|65","p3-3|g01|top|45","p3-4|g09|top|85","p3-5|g03|top|70","p3-6|g07|top|95","p3-7|g05|top|65"],"hero":"","bookings":[],"new_bookings":[],"draft_roster":["p3-1|g03|top|70|false","p3-2|g05|top|65|false","p3-3|g01|top|45|false","p3-4|g09|top|85|false","p3-5|g03|top|70|false","p3-6|g07|top|95|false","p3-7|g05|top|65|false"],"draft_hero":"","boss_lane":"","undo":0},{"gold":132,"draft_gold":132,"ready":true,"earned":412,"spent":500,"next_seq":8,"roster":["p4-1|w03|mid|75","p4-2|w01|mid|50","p4-3|w05|mid|60","p4-4|w03|mid|75","p4-5|w07|mid|100","p4-6|w09|mid|90","p4-7|w01|mid|50"],"hero":"","bookings":[],"new_bookings":[],"draft_roster":["p4-1|w03|mid|75|false","p4-2|w01|mid|50|false","p4-3|w05|mid|60|false","p4-4|w03|mid|75|false","p4-5|w07|mid|100|false","p4-6|w09|mid|90|false","p4-7|w01|mid|50|false"],"draft_hero":"","boss_lane":"","undo":0},{"gold":157,"draft_gold":157,"ready":true,"earned":412,"spent":475,"next_seq":8,"roster":["p5-1|g03|bot|70","p5-2|g01|bot|45","p5-3|g05|bot|65","p5-4|g07|bot|95","p5-5|g03|bot|70","p5-6|g09|bot|85","p5-7|g01|bot|45"],"hero":"","bookings":[],"new_bookings":[],"draft_roster":["p5-1|g03|bot|70|false","p5-2|g01|bot|45|false","p5-3|g05|bot|65|false","p5-4|g07|bot|95|false","p5-5|g03|bot|70|false","p5-6|g09|bot|85|false","p5-7|g01|bot|45|false"],"draft_hero":"","boss_lane":"","undo":0}],"buildings":[7500.0,6000.0,7500.0,6000.0,7500.0,5882.55,9000.0,9000.0,12000.0,7500.0,5288.100000000004,7500.0,5376.800000000001,7500.0,4973.300000000012,9000.0,9000.0,12000.0],"boss":{"next":1,"settled":4,"claim":""},"boss_log":[],"announcements":[],"settlement":{"round":4,"gains":[40,40,40,40,40,40],"income":82,"lost":[],"end_reason":"cleared","combat_time":61.69999999999863,"boss":"none","lane_kills":{"mid":8,"bot":8,"top":8},"xp":{}},"combat":{"round":4,"steps":1234,"elapsed":61.69999999999863,"finished":true,"end_reason":"cleared","destroyed":[],"grotto":"none|-1|-1|true","grotto_boss":"","grotto_boss_hp":0.0,"events":67,"mobile":[0,0,0]}},{"label":"round-5","phase":0,"round":6,"winner":-2,"end_note":"","players":[{"gold":153,"draft_gold":153,"ready":true,"earned":543,"spent":610,"next_seq":8,"roster":["p0-1|w03|top|75","p0-2|w05|top|60","p0-3|w02|top|150","p0-4|w03|top|75","p0-5|w07|top|100","p0-6|w09|top|90","p0-7|w05|top|60"],"hero":"","bookings":[],"new_bookings":[],"draft_roster":["p0-1|w03|top|75|false","p0-2|w05|top|60|false","p0-3|w02|top|150|false","p0-4|w03|top|75|false","p0-5|w07|top|100|false","p0-6|w09|top|90|false","p0-7|w05|top|60|false"],"draft_hero":"","boss_lane":"","undo":0},{"gold":173,"draft_gold":173,"ready":true,"earned":543,"spent":590,"next_seq":9,"roster":["p1-1|g02|mid|135","p1-2|g05|mid|65","p1-3|g03|mid|70","p1-4|g07|mid|95","p1-5|g01|mid|45","p1-6|g05|mid|65","p1-7|g01|mid|45","p1-8|g03|mid|70"],"hero":"","bookings":[],"new_bookings":[],"draft_roster":["p1-1|g02|mid|135|false","p1-2|g05|mid|65|false","p1-3|g03|mid|70|false","p1-4|g07|mid|95|false","p1-5|g01|mid|45|false","p1-6|g05|mid|65|false","p1-7|g01|mid|45|false","p1-8|g03|mid|70|false"],"draft_hero":"","boss_lane":"","undo":0},{"gold":168,"draft_gold":168,"ready":true,"earned":543,"spent":595,"next_seq":8,"roster":["p2-1|w05|bot|60","p2-2|w03|bot|75","p2-3|w07|bot|100","p2-4|w05|bot|60","p2-5|w02|bot|150","p2-6|w09|bot|90","p2-7|w05|bot|60"],"hero":"","bookings":[],"new_bookings":[],"draft_roster":["p2-1|w05|bot|60|false","p2-2|w03|bot|75|false","p2-3|w07|bot|100|false","p2-4|w05|bot|60|false","p2-5|w02|bot|150|false","p2-6|w09|bot|90|false","p2-7|w05|bot|60|false"],"draft_hero":"","boss_lane":"","undo":0},{"gold":133,"draft_gold":133,"ready":true,"earned":543,"spent":630,"next_seq":9,"roster":["p3-1|g03|top|70","p3-2|g05|top|65","p3-3|g02|top|135","p3-4|g09|top|85","p3-5|g03|top|70","p3-6|g07|top|95","p3-7|g05|top|65","p3-8|g01|top|45"],"hero":"","bookings":[],"new_bookings":[],"draft_roster":["p3-1|g03|top|70|false","p3-2|g05|top|65|false","p3-3|g02|top|135|false","p3-4|g09|top|85|false","p3-5|g03|top|70|false","p3-6|g07|top|95|false","p3-7|g05|top|65|false","p3-8|g01|top|45|false"],"draft_hero":"","boss_lane":"","undo":0},{"gold":163,"draft_gold":163,"ready":true,"earned":543,"spent":600,"next_seq":8,"roster":["p4-1|w03|mid|75","p4-2|w02|mid|150","p4-3|w05|mid|60","p4-4|w03|mid|75","p4-5|w07|mid|100","p4-6|w09|mid|90","p4-7|w01|mid|50"],"hero":"","bookings":[],"new_bookings":[],"draft_roster":["p4-1|w03|mid|75|false","p4-2|w02|mid|150|false","p4-3|w05|mid|60|false","p4-4|w03|mid|75|false","p4-5|w07|mid|100|false","p4-6|w09|mid|90|false","p4-7|w01|mid|50|false"],"draft_hero":"","boss_lane":"","undo":0},{"gold":133,"draft_gold":133,"ready":true,"earned":543,"spent":630,"next_seq":9,"roster":["p5-1|g03|bot|70","p5-2|g02|bot|135","p5-3|g05|bot|65","p5-4|g07|bot|95","p5-5|g03|bot|70","p5-6|g09|bot|85","p5-7|g01|bot|45","p5-8|g05|bot|65"],"hero":"","bookings":[],"new_bookings":[],"draft_roster":["p5-1|g03|bot|70|false","p5-2|g02|bot|135|false","p5-3|g05|bot|65|false","p5-4|g07|bot|95|false","p5-5|g03|bot|70|false","p5-6|g09|bot|85|false","p5-7|g01|bot|45|false","p5-8|g05|bot|65|false"],"draft_hero":"","boss_lane":"","undo":0}],"buildings":[7500.0,5614.118399999997,7500.0,5979.6576,7500.0,5590.268399999996,9000.0,9000.0,12000.0,7500.0,5288.100000000004,7500.0,5376.800000000001,7500.0,4973.300000000012,9000.0,9000.0,12000.0],"boss":{"next":1,"settled":5,"claim":""},"boss_log":[],"announcements":[],"settlement":{"round":5,"gains":[45,45,45,45,45,45],"income":86,"lost":[],"end_reason":"cleared","combat_time":56.49999999999893,"boss":"none","lane_kills":{"mid":8,"bot":8,"top":8},"xp":{}},"combat":{"round":5,"steps":1130,"elapsed":56.49999999999893,"finished":true,"end_reason":"cleared","destroyed":[],"grotto":"none|-1|-1|true","grotto_boss":"","grotto_boss_hp":0.0,"events":69,"mobile":[0,0,0]}},{"label":"round-6","phase":0,"round":7,"winner":-2,"end_note":"","players":[{"gold":148,"draft_gold":148,"ready":true,"earned":673,"spent":745,"next_seq":8,"roster":["p0-1|w03|top|75","p0-2|w06|top|195","p0-3|w02|top|150","p0-4|w03|top|75","p0-5|w07|top|100","p0-6|w09|top|90","p0-7|w05|top|60"],"hero":"","bookings":[],"new_bookings":[],"draft_roster":["p0-1|w03|top|75|false","p0-2|w06|top|195|false","p0-3|w02|top|150|false","p0-4|w03|top|75|false","p0-5|w07|top|100|false","p0-6|w09|top|90|false","p0-7|w05|top|60|false"],"draft_hero":"","boss_lane":"","undo":0},{"gold":213,"draft_gold":213,"ready":true,"earned":673,"spent":680,"next_seq":9,"roster":["p1-1|g02|mid|135","p1-2|g05|mid|65","p1-3|g03|mid|70","p1-4|g07|mid|95","p1-5|g02|mid|135","p1-6|g05|mid|65","p1-7|g01|mid|45","p1-8|g03|mid|70"],"hero":"","bookings":[],"new_bookings":[],"draft_roster":["p1-1|g02|mid|135|false","p1-2|g05|mid|65|false","p1-3|g03|mid|70|false","p1-4|g07|mid|95|false","p1-5|g02|mid|135|false","p1-6|g05|mid|65|false","p1-7|g01|mid|45|false","p1-8|g03|mid|70|false"],"draft_hero":"","boss_lane":"","undo":0},{"gold":163,"draft_gold":163,"ready":true,"earned":673,"spent":730,"next_seq":8,"roster":["p2-1|w06|bot|195","p2-2|w03|bot|75","p2-3|w07|bot|100","p2-4|w05|bot|60","p2-5|w02|bot|150","p2-6|w09|bot|90","p2-7|w05|bot|60"],"hero":"","bookings":[],"new_bookings":[],"draft_roster":["p2-1|w06|bot|195|false","p2-2|w03|bot|75|false","p2-3|w07|bot|100|false","p2-4|w05|bot|60|false","p2-5|w02|bot|150|false","p2-6|w09|bot|90|false","p2-7|w05|bot|60|false"],"draft_hero":"","boss_lane":"","undo":0},{"gold":173,"draft_gold":173,"ready":true,"earned":673,"spent":720,"next_seq":9,"roster":["p3-1|g03|top|70","p3-2|g05|top|65","p3-3|g02|top|135","p3-4|g09|top|85","p3-5|g03|top|70","p3-6|g07|top|95","p3-7|g05|top|65","p3-8|g02|top|135"],"hero":"","bookings":[],"new_bookings":[],"draft_roster":["p3-1|g03|top|70|false","p3-2|g05|top|65|false","p3-3|g02|top|135|false","p3-4|g09|top|85|false","p3-5|g03|top|70|false","p3-6|g07|top|95|false","p3-7|g05|top|65|false","p3-8|g02|top|135|false"],"draft_hero":"","boss_lane":"","undo":0},{"gold":193,"draft_gold":193,"ready":true,"earned":673,"spent":700,"next_seq":8,"roster":["p4-1|w03|mid|75","p4-2|w02|mid|150","p4-3|w05|mid|60","p4-4|w03|mid|75","p4-5|w07|mid|100","p4-6|w09|mid|90","p4-7|w02|mid|150"],"hero":"","bookings":[],"new_bookings":[],"draft_roster":["p4-1|w03|mid|75|false","p4-2|w02|mid|150|false","p4-3|w05|mid|60|false","p4-4|w03|mid|75|false","p4-5|w07|mid|100|false","p4-6|w09|mid|90|false","p4-7|w02|mid|150|false"],"draft_hero":"","boss_lane":"","undo":0},{"gold":173,"draft_gold":173,"ready":true,"earned":673,"spent":720,"next_seq":9,"roster":["p5-1|g03|bot|70","p5-2|g02|bot|135","p5-3|g05|bot|65","p5-4|g07|bot|95","p5-5|g03|bot|70","p5-6|g09|bot|85","p5-7|g02|bot|135","p5-8|g05|bot|65"],"hero":"","bookings":[],"new_bookings":[],"draft_roster":["p5-1|g03|bot|70|false","p5-2|g02|bot|135|false","p5-3|g05|bot|65|false","p5-4|g07|bot|95|false","p5-5|g03|bot|70|false","p5-6|g09|bot|85|false","p5-7|g02|bot|135|false","p5-8|g05|bot|65|false"],"draft_hero":"","boss_lane":"","undo":0}],"buildings":[7500.0,5614.118399999997,7500.0,5979.6576,7500.0,5590.268399999996,9000.0,9000.0,12000.0,7500.0,4122.065000000002,7500.0,4954.039999999998,7500.0,3861.800000000013,9000.0,9000.0,12000.0],"boss":{"next":1,"settled":6,"claim":""},"boss_log":[],"announcements":[],"settlement":{"round":6,"gains":[40,40,40,40,40,40],"income":90,"lost":[],"end_reason":"cleared","combat_time":59.09999999999878,"boss":"none","lane_kills":{"mid":8,"bot":8,"top":8},"xp":{}},"combat":{"round":6,"steps":1182,"elapsed":59.09999999999878,"finished":true,"end_reason":"cleared","destroyed":[],"grotto":"none|-1|-1|true","grotto_boss":"","grotto_boss_hp":0.0,"events":69,"mobile":[0,0,0]}},{"label":"round-7","phase":0,"round":8,"winner":-2,"end_note":"","players":[{"gold":165,"draft_gold":165,"ready":true,"earned":825,"spent":880,"next_seq":8,"roster":["p0-1|w03|top|75","p0-2|w06|top|195","p0-3|w02|top|150","p0-4|w03|top|75","p0-5|w07|top|100","p0-6|w09|top|90","p0-7|w06|top|195"],"hero":"","bookings":[],"new_bookings":[],"draft_roster":["p0-1|w03|top|75|false","p0-2|w06|top|195|false","p0-3|w02|top|150|false","p0-4|w03|top|75|false","p0-5|w07|top|100|false","p0-6|w09|top|90|false","p0-7|w06|top|195|false"],"draft_hero":"","boss_lane":"","undo":0},{"gold":190,"draft_gold":190,"ready":true,"earned":825,"spent":855,"next_seq":10,"roster":["p1-1|g02|mid|135","p1-2|g05|mid|65","p1-3|g03|mid|70","p1-4|g07|mid|95","p1-5|g02|mid|135","p1-6|g05|mid|65","p1-7|g02|mid|135","p1-8|g03|mid|70","p1-9|g09|mid|85"],"hero":"","bookings":[],"new_bookings":[],"draft_roster":["p1-1|g02|mid|135|false","p1-2|g05|mid|65|false","p1-3|g03|mid|70|false","p1-4|g07|mid|95|false","p1-5|g02|mid|135|false","p1-6|g05|mid|65|false","p1-7|g02|mid|135|false","p1-8|g03|mid|70|false","p1-9|g09|mid|85|false"],"draft_hero":"","boss_lane":"","undo":0},{"gold":180,"draft_gold":180,"ready":true,"earned":825,"spent":865,"next_seq":8,"roster":["p2-1|w06|bot|195","p2-2|w03|bot|75","p2-3|w07|bot|100","p2-4|w06|bot|195","p2-5|w02|bot|150","p2-6|w09|bot|90","p2-7|w05|bot|60"],"hero":"","bookings":[],"new_bookings":[],"draft_roster":["p2-1|w06|bot|195|false","p2-2|w03|bot|75|false","p2-3|w07|bot|100|false","p2-4|w06|bot|195|false","p2-5|w02|bot|150|false","p2-6|w09|bot|90|false","p2-7|w05|bot|60|false"],"draft_hero":"","boss_lane":"","undo":0},{"gold":185,"draft_gold":185,"ready":true,"earned":825,"spent":860,"next_seq":9,"roster":["p3-1|g03|top|70","p3-2|g06|top|205","p3-3|g02|top|135","p3-4|g09|top|85","p3-5|g03|top|70","p3-6|g07|top|95","p3-7|g05|top|65","p3-8|g02|top|135"],"hero":"","bookings":[],"new_bookings":[],"draft_roster":["p3-1|g03|top|70|false","p3-2|g06|top|205|false","p3-3|g02|top|135|false","p3-4|g09|top|85|false","p3-5|g03|top|70|false","p3-6|g07|top|95|false","p3-7|g05|top|65|false","p3-8|g02|top|135|false"],"draft_hero":"","boss_lane":"","undo":0},{"gold":210,"draft_gold":210,"ready":true,"earned":825,"spent":835,"next_seq":8,"roster":["p4-1|w03|mid|75","p4-2|w02|mid|150","p4-3|w06|mid|195","p4-4|w03|mid|75","p4-5|w07|mid|100","p4-6|w09|mid|90","p4-7|w02|mid|150"],"hero":"","bookings":[],"new_bookings":[],"draft_roster":["p4-1|w03|mid|75|false","p4-2|w02|mid|150|false","p4-3|w06|mid|195|false","p4-4|w03|mid|75|false","p4-5|w07|mid|100|false","p4-6|w09|mid|90|false","p4-7|w02|mid|150|false"],"draft_hero":"","boss_lane":"","undo":0},{"gold":185,"draft_gold":185,"ready":true,"earned":825,"spent":860,"next_seq":9,"roster":["p5-1|g03|bot|70","p5-2|g02|bot|135","p5-3|g06|bot|205","p5-4|g07|bot|95","p5-5|g03|bot|70","p5-6|g09|bot|85","p5-7|g02|bot|135","p5-8|g05|bot|65"],"hero":"","bookings":[],"new_bookings":[],"draft_roster":["p5-1|g03|bot|70|false","p5-2|g02|bot|135|false","p5-3|g06|bot|205|false","p5-4|g07|bot|95|false","p5-5|g03|bot|70|false","p5-6|g09|bot|85|false","p5-7|g02|bot|135|false","p5-8|g05|bot|65|false"],"draft_hero":"","boss_lane":"","undo":0}],"buildings":[7500.0,5614.118399999997,7500.0,5979.6576,7500.0,5590.268399999996,9000.0,9000.0,12000.0,7500.0,3362.376200000001,7500.0,4536.084800000002,7500.0,3544.600000000012,9000.0,9000.0,12000.0],"boss":{"next":1,"settled":7,"claim":""},"boss_log":[],"announcements":[],"settlement":{"round":7,"gains":[58,58,58,58,58,58],"income":94,"lost":[],"end_reason":"cleared","combat_time":55.499999999998984,"boss":"none","lane_kills":{"mid":10,"bot":10,"top":10},"xp":{}},"combat":{"round":7,"steps":1110,"elapsed":55.499999999998984,"finished":true,"end_reason":"cleared","destroyed":[],"grotto":"none|-1|-1|true","grotto_boss":"","grotto_boss_hp":0.0,"events":76,"mobile":[0,0,0]}},{"label":"round-8","phase":0,"round":9,"winner":-2,"end_note":"","players":[{"gold":165,"draft_gold":165,"ready":true,"earned":980,"spent":1035,"next_seq":8,"roster":["p0-1|w04|top|230","p0-2|w06|top|195","p0-3|w02|top|150","p0-4|w03|top|75","p0-5|w07|top|100","p0-6|w09|top|90","p0-7|w06|top|195"],"hero":"","bookings":[],"new_bookings":[],"draft_roster":["p0-1|w04|top|230|false","p0-2|w06|top|195|false","p0-3|w02|top|150|false","p0-4|w03|top|75|false","p0-5|w07|top|100|false","p0-6|w09|top|90|false","p0-7|w06|top|195|false"],"draft_hero":"","boss_lane":"","undo":0},{"gold":160,"draft_gold":160,"ready":true,"earned":980,"spent":1040,"next_seq":11,"roster":["p1-1|g02|mid|135","p1-2|g06|mid|205","p1-3|g03|mid|70","p1-4|g07|mid|95","p1-5|g02|mid|135","p1-6|g05|mid|65","p1-7|g02|mid|135","p1-8|g03|mid|70","p1-9|g09|mid|85","p1-10|g01|mid|45"],"hero":"","bookings":[],"new_bookings":[],"draft_roster":["p1-1|g02|mid|135|false","p1-2|g06|mid|205|false","p1-3|g03|mid|70|false","p1-4|g07|mid|95|false","p1-5|g02|mid|135|false","p1-6|g05|mid|65|false","p1-7|g02|mid|135|false","p1-8|g03|mid|70|false","p1-9|g09|mid|85|false","p1-10|g01|mid|45|false"],"draft_hero":"","boss_lane":"","undo":0},{"gold":200,"draft_gold":200,"ready":true,"earned":980,"spent":1000,"next_seq":8,"roster":["p2-1|w06|bot|195","p2-2|w03|bot|75","p2-3|w07|bot|100","p2-4|w06|bot|195","p2-5|w02|bot|150","p2-6|w09|bot|90","p2-7|w06|bot|195"],"hero":"","bookings":[],"new_bookings":[],"draft_roster":["p2-1|w06|bot|195|false","p2-2|w03|bot|75|false","p2-3|w07|bot|100|false","p2-4|w06|bot|195|false","p2-5|w02|bot|150|false","p2-6|w09|bot|90|false","p2-7|w06|bot|195|false"],"draft_hero":"","boss_lane":"","undo":0},{"gold":200,"draft_gold":200,"ready":true,"earned":980,"spent":1000,"next_seq":9,"roster":["p3-1|g03|top|70","p3-2|g06|top|205","p3-3|g02|top|135","p3-4|g09|top|85","p3-5|g03|top|70","p3-6|g07|top|95","p3-7|g06|top|205","p3-8|g02|top|135"],"hero":"","bookings":[],"new_bookings":[],"draft_roster":["p3-1|g03|top|70|false","p3-2|g06|top|205|false","p3-3|g02|top|135|false","p3-4|g09|top|85|false","p3-5|g03|top|70|false","p3-6|g07|top|95|false","p3-7|g06|top|205|false","p3-8|g02|top|135|false"],"draft_hero":"","boss_lane":"","undo":0},{"gold":210,"draft_gold":210,"ready":true,"earned":980,"spent":990,"next_seq":8,"roster":["p4-1|w04|mid|230","p4-2|w02|mid|150","p4-3|w06|mid|195","p4-4|w03|mid|75","p4-5|w07|mid|100","p4-6|w09|mid|90","p4-7|w02|mid|150"],"hero":"","bookings":[],"new_bookings":[],"draft_roster":["p4-1|w04|mid|230|false","p4-2|w02|mid|150|false","p4-3|w06|mid|195|false","p4-4|w03|mid|75|false","p4-5|w07|mid|100|false","p4-6|w09|mid|90|false","p4-7|w02|mid|150|false"],"draft_hero":"","boss_lane":"","undo":0},{"gold":200,"draft_gold":200,"ready":true,"earned":980,"spent":1000,"next_seq":9,"roster":["p5-1|g03|bot|70","p5-2|g02|bot|135","p5-3|g06|bot|205","p5-4|g07|bot|95","p5-5|g03|bot|70","p5-6|g09|bot|85","p5-7|g02|bot|135","p5-8|g06|bot|205"],"hero":"","bookings":[],"new_bookings":[],"draft_roster":["p5-1|g03|bot|70|false","p5-2|g02|bot|135|false","p5-3|g06|bot|205|false","p5-4|g07|bot|95|false","p5-5|g03|bot|70|false","p5-6|g09|bot|85|false","p5-7|g02|bot|135|false","p5-8|g06|bot|205|false"],"draft_hero":"","boss_lane":"","undo":0}],"buildings":[7500.0,5614.118399999997,7500.0,5979.6576,7500.0,5590.268399999996,9000.0,9000.0,12000.0,7500.0,2965.8762,7500.0,3157.557000000002,7500.0,2037.900000000009,9000.0,9000.0,12000.0],"boss":{"next":1,"settled":8,"claim":""},"boss_log":[],"announcements":[],"settlement":{"round":8,"gains":[57,57,57,57,57,57],"income":98,"lost":[],"end_reason":"cleared","combat_time":53.29999999999911,"boss":"none","lane_kills":{"mid":10,"top":10,"bot":10},"xp":{}},"combat":{"round":8,"steps":1066,"elapsed":53.29999999999911,"finished":true,"end_reason":"cleared","destroyed":[],"grotto":"none|-1|-1|true","grotto_boss":"","grotto_boss_hp":0.0,"events":77,"mobile":[0,0,0]}},{"label":"round-9","phase":0,"round":10,"winner":-2,"end_note":"","players":[{"gold":178,"draft_gold":178,"ready":true,"earned":1148,"spent":1190,"next_seq":8,"roster":["p0-1|w04|top|230","p0-2|w06|top|195","p0-3|w02|top|150","p0-4|w04|top|230","p0-5|w07|top|100","p0-6|w09|top|90","p0-7|w06|top|195"],"hero":"","bookings":[],"new_bookings":[],"draft_roster":["p0-1|w04|top|230|false","p0-2|w06|top|195|false","p0-3|w02|top|150|false","p0-4|w04|top|230|false","p0-5|w07|top|100|false","p0-6|w09|top|90|false","p0-7|w06|top|195|false"],"draft_hero":"","boss_lane":"","undo":0},{"gold":173,"draft_gold":173,"ready":true,"earned":1148,"spent":1195,"next_seq":12,"roster":["p1-1|g02|mid|135","p1-2|g06|mid|205","p1-3|g03|mid|70","p1-4|g07|mid|95","p1-5|g02|mid|135","p1-6|g05|mid|65","p1-7|g02|mid|135","p1-8|g03|mid|70","p1-9|g09|mid|85","p1-10|g02|mid|135","p1-11|g05|mid|65"],"hero":"","bookings":[],"new_bookings":[],"draft_roster":["p1-1|g02|mid|135|false","p1-2|g06|mid|205|false","p1-3|g03|mid|70|false","p1-4|g07|mid|95|false","p1-5|g02|mid|135|false","p1-6|g05|mid|65|false","p1-7|g02|mid|135|false","p1-8|g03|mid|70|false","p1-9|g09|mid|85|false","p1-10|g02|mid|135|false","p1-11|g05|mid|65|false"],"draft_hero":"","boss_lane":"","undo":0},{"gold":218,"draft_gold":218,"ready":true,"earned":1148,"spent":1150,"next_seq":9,"roster":["p2-1|w06|bot|195","p2-2|w03|bot|75","p2-3|w07|bot|100","p2-4|w06|bot|195","p2-5|w02|bot|150","p2-6|w09|bot|90","p2-7|w06|bot|195"],"hero":"","bookings":["c2-8|ch_druck|bot|150|10"],"new_bookings":[],"draft_roster":["p2-1|w06|bot|195|false","p2-2|w03|bot|75|false","p2-3|w07|bot|100|false","p2-4|w06|bot|195|false","p2-5|w02|bot|150|false","p2-6|w09|bot|90|false","p2-7|w06|bot|195|false"],"draft_hero":"","boss_lane":"","undo":0},{"gold":218,"draft_gold":218,"ready":true,"earned":1148,"spent":1150,"next_seq":10,"roster":["p3-1|g03|top|70","p3-2|g06|top|205","p3-3|g02|top|135","p3-4|g09|top|85","p3-5|g03|top|70","p3-6|g07|top|95","p3-7|g06|top|205","p3-8|g02|top|135"],"hero":"","bookings":["c3-9|ch_schutz|top|150|10"],"new_bookings":[],"draft_roster":["p3-1|g03|top|70|false","p3-2|g06|top|205|false","p3-3|g02|top|135|false","p3-4|g09|top|85|false","p3-5|g03|top|70|false","p3-6|g07|top|95|false","p3-7|g06|top|205|false","p3-8|g02|top|135|false"],"draft_hero":"","boss_lane":"","undo":0},{"gold":223,"draft_gold":223,"ready":true,"earned":1148,"spent":1145,"next_seq":8,"roster":["p4-1|w04|mid|230","p4-2|w02|mid|150","p4-3|w06|mid|195","p4-4|w04|mid|230","p4-5|w07|mid|100","p4-6|w09|mid|90","p4-7|w02|mid|150"],"hero":"","bookings":[],"new_bookings":[],"draft_roster":["p4-1|w04|mid|230|false","p4-2|w02|mid|150|false","p4-3|w06|mid|195|false","p4-4|w04|mid|230|false","p4-5|w07|mid|100|false","p4-6|w09|mid|90|false","p4-7|w02|mid|150|false"],"draft_hero":"","boss_lane":"","undo":0},{"gold":218,"draft_gold":218,"ready":true,"earned":1148,"spent":1150,"next_seq":9,"roster":["p5-1|g04|bot|220","p5-2|g02|bot|135","p5-3|g06|bot|205","p5-4|g07|bot|95","p5-5|g03|bot|70","p5-6|g09|bot|85","p5-7|g02|bot|135","p5-8|g06|bot|205"],"hero":"","bookings":[],"new_bookings":[],"draft_roster":["p5-1|g04|bot|220|false","p5-2|g02|bot|135|false","p5-3|g06|bot|205|false","p5-4|g07|bot|95|false","p5-5|g03|bot|70|false","p5-6|g09|bot|85|false","p5-7|g02|bot|135|false","p5-8|g06|bot|205|false"],"draft_hero":"","boss_lane":"","undo":0}],"buildings":[7500.0,5614.118399999997,7500.0,5979.6576,7500.0,1170.1655999999975,9000.0,9000.0,12000.0,7500.0,355.22419999999954,7500.0,156.7788000000039,7500.0,2037.900000000009,9000.0,9000.0,12000.0],"boss":{"next":1,"settled":9,"claim":""},"boss_log":[],"announcements":["champion|0|2|bot|ch_druck|0","champion|1|3|top|ch_schutz|0"],"settlement":{"round":9,"gains":[66,66,66,66,66,66],"income":102,"lost":[],"end_reason":"cleared","combat_time":66.29999999999838,"boss":"none","lane_kills":{"mid":10,"bot":10,"top":10},"xp":{}},"combat":{"round":9,"steps":1326,"elapsed":66.29999999999838,"finished":true,"end_reason":"cleared","destroyed":[],"grotto":"none|-1|-1|true","grotto_boss":"","grotto_boss_hp":0.0,"events":78,"mobile":[0,0,0]}},{"label":"round-10","phase":0,"round":11,"winner":-2,"end_note":"","players":[{"gold":422,"draft_gold":422,"ready":true,"earned":1517,"spent":1315,"next_seq":10,"roster":["p0-1|w04|top|230","p0-2|w06|top|195","p0-3|w02|top|150","p0-4|w04|top|230","p0-5|w07|top|100","p0-6|w09|top|90","p0-7|w06|top|195","p0-8|w03|top|75","p0-9|w01|top|50"],"hero":"","bookings":[],"new_bookings":[],"draft_roster":["p0-1|w04|top|230|false","p0-2|w06|top|195|false","p0-3|w02|top|150|false","p0-4|w04|top|230|false","p0-5|w07|top|100|false","p0-6|w09|top|90|false","p0-7|w06|top|195|false","p0-8|w03|top|75|false","p0-9|w01|top|50|false"],"draft_hero":"","boss_lane":"","undo":0},{"gold":337,"draft_gold":337,"ready":true,"earned":1452,"spent":1335,"next_seq":12,"roster":["p1-1|g02|mid|135","p1-2|g06|mid|205","p1-3|g03|mid|70","p1-4|g07|mid|95","p1-5|g02|mid|135","p1-6|g06|mid|205","p1-7|g02|mid|135","p1-8|g03|mid|70","p1-9|g09|mid|85","p1-10|g02|mid|135","p1-11|g05|mid|65"],"hero":"","bookings":[],"new_bookings":[],"draft_roster":["p1-1|g02|mid|135|false","p1-2|g06|mid|205|false","p1-3|g03|mid|70|false","p1-4|g07|mid|95|false","p1-5|g02|mid|135|false","p1-6|g06|mid|205|false","p1-7|g02|mid|135|false","p1-8|g03|mid|70|false","p1-9|g09|mid|85|false","p1-10|g02|mid|135|false","p1-11|g05|mid|65|false"],"draft_hero":"","boss_lane":"","undo":0},{"gold":366,"draft_gold":366,"ready":true,"earned":1451,"spent":1305,"next_seq":9,"roster":["p2-1|w06|bot|195","p2-2|w04|bot|230","p2-3|w07|bot|100","p2-4|w06|bot|195","p2-5|w02|bot|150","p2-6|w09|bot|90","p2-7|w06|bot|195"],"hero":"","bookings":[],"new_bookings":[],"draft_roster":["p2-1|w06|bot|195|false","p2-2|w04|bot|230|false","p2-3|w07|bot|100|false","p2-4|w06|bot|195|false","p2-5|w02|bot|150|false","p2-6|w09|bot|90|false","p2-7|w06|bot|195|false"],"draft_hero":"","boss_lane":"","undo":0},{"gold":272,"draft_gold":272,"ready":true,"earned":1352,"spent":1300,"next_seq":10,"roster":["p3-1|g04|top|220","p3-2|g06|top|205","p3-3|g02|top|135","p3-4|g09|top|85","p3-5|g03|top|70","p3-6|g07|top|95","p3-7|g06|top|205","p3-8|g02|top|135"],"hero":"","bookings":[],"new_bookings":[],"draft_roster":["p3-1|g04|top|220|false","p3-2|g06|top|205|false","p3-3|g02|top|135|false","p3-4|g09|top|85|false","p3-5|g03|top|70|false","p3-6|g07|top|95|false","p3-7|g06|top|205|false","p3-8|g02|top|135|false"],"draft_hero":"","boss_lane":"","undo":0},{"gold":247,"draft_gold":247,"ready":true,"earned":1352,"spent":1325,"next_seq":9,"roster":["p4-1|w04|mid|230","p4-2|w02|mid|150","p4-3|w06|mid|195","p4-4|w04|mid|230","p4-5|w07|mid|100","p4-6|w09|mid|90","p4-7|w02|mid|150"],"hero":"","bookings":["c4-8|ch_belagerung|mid|180|11"],"new_bookings":[],"draft_roster":["p4-1|w04|mid|230|false","p4-2|w02|mid|150|false","p4-3|w06|mid|195|false","p4-4|w04|mid|230|false","p4-5|w07|mid|100|false","p4-6|w09|mid|90|false","p4-7|w02|mid|150|false"],"draft_hero":"","boss_lane":"","undo":0},{"gold":336,"draft_gold":336,"ready":true,"earned":1416,"spent":1300,"next_seq":9,"roster":["p5-1|g04|bot|220","p5-2|g02|bot|135","p5-3|g06|bot|205","p5-4|g07|bot|95","p5-5|g04|bot|220","p5-6|g09|bot|85","p5-7|g02|bot|135","p5-8|g06|bot|205"],"hero":"","bookings":[],"new_bookings":[],"draft_roster":["p5-1|g04|bot|220|false","p5-2|g02|bot|135|false","p5-3|g06|bot|205|false","p5-4|g07|bot|95|false","p5-5|g04|bot|220|false","p5-6|g09|bot|85|false","p5-7|g02|bot|135|false","p5-8|g06|bot|205|false"],"draft_hero":"","boss_lane":"","undo":0}],"buildings":[7500.0,3643.2949999999964,7500.0,5979.6576,7500.0,1170.1655999999975,9000.0,9000.0,12000.0,7500.0,355.22419999999954,2223.154199999998,0.0,7024.199999999999,0.0,9000.0,9000.0,12000.0],"boss":{"next":1,"settled":10,"claim":""},"boss_log":[],"announcements":["champion|1|4|mid|ch_belagerung|0"],"settlement":{"round":10,"gains":[263,198,197,98,98,162],"income":106,"lost":["rot_mid_outer","rot_bot_outer"],"end_reason":"cleared","combat_time":72.14999999999804,"boss":"none","lane_kills":{"mid":12,"bot":13,"top":13},"xp":{}},"combat":{"round":10,"steps":1443,"elapsed":72.14999999999804,"finished":true,"end_reason":"cleared","destroyed":[],"grotto":"none|-1|-1|true","grotto_boss":"","grotto_boss_hp":0.0,"events":90,"mobile":[0,0,0]}},{"label":"round-11","phase":0,"round":12,"winner":-2,"end_note":"","players":[{"gold":413,"draft_gold":413,"ready":true,"earned":1868,"spent":1675,"next_seq":11,"roster":["p0-1|w04|top|230","p0-2|w06|top|195","p0-3|w02|top|150","p0-4|w04|top|230","p0-5|w07|top|100","p0-6|w09|top|90","p0-7|w06|top|195","p0-8|w03|top|75","p0-9|w02|top|150"],"hero":"h0-10|held_ringborke|159|top|||260|false|","bookings":[],"new_bookings":[],"draft_roster":["p0-1|w04|top|230|false","p0-2|w06|top|195|false","p0-3|w02|top|150|false","p0-4|w04|top|230|false","p0-5|w07|top|100|false","p0-6|w09|top|90|false","p0-7|w06|top|195|false","p0-8|w03|top|75|false","p0-9|w02|top|150|false"],"draft_hero":"h0-10|held_ringborke|159|top|||260|false|","boss_lane":"","undo":0},{"gold":495,"draft_gold":495,"ready":true,"earned":1870,"spent":1595,"next_seq":13,"roster":["p1-1|g02|mid|135","p1-2|g06|mid|205","p1-3|g03|mid|70","p1-4|g07|mid|95","p1-5|g02|mid|135","p1-6|g06|mid|205","p1-7|g02|mid|135","p1-8|g03|mid|70","p1-9|g09|mid|85","p1-10|g02|mid|135","p1-11|g05|mid|65"],"hero":"h1-12|held_funkenlanze|348|mid|||260|false|","bookings":[],"new_bookings":[],"draft_roster":["p1-1|g02|mid|135|false","p1-2|g06|mid|205|false","p1-3|g03|mid|70|false","p1-4|g07|mid|95|false","p1-5|g02|mid|135|false","p1-6|g06|mid|205|false","p1-7|g02|mid|135|false","p1-8|g03|mid|70|false","p1-9|g09|mid|85|false","p1-10|g02|mid|135|false","p1-11|g05|mid|65|false"],"draft_hero":"h1-12|held_funkenlanze|348|mid|||260|false|","boss_lane":"","undo":0},{"gold":382,"draft_gold":382,"ready":true,"earned":1802,"spent":1640,"next_seq":11,"roster":["p2-1|w06|bot|195","p2-2|w04|bot|230","p2-3|w07|bot|100","p2-4|w06|bot|195","p2-5|w02|bot|150","p2-6|w09|bot|90","p2-7|w06|bot|195","p2-10|w03|bot|75"],"hero":"h2-9|held_funkenlanze|326|bot|||260|false|","bookings":[],"new_bookings":[],"draft_roster":["p2-1|w06|bot|195|false","p2-2|w04|bot|230|false","p2-3|w07|bot|100|false","p2-4|w06|bot|195|false","p2-5|w02|bot|150|false","p2-6|w09|bot|90|false","p2-7|w06|bot|195|false","p2-10|w03|bot|75|false"],"draft_hero":"h2-9|held_funkenlanze|326|bot|||260|false|","boss_lane":"","undo":0},{"gold":270,"draft_gold":270,"ready":true,"earned":1610,"spent":1560,"next_seq":11,"roster":["p3-1|g04|top|220","p3-2|g06|top|205","p3-3|g02|top|135","p3-4|g09|top|85","p3-5|g03|top|70","p3-6|g07|top|95","p3-7|g06|top|205","p3-8|g02|top|135"],"hero":"h3-10|held_quellgeflecht|227|top|||260|false|","bookings":[],"new_bookings":[],"draft_roster":["p3-1|g04|top|220|false","p3-2|g06|top|205|false","p3-3|g02|top|135|false","p3-4|g09|top|85|false","p3-5|g03|top|70|false","p3-6|g07|top|95|false","p3-7|g06|top|205|false","p3-8|g02|top|135|false"],"draft_hero":"h3-10|held_quellgeflecht|227|top|||260|false|","boss_lane":"","undo":0},{"gold":325,"draft_gold":325,"ready":true,"earned":1610,"spent":1505,"next_seq":9,"roster":["p4-1|w04|mid|230","p4-2|w02|mid|150","p4-3|w06|mid|195","p4-4|w04|mid|230","p4-5|w07|mid|100","p4-6|w10|mid|270","p4-7|w02|mid|150"],"hero":"","bookings":[],"new_bookings":[],"draft_roster":["p4-1|w04|mid|230|false","p4-2|w02|mid|150|false","p4-3|w06|mid|195|false","p4-4|w04|mid|230|false","p4-5|w07|mid|100|false","p4-6|w10|mid|270|false","p4-7|w02|mid|150|false"],"draft_hero":"","boss_lane":"","undo":0},{"gold":264,"draft_gold":264,"ready":true,"earned":1674,"spent":1630,"next_seq":11,"roster":["p5-1|g04|bot|220","p5-2|g02|bot|135","p5-3|g06|bot|205","p5-4|g07|bot|95","p5-5|g04|bot|220","p5-6|g09|bot|85","p5-7|g02|bot|135","p5-8|g06|bot|205","p5-10|g03|bot|70"],"hero":"h5-9|held_ringborke|319|bot|||260|false|","bookings":[],"new_bookings":[],"draft_roster":["p5-1|g04|bot|220|false","p5-2|g02|bot|135|false","p5-3|g06|bot|205|false","p5-4|g07|bot|95|false","p5-5|g04|bot|220|false","p5-6|g09|bot|85|false","p5-7|g02|bot|135|false","p5-8|g06|bot|205|false","p5-10|g03|bot|70|false"],"draft_hero":"h5-9|held_ringborke|319|bot|||260|false|","boss_lane":"","undo":0}],"buildings":[7500.0,3643.2949999999964,7500.0,5979.6576,4974.670000000001,0.0,9000.0,9000.0,12000.0,0.0,0.0,1504.9041999999981,0.0,7024.199999999999,0.0,5416.529999999997,9000.0,12000.0],"boss":{"next":1,"settled":11,"claim":""},"boss_log":[],"announcements":[],"settlement":{"round":11,"gains":[241,308,241,148,148,148],"income":110,"lost":["rot_top_outer","blau_bot_outer","rot_top_inner"],"end_reason":"cleared","combat_time":114.74999999999562,"boss":"none","lane_kills":{"mid":13,"bot":12,"top":12},"xp":{"h1-12":348,"h2-9":326,"h5-9":319,"h3-10":227,"h0-10":159}},"combat":{"round":11,"steps":2295,"elapsed":114.74999999999562,"finished":true,"end_reason":"cleared","destroyed":[],"grotto":"none|-1|-1|true","grotto_boss":"","grotto_boss_hp":0.0,"events":97,"mobile":[0,0,0]}},{"label":"round-12","phase":2,"round":12,"winner":0,"end_note":"Ancient von Rot zerstört.","players":[{"gold":358,"draft_gold":8,"ready":true,"earned":2218,"spent":2080,"next_seq":13,"roster":["p0-1|w04|top|230","p0-2|w06|top|195","p0-3|w02|top|150","p0-4|w04|top|230","p0-5|w07|top|100","p0-6|w09|top|90","p0-7|w06|top|195","p0-8|w03|top|75","p0-9|w02|top|150","p0-12|w03|top|75"],"hero":"h0-10|held_ringborke|340|top|basaltschild||260|false|","bookings":["c0-11|ch_schutz|top|150|13"],"new_bookings":["c0-11|ch_schutz|top|150"],"draft_roster":["p0-1|w04|top|230|false","p0-2|w06|top|195|false","p0-3|w02|top|150|false","p0-4|w04|top|230|false","p0-5|w07|top|100|false","p0-6|w09|top|90|false","p0-7|w06|top|195|false","p0-8|w03|top|75|false","p0-9|w02|top|150|false","p0-12|w03|top|75|true"],"draft_hero":"h0-10|held_ringborke|159|top|basaltschild||260|false|basaltschild","boss_lane":"","undo":0},{"gold":390,"draft_gold":40,"ready":true,"earned":2220,"spent":2050,"next_seq":15,"roster":["p1-1|g02|mid|135","p1-2|g06|mid|205","p1-3|g03|mid|70","p1-4|g07|mid|95","p1-5|g02|mid|135","p1-6|g06|mid|205","p1-7|g02|mid|135","p1-8|g03|mid|70","p1-9|g09|mid|85","p1-10|g02|mid|135","p1-11|g05|mid|65","p1-14|g07|mid|95"],"hero":"h1-12|held_funkenlanze|889|mid|glutklinge|splitterschuss|260|false|","bookings":["c1-13|ch_belagerung|mid|180|13"],"new_bookings":["c1-13|ch_belagerung|mid|180"],"draft_roster":["p1-1|g02|mid|135|false","p1-2|g06|mid|205|false","p1-3|g03|mid|70|false","p1-4|g07|mid|95|false","p1-5|g02|mid|135|false","p1-6|g06|mid|205|false","p1-7|g02|mid|135|false","p1-8|g03|mid|70|false","p1-9|g09|mid|85|false","p1-10|g02|mid|135|false","p1-11|g05|mid|65|false","p1-14|g07|mid|95|true"],"draft_hero":"h1-12|held_funkenlanze|348|mid|glutklinge|splitterschuss|260|false|glutklinge","boss_lane":"","undo":0},{"gold":377,"draft_gold":27,"ready":true,"earned":2152,"spent":1995,"next_seq":11,"roster":["p2-1|w06|bot|195","p2-2|w04|bot|230","p2-3|w07|bot|100","p2-4|w06|bot|195","p2-5|w02|bot|150","p2-6|w09|bot|90","p2-7|w06|bot|195","p2-10|w04|bot|230"],"hero":"h2-9|held_funkenlanze|615|bot|funkenfokus|durchschlag|260|false|","bookings":[],"new_bookings":[],"draft_roster":["p2-1|w06|bot|195|false","p2-2|w04|bot|230|false","p2-3|w07|bot|100|false","p2-4|w06|bot|195|false","p2-5|w02|bot|150|false","p2-6|w09|bot|90|false","p2-7|w06|bot|195|false","p2-10|w04|bot|230|false"],"draft_hero":"h2-9|held_funkenlanze|326|bot|funkenfokus|durchschlag|260|false|funkenfokus","boss_lane":"","undo":0},{"gold":188,"draft_gold":50,"ready":true,"earned":1748,"spent":1780,"next_seq":13,"roster":["p3-1|g04|top|220","p3-2|g06|top|205","p3-3|g02|top|135","p3-4|g09|top|85","p3-5|g03|top|70","p3-6|g07|top|95","p3-7|g06|top|205","p3-8|g02|top|135","p3-12|g03|top|70"],"hero":"h3-10|held_quellgeflecht|486|top|||260|false|","bookings":["c3-11|ch_schutz|top|150|13"],"new_bookings":["c3-11|ch_schutz|top|150"],"draft_roster":["p3-1|g04|top|220|false","p3-2|g06|top|205|false","p3-3|g02|top|135|false","p3-4|g09|top|85|false","p3-5|g03|top|70|false","p3-6|g07|top|95|false","p3-7|g06|top|205|false","p3-8|g02|top|135|false","p3-12|g03|top|70|true"],"draft_hero":"h3-10|held_quellgeflecht|227|top|||260|false|","boss_lane":"","undo":0},{"gold":218,"draft_gold":65,"ready":true,"earned":1763,"spent":1765,"next_seq":10,"roster":["p4-1|w04|mid|230","p4-2|w02|mid|150","p4-3|w06|mid|195","p4-4|w04|mid|230","p4-5|w07|mid|100","p4-6|w10|mid|270","p4-7|w02|mid|150"],"hero":"h4-9|held_ringborke|332|mid|||260|false|","bookings":[],"new_bookings":[],"draft_roster":["p4-1|w04|grotto|230|false","p4-2|w02|mid|150|false","p4-3|w06|grotto|195|false","p4-4|w04|grotto|230|false","p4-5|w07|mid|100|false","p4-6|w10|grotto|270|false","p4-7|w02|mid|150|false"],"draft_hero":"h4-9|held_ringborke|0|grotto|||260|true|","boss_lane":"","undo":0},{"gold":164,"draft_gold":4,"ready":true,"earned":1834,"spent":1890,"next_seq":13,"roster":["p5-1|g04|bot|220","p5-2|g02|bot|135","p5-3|g06|bot|205","p5-4|g07|bot|95","p5-5|g04|bot|220","p5-6|g09|bot|85","p5-7|g02|bot|135","p5-8|g06|bot|205","p5-10|g04|bot|220","p5-11|g01|bot|45","p5-12|g05|bot|65"],"hero":"h5-9|held_ringborke|665|bot||borkenhaut|260|false|","bookings":[],"new_bookings":[],"draft_roster":["p5-1|g04|bot|220|false","p5-2|g02|bot|135|false","p5-3|g06|bot|205|false","p5-4|g07|bot|95|false","p5-5|g04|bot|220|false","p5-6|g09|bot|85|false","p5-7|g02|bot|135|false","p5-8|g06|bot|205|false","p5-10|g04|bot|220|false","p5-11|g01|bot|45|true","p5-12|g05|bot|65|true"],"draft_hero":"h5-9|held_ringborke|319|bot||borkenhaut|260|false|","boss_lane":"","undo":0}],"buildings":[7500.0,3643.2949999999964,7500.0,5979.6576,0.0,0.0,9000.0,7424.6132,12000.0,0.0,0.0,0.0,0.0,7024.199999999999,0.0,0.0,0.0,0.0],"boss":{"next":16,"settled":12,"claim":"1|12|13|4|mid"},"boss_log":["12|won|1||4"],"announcements":[],"settlement":{"round":12,"gains":[350,350,350,138,153,160],"income":114,"lost":["rot_mid_inner","rot_base_1","rot_base_2","blau_bot_inner","rot_ancient"],"end_reason":"core","combat_time":87.34999999999718,"boss":"won","lane_kills":{"mid":11,"bot":12,"top":9},"xp":{"h1-12":541,"h5-9":346,"h2-9":289,"h0-10":181,"h3-10":259,"h4-9":332}},"combat":{"round":12,"steps":1747,"elapsed":87.34999999999718,"finished":true,"end_reason":"core","destroyed":[1],"grotto":"success|1|1|true","grotto_boss":"false|false|113","grotto_boss_hp":0.0,"events":88,"mobile":[12,5,0]}}],"results":[]},"bot_match_2":{"title":"Vollständige Bot-Partie Seed 2 bis zum Ancient-Fall","snapshots":[{"label":"round-1","phase":0,"round":2,"winner":-2,"end_note":"","players":[{"gold":128,"draft_gold":128,"ready":true,"earned":88,"spent":180,"next_seq":4,"roster":["p0-1|g01|top|45","p0-2|g05|top|65","p0-3|g03|top|70"],"hero":"","bookings":[],"new_bookings":[],"draft_roster":["p0-1|g01|top|45|false","p0-2|g05|top|65|false","p0-3|g03|top|70|false"],"draft_hero":"","boss_lane":"","undo":0},{"gold":173,"draft_gold":173,"ready":true,"earned":88,"spent":135,"next_seq":3,"roster":["p1-1|w05|mid|60","p1-2|w03|mid|75"],"hero":"","bookings":[],"new_bookings":[],"draft_roster":["p1-1|w05|mid|60|false","p1-2|w03|mid|75|false"],"draft_hero":"","boss_lane":"","undo":0},{"gold":128,"draft_gold":128,"ready":true,"earned":88,"spent":180,"next_seq":4,"roster":["p2-1|g03|bot|70","p2-2|g05|bot|65","p2-3|g01|bot|45"],"hero":"","bookings":[],"new_bookings":[],"draft_roster":["p2-1|g03|bot|70|false","p2-2|g05|bot|65|false","p2-3|g01|bot|45|false"],"draft_hero":"","boss_lane":"","undo":0},{"gold":123,"draft_gold":123,"ready":true,"earned":88,"spent":185,"next_seq":4,"roster":["p3-1|w03|top|75","p3-2|w01|top|50","p3-3|w05|top|60"],"hero":"","bookings":[],"new_bookings":[],"draft_roster":["p3-1|w03|top|75|false","p3-2|w01|top|50|false","p3-3|w05|top|60|false"],"draft_hero":"","boss_lane":"","undo":0},{"gold":128,"draft_gold":128,"ready":true,"earned":88,"spent":180,"next_seq":4,"roster":["p4-1|g03|mid|70","p4-2|g01|mid|45","p4-3|g05|mid|65"],"hero":"","bookings":[],"new_bookings":[],"draft_roster":["p4-1|g03|mid|70|false","p4-2|g01|mid|45|false","p4-3|g05|mid|65|false"],"draft_hero":"","boss_lane":"","undo":0},{"gold":123,"draft_gold":123,"ready":true,"earned":88,"spent":185,"next_seq":4,"roster":["p5-1|w03|bot|75","p5-2|w05|bot|60","p5-3|w01|bot|50"],"hero":"","bookings":[],"new_bookings":[],"draft_roster":["p5-1|w03|bot|75|false","p5-2|w05|bot|60|false","p5-3|w01|bot|50|false"],"draft_hero":"","boss_lane":"","undo":0}],"buildings":[7500.0,5970.1,7500.0,5968.8,7500.0,5940.200000000001,9000.0,9000.0,12000.0,7500.0,6000.0,7500.0,6000.0,7500.0,6000.0,9000.0,9000.0,12000.0],"boss":{"next":1,"settled":1,"claim":""},"boss_log":[],"announcements":[],"settlement":{"round":1,"gains":[18,18,18,18,18,18],"income":70,"lost":[],"end_reason":"cleared","combat_time":44.89999999999959,"boss":"none","lane_kills":{"mid":6,"bot":6,"top":6},"xp":{}},"combat":{"round":1,"steps":898,"elapsed":44.89999999999959,"finished":true,"end_reason":"cleared","destroyed":[],"grotto":"none|-1|-1|true","grotto_boss":"","grotto_boss_hp":0.0,"events":35,"mobile":[0,0,0]}},{"label":"round-2","phase":0,"round":3,"winner":-2,"end_note":"","players":[{"gold":125,"draft_gold":125,"ready":true,"earned":180,"spent":275,"next_seq":5,"roster":["p0-1|g01|top|45","p0-2|g05|top|65","p0-3|g03|top|70","p0-4|g07|top|95"],"hero":"","bookings":[],"new_bookings":[],"draft_roster":["p0-1|g01|top|45|false","p0-2|g05|top|65|false","p0-3|g03|top|70|false","p0-4|g07|top|95|false"],"draft_hero":"","boss_lane":"","undo":0},{"gold":105,"draft_gold":105,"ready":true,"earned":180,"spent":295,"next_seq":5,"roster":["p1-1|w05|mid|60","p1-2|w03|mid|75","p1-3|w07|mid|100","p1-4|w05|mid|60"],"hero":"","bookings":[],"new_bookings":[],"draft_roster":["p1-1|w05|mid|60|false","p1-2|w03|mid|75|false","p1-3|w07|mid|100|false","p1-4|w05|mid|60|false"],"draft_hero":"","boss_lane":"","undo":0},{"gold":135,"draft_gold":135,"ready":true,"earned":180,"spent":265,"next_seq":5,"roster":["p2-1|g03|bot|70","p2-2|g05|bot|65","p2-3|g01|bot|45","p2-4|g09|bot|85"],"hero":"","bookings":[],"new_bookings":[],"draft_roster":["p2-1|g03|bot|70|false","p2-2|g05|bot|65|false","p2-3|g01|bot|45|false","p2-4|g09|bot|85|false"],"draft_hero":"","boss_lane":"","undo":0},{"gold":140,"draft_gold":140,"ready":true,"earned":180,"spent":260,"next_seq":5,"roster":["p3-1|w03|top|75","p3-2|w01|top|50","p3-3|w05|top|60","p3-4|w03|top|75"],"hero":"","bookings":[],"new_bookings":[],"draft_roster":["p3-1|w03|top|75|false","p3-2|w01|top|50|false","p3-3|w05|top|60|false","p3-4|w03|top|75|false"],"draft_hero":"","boss_lane":"","undo":0},{"gold":125,"draft_gold":125,"ready":true,"earned":180,"spent":275,"next_seq":5,"roster":["p4-1|g03|mid|70","p4-2|g01|mid|45","p4-3|g05|mid|65","p4-4|g07|mid|95"],"hero":"","bookings":[],"new_bookings":[],"draft_roster":["p4-1|g03|mid|70|false","p4-2|g01|mid|45|false","p4-3|g05|mid|65|false","p4-4|g07|mid|95|false"],"draft_hero":"","boss_lane":"","undo":0},{"gold":140,"draft_gold":140,"ready":true,"earned":180,"spent":260,"next_seq":5,"roster":["p5-1|w03|bot|75","p5-2|w05|bot|60","p5-3|w01|bot|50","p5-4|w03|bot|75"],"hero":"","bookings":[],"new_bookings":[],"draft_roster":["p5-1|w03|bot|75|false","p5-2|w05|bot|60|false","p5-3|w01|bot|50|false","p5-4|w03|bot|75|false"],"draft_hero":"","boss_lane":"","undo":0}],"buildings":[7500.0,5970.1,7500.0,5968.8,7500.0,5910.300000000001,9000.0,9000.0,12000.0,7500.0,6000.0,7500.0,5730.900000000003,7500.0,6000.0,9000.0,9000.0,12000.0],"boss":{"next":1,"settled":2,"claim":""},"boss_log":[],"announcements":[],"settlement":{"round":2,"gains":[18,18,18,18,18,18],"income":74,"lost":[],"end_reason":"cleared","combat_time":57.09999999999889,"boss":"none","lane_kills":{"mid":6,"bot":6,"top":6},"xp":{}},"combat":{"round":2,"steps":1142,"elapsed":57.09999999999889,"finished":true,"end_reason":"cleared","destroyed":[],"grotto":"none|-1|-1|true","grotto_boss":"","grotto_boss_hp":0.0,"events":42,"mobile":[0,0,0]}},{"label":"round-3","phase":0,"round":4,"winner":-2,"end_note":"","players":[{"gold":125,"draft_gold":125,"ready":true,"earned":290,"spent":385,"next_seq":7,"roster":["p0-1|g01|top|45","p0-2|g05|top|65","p0-3|g03|top|70","p0-4|g07|top|95","p0-5|g01|top|45","p0-6|g05|top|65"],"hero":"","bookings":[],"new_bookings":[],"draft_roster":["p0-1|g01|top|45|false","p0-2|g05|top|65|false","p0-3|g03|top|70|false","p0-4|g07|top|95|false","p0-5|g01|top|45|false","p0-6|g05|top|65|false"],"draft_hero":"","boss_lane":"","undo":0},{"gold":165,"draft_gold":165,"ready":true,"earned":290,"spent":345,"next_seq":6,"roster":["p1-1|w05|mid|60","p1-2|w03|mid|75","p1-3|w07|mid|100","p1-4|w05|mid|60","p1-5|w01|mid|50"],"hero":"","bookings":[],"new_bookings":[],"draft_roster":["p1-1|w05|mid|60|false","p1-2|w03|mid|75|false","p1-3|w07|mid|100|false","p1-4|w05|mid|60|false","p1-5|w01|mid|50|false"],"draft_hero":"","boss_lane":"","undo":0},{"gold":175,"draft_gold":175,"ready":true,"earned":290,"spent":335,"next_seq":6,"roster":["p2-1|g03|bot|70","p2-2|g05|bot|65","p2-3|g01|bot|45","p2-4|g09|bot|85","p2-5|g03|top|70"],"hero":"","bookings":[],"new_bookings":[],"draft_roster":["p2-1|g03|bot|70|false","p2-2|g05|bot|65|false","p2-3|g01|bot|45|false","p2-4|g09|bot|85|false","p2-5|g03|top|70|false"],"draft_hero":"","boss_lane":"","undo":0},{"gold":150,"draft_gold":150,"ready":true,"earned":290,"spent":360,"next_seq":6,"roster":["p3-1|w03|top|75","p3-2|w01|top|50","p3-3|w05|top|60","p3-4|w03|top|75","p3-5|w07|top|100"],"hero":"","bookings":[],"new_bookings":[],"draft_roster":["p3-1|w03|top|75|false","p3-2|w01|top|50|false","p3-3|w05|top|60|false","p3-4|w03|top|75|false","p3-5|w07|top|100|false"],"draft_hero":"","boss_lane":"","undo":0},{"gold":165,"draft_gold":165,"ready":true,"earned":290,"spent":345,"next_seq":6,"roster":["p4-1|g03|mid|70","p4-2|g01|mid|45","p4-3|g05|mid|65","p4-4|g07|mid|95","p4-5|g03|mid|70"],"hero":"","bookings":[],"new_bookings":[],"draft_roster":["p4-1|g03|mid|70|false","p4-2|g01|mid|45|false","p4-3|g05|mid|65|false","p4-4|g07|mid|95|false","p4-5|g03|mid|70|false"],"draft_hero":"","boss_lane":"","undo":0},{"gold":150,"draft_gold":150,"ready":true,"earned":290,"spent":360,"next_seq":6,"roster":["p5-1|w03|bot|75","p5-2|w05|bot|60","p5-3|w01|bot|50","p5-4|w03|bot|75","p5-5|w07|bot|100"],"hero":"","bookings":[],"new_bookings":[],"draft_roster":["p5-1|w03|bot|75|false","p5-2|w05|bot|60|false","p5-3|w01|bot|50|false","p5-4|w03|bot|75|false","p5-5|w07|bot|100|false"],"draft_hero":"","boss_lane":"","undo":0}],"buildings":[7500.0,5970.1,7500.0,5968.8,7500.0,4879.193400000009,9000.0,9000.0,12000.0,7500.0,5078.983600000002,7500.0,5551.5000000000055,7500.0,6000.0,9000.0,9000.0,12000.0],"boss":{"next":1,"settled":3,"claim":""},"boss_log":[],"announcements":[],"settlement":{"round":3,"gains":[32,32,32,32,32,32],"income":78,"lost":[],"end_reason":"cleared","combat_time":54.09999999999906,"boss":"none","lane_kills":{"mid":6,"top":6,"bot":6},"xp":{}},"combat":{"round":3,"steps":1082,"elapsed":54.09999999999906,"finished":true,"end_reason":"cleared","destroyed":[],"grotto":"none|-1|-1|true","grotto_boss":"","grotto_boss_hp":0.0,"events":49,"mobile":[0,0,0]}},{"label":"round-4","phase":0,"round":5,"winner":-2,"end_note":"","players":[{"gold":132,"draft_gold":132,"ready":true,"earned":412,"spent":500,"next_seq":9,"roster":["p0-1|g01|top|45","p0-2|g05|top|65","p0-3|g03|top|70","p0-4|g07|top|95","p0-5|g01|top|45","p0-6|g05|top|65","p0-7|g01|top|45","p0-8|g03|top|70"],"hero":"","bookings":[],"new_bookings":[],"draft_roster":["p0-1|g01|top|45|false","p0-2|g05|top|65|false","p0-3|g03|top|70|false","p0-4|g07|top|95|false","p0-5|g01|top|45|false","p0-6|g05|top|65|false","p0-7|g01|top|45|false","p0-8|g03|top|70|false"],"draft_hero":"","boss_lane":"","undo":0},{"gold":137,"draft_gold":137,"ready":true,"earned":412,"spent":495,"next_seq":8,"roster":["p1-1|w05|mid|60","p1-2|w03|mid|75","p1-3|w07|mid|100","p1-4|w05|mid|60","p1-5|w01|mid|50","p1-6|w09|mid|90","p1-7|w05|mid|60"],"hero":"","bookings":[],"new_bookings":[],"draft_roster":["p1-1|w05|mid|60|false","p1-2|w03|mid|75|false","p1-3|w07|mid|100|false","p1-4|w05|mid|60|false","p1-5|w01|mid|50|false","p1-6|w09|mid|90|false","p1-7|w05|mid|60|false"],"draft_hero":"","boss_lane":"","undo":0},{"gold":137,"draft_gold":137,"ready":true,"earned":412,"spent":495,"next_seq":8,"roster":["p2-1|g03|bot|70","p2-2|g05|bot|65","p2-3|g01|bot|45","p2-4|g09|bot|85","p2-5|g03|top|70","p2-6|g07|bot|95","p2-7|g05|bot|65"],"hero":"","bookings":[],"new_bookings":[],"draft_roster":["p2-1|g03|bot|70|false","p2-2|g05|bot|65|false","p2-3|g01|bot|45|false","p2-4|g09|bot|85|false","p2-5|g03|top|70|false","p2-6|g07|bot|95|false","p2-7|g05|bot|65|false"],"draft_hero":"","boss_lane":"","undo":0},{"gold":132,"draft_gold":132,"ready":true,"earned":412,"spent":500,"next_seq":8,"roster":["p3-1|w03|top|75","p3-2|w01|top|50","p3-3|w05|top|60","p3-4|w03|top|75","p3-5|w07|top|100","p3-6|w09|top|90","p3-7|w01|top|50"],"hero":"","bookings":[],"new_bookings":[],"draft_roster":["p3-1|w03|top|75|false","p3-2|w01|top|50|false","p3-3|w05|top|60|false","p3-4|w03|top|75|false","p3-5|w07|top|100|false","p3-6|w09|top|90|false","p3-7|w01|top|50|false"],"draft_hero":"","boss_lane":"","undo":0},{"gold":157,"draft_gold":157,"ready":true,"earned":412,"spent":475,"next_seq":8,"roster":["p4-1|g03|mid|70","p4-2|g01|mid|45","p4-3|g05|mid|65","p4-4|g07|mid|95","p4-5|g03|mid|70","p4-6|g09|mid|85","p4-7|g01|mid|45"],"hero":"","bookings":[],"new_bookings":[],"draft_roster":["p4-1|g03|mid|70|false","p4-2|g01|mid|45|false","p4-3|g05|mid|65|false","p4-4|g07|mid|95|false","p4-5|g03|mid|70|false","p4-6|g09|mid|85|false","p4-7|g01|mid|45|false"],"draft_hero":"","boss_lane":"","undo":0},{"gold":122,"draft_gold":122,"ready":true,"earned":412,"spent":510,"next_seq":8,"roster":["p5-1|w03|bot|75","p5-2|w05|bot|60","p5-3|w01|bot|50","p5-4|w03|bot|75","p5-5|w07|bot|100","p5-6|w09|bot|90","p5-7|w05|bot|60"],"hero":"","bookings":[],"new_bookings":[],"draft_roster":["p5-1|w03|bot|75|false","p5-2|w05|bot|60|false","p5-3|w01|bot|50|false","p5-4|w03|bot|75|false","p5-5|w07|bot|100|false","p5-6|w09|bot|90|false","p5-7|w05|bot|60|false"],"draft_hero":"","boss_lane":"","undo":0}],"buildings":[7500.0,5970.1,7500.0,5968.8,7500.0,3905.693400000015,9000.0,9000.0,12000.0,7500.0,4003.983600000005,7500.0,4644.400000000016,7500.0,6000.0,9000.0,9000.0,12000.0],"boss":{"next":1,"settled":4,"claim":""},"boss_log":[],"announcements":[],"settlement":{"round":4,"gains":[40,40,40,40,40,40],"income":82,"lost":[],"end_reason":"cleared","combat_time":62.89999999999856,"boss":"none","lane_kills":{"mid":8,"bot":8,"top":8},"xp":{}},"combat":{"round":4,"steps":1258,"elapsed":62.89999999999856,"finished":true,"end_reason":"cleared","destroyed":[],"grotto":"none|-1|-1|true","grotto_boss":"","grotto_boss_hp":0.0,"events":67,"mobile":[0,0,0]}},{"label":"round-5","phase":0,"round":6,"winner":-2,"end_note":"","players":[{"gold":173,"draft_gold":173,"ready":true,"earned":543,"spent":590,"next_seq":9,"roster":["p0-1|g02|top|135","p0-2|g05|top|65","p0-3|g03|top|70","p0-4|g07|top|95","p0-5|g01|top|45","p0-6|g05|top|65","p0-7|g01|top|45","p0-8|g03|top|70"],"hero":"","bookings":[],"new_bookings":[],"draft_roster":["p0-1|g02|top|135|false","p0-2|g05|top|65|false","p0-3|g03|top|70|false","p0-4|g07|top|95|false","p0-5|g01|top|45|false","p0-6|g05|top|65|false","p0-7|g01|top|45|false","p0-8|g03|top|70|false"],"draft_hero":"","boss_lane":"","undo":0},{"gold":168,"draft_gold":168,"ready":true,"earned":543,"spent":595,"next_seq":8,"roster":["p1-1|w05|mid|60","p1-2|w03|mid|75","p1-3|w07|mid|100","p1-4|w05|mid|60","p1-5|w02|mid|150","p1-6|w09|mid|90","p1-7|w05|mid|60"],"hero":"","bookings":[],"new_bookings":[],"draft_roster":["p1-1|w05|mid|60|false","p1-2|w03|mid|75|false","p1-3|w07|mid|100|false","p1-4|w05|mid|60|false","p1-5|w02|mid|150|false","p1-6|w09|mid|90|false","p1-7|w05|mid|60|false"],"draft_hero":"","boss_lane":"","undo":0},{"gold":133,"draft_gold":133,"ready":true,"earned":543,"spent":630,"next_seq":9,"roster":["p2-1|g03|bot|70","p2-2|g05|bot|65","p2-3|g02|bot|135","p2-4|g09|bot|85","p2-5|g03|top|70","p2-6|g07|bot|95","p2-7|g05|bot|65","p2-8|g01|bot|45"],"hero":"","bookings":[],"new_bookings":[],"draft_roster":["p2-1|g03|bot|70|false","p2-2|g05|bot|65|false","p2-3|g02|bot|135|false","p2-4|g09|bot|85|false","p2-5|g03|top|70|false","p2-6|g07|bot|95|false","p2-7|g05|bot|65|false","p2-8|g01|bot|45|false"],"draft_hero":"","boss_lane":"","undo":0},{"gold":163,"draft_gold":163,"ready":true,"earned":543,"spent":600,"next_seq":8,"roster":["p3-1|w03|top|75","p3-2|w02|top|150","p3-3|w05|top|60","p3-4|w03|top|75","p3-5|w07|top|100","p3-6|w09|top|90","p3-7|w01|top|50"],"hero":"","bookings":[],"new_bookings":[],"draft_roster":["p3-1|w03|top|75|false","p3-2|w02|top|150|false","p3-3|w05|top|60|false","p3-4|w03|top|75|false","p3-5|w07|top|100|false","p3-6|w09|top|90|false","p3-7|w01|top|50|false"],"draft_hero":"","boss_lane":"","undo":0},{"gold":133,"draft_gold":133,"ready":true,"earned":543,"spent":630,"next_seq":9,"roster":["p4-1|g03|mid|70","p4-2|g02|mid|135","p4-3|g05|mid|65","p4-4|g07|mid|95","p4-5|g03|mid|70","p4-6|g09|mid|85","p4-7|g01|mid|45","p4-8|g05|mid|65"],"hero":"","bookings":[],"new_bookings":[],"draft_roster":["p4-1|g03|mid|70|false","p4-2|g02|mid|135|false","p4-3|g05|mid|65|false","p4-4|g07|mid|95|false","p4-5|g03|mid|70|false","p4-6|g09|mid|85|false","p4-7|g01|mid|45|false","p4-8|g05|mid|65|false"],"draft_hero":"","boss_lane":"","undo":0},{"gold":153,"draft_gold":153,"ready":true,"earned":543,"spent":610,"next_seq":8,"roster":["p5-1|w03|bot|75","p5-2|w05|bot|60","p5-3|w02|bot|150","p5-4|w03|bot|75","p5-5|w07|bot|100","p5-6|w09|bot|90","p5-7|w05|bot|60"],"hero":"","bookings":[],"new_bookings":[],"draft_roster":["p5-1|w03|bot|75|false","p5-2|w05|bot|60|false","p5-3|w02|bot|150|false","p5-4|w03|bot|75|false","p5-5|w07|bot|100|false","p5-6|w09|bot|90|false","p5-7|w05|bot|60|false"],"draft_hero":"","boss_lane":"","undo":0}],"buildings":[7500.0,5970.1,7500.0,5867.087999999998,7500.0,2885.7726000000134,9000.0,9000.0,12000.0,7500.0,2949.738800000006,7500.0,4644.400000000016,7500.0,6000.0,9000.0,9000.0,12000.0],"boss":{"next":1,"settled":5,"claim":""},"boss_log":[],"announcements":[],"settlement":{"round":5,"gains":[45,45,45,45,45,45],"income":86,"lost":[],"end_reason":"cleared","combat_time":60.69999999999869,"boss":"none","lane_kills":{"mid":8,"bot":8,"top":8},"xp":{}},"combat":{"round":5,"steps":1214,"elapsed":60.69999999999869,"finished":true,"end_reason":"cleared","destroyed":[],"grotto":"none|-1|-1|true","grotto_boss":"","grotto_boss_hp":0.0,"events":69,"mobile":[0,0,0]}},{"label":"round-6","phase":0,"round":7,"winner":-2,"end_note":"","players":[{"gold":213,"draft_gold":213,"ready":true,"earned":673,"spent":680,"next_seq":9,"roster":["p0-1|g02|top|135","p0-2|g05|top|65","p0-3|g03|top|70","p0-4|g07|top|95","p0-5|g02|top|135","p0-6|g05|top|65","p0-7|g01|top|45","p0-8|g03|top|70"],"hero":"","bookings":[],"new_bookings":[],"draft_roster":["p0-1|g02|top|135|false","p0-2|g05|top|65|false","p0-3|g03|top|70|false","p0-4|g07|top|95|false","p0-5|g02|top|135|false","p0-6|g05|top|65|false","p0-7|g01|top|45|false","p0-8|g03|top|70|false"],"draft_hero":"","boss_lane":"","undo":0},{"gold":163,"draft_gold":163,"ready":true,"earned":673,"spent":730,"next_seq":8,"roster":["p1-1|w06|mid|195","p1-2|w03|mid|75","p1-3|w07|mid|100","p1-4|w05|mid|60","p1-5|w02|mid|150","p1-6|w09|mid|90","p1-7|w05|mid|60"],"hero":"","bookings":[],"new_bookings":[],"draft_roster":["p1-1|w06|mid|195|false","p1-2|w03|mid|75|false","p1-3|w07|mid|100|false","p1-4|w05|mid|60|false","p1-5|w02|mid|150|false","p1-6|w09|mid|90|false","p1-7|w05|mid|60|false"],"draft_hero":"","boss_lane":"","undo":0},{"gold":173,"draft_gold":173,"ready":true,"earned":673,"spent":720,"next_seq":9,"roster":["p2-1|g03|bot|70","p2-2|g05|bot|65","p2-3|g02|bot|135","p2-4|g09|bot|85","p2-5|g03|top|70","p2-6|g07|bot|95","p2-7|g05|bot|65","p2-8|g02|bot|135"],"hero":"","bookings":[],"new_bookings":[],"draft_roster":["p2-1|g03|bot|70|false","p2-2|g05|bot|65|false","p2-3|g02|bot|135|false","p2-4|g09|bot|85|false","p2-5|g03|top|70|false","p2-6|g07|bot|95|false","p2-7|g05|bot|65|false","p2-8|g02|bot|135|false"],"draft_hero":"","boss_lane":"","undo":0},{"gold":193,"draft_gold":193,"ready":true,"earned":673,"spent":700,"next_seq":8,"roster":["p3-1|w03|top|75","p3-2|w02|top|150","p3-3|w05|top|60","p3-4|w03|top|75","p3-5|w07|top|100","p3-6|w09|top|90","p3-7|w02|top|150"],"hero":"","bookings":[],"new_bookings":[],"draft_roster":["p3-1|w03|top|75|false","p3-2|w02|top|150|false","p3-3|w05|top|60|false","p3-4|w03|top|75|false","p3-5|w07|top|100|false","p3-6|w09|top|90|false","p3-7|w02|top|150|false"],"draft_hero":"","boss_lane":"","undo":0},{"gold":173,"draft_gold":173,"ready":true,"earned":673,"spent":720,"next_seq":9,"roster":["p4-1|g03|mid|70","p4-2|g02|mid|135","p4-3|g05|mid|65","p4-4|g07|mid|95","p4-5|g03|mid|70","p4-6|g09|mid|85","p4-7|g02|mid|135","p4-8|g05|mid|65"],"hero":"","bookings":[],"new_bookings":[],"draft_roster":["p4-1|g03|mid|70|false","p4-2|g02|mid|135|false","p4-3|g05|mid|65|false","p4-4|g07|mid|95|false","p4-5|g03|mid|70|false","p4-6|g09|mid|85|false","p4-7|g02|mid|135|false","p4-8|g05|mid|65|false"],"draft_hero":"","boss_lane":"","undo":0},{"gold":148,"draft_gold":148,"ready":true,"earned":673,"spent":745,"next_seq":8,"roster":["p5-1|w03|bot|75","p5-2|w06|bot|195","p5-3|w02|bot|150","p5-4|w03|bot|75","p5-5|w07|bot|100","p5-6|w09|bot|90","p5-7|w05|bot|60"],"hero":"","bookings":[],"new_bookings":[],"draft_roster":["p5-1|w03|bot|75|false","p5-2|w06|bot|195|false","p5-3|w02|bot|150|false","p5-4|w03|bot|75|false","p5-5|w07|bot|100|false","p5-6|w09|bot|90|false","p5-7|w05|bot|60|false"],"draft_hero":"","boss_lane":"","undo":0}],"buildings":[7500.0,5970.1,7500.0,5867.087999999998,7500.0,635.7826000000118,9000.0,9000.0,12000.0,7500.0,1732.5088000000076,7500.0,3691.3050000000144,7500.0,6000.0,9000.0,9000.0,12000.0],"boss":{"next":1,"settled":6,"claim":""},"boss_log":[],"announcements":[],"settlement":{"round":6,"gains":[40,40,40,40,40,40],"income":90,"lost":[],"end_reason":"cleared","combat_time":62.09999999999861,"boss":"none","lane_kills":{"mid":8,"bot":8,"top":8},"xp":{}},"combat":{"round":6,"steps":1242,"elapsed":62.09999999999861,"finished":true,"end_reason":"cleared","destroyed":[],"grotto":"none|-1|-1|true","grotto_boss":"","grotto_boss_hp":0.0,"events":69,"mobile":[0,0,0]}},{"label":"round-7","phase":0,"round":8,"winner":-2,"end_note":"","players":[{"gold":190,"draft_gold":190,"ready":true,"earned":825,"spent":855,"next_seq":10,"roster":["p0-1|g02|top|135","p0-2|g05|top|65","p0-3|g03|top|70","p0-4|g07|top|95","p0-5|g02|top|135","p0-6|g05|top|65","p0-7|g02|top|135","p0-8|g03|top|70","p0-9|g09|top|85"],"hero":"","bookings":[],"new_bookings":[],"draft_roster":["p0-1|g02|top|135|false","p0-2|g05|top|65|false","p0-3|g03|top|70|false","p0-4|g07|top|95|false","p0-5|g02|top|135|false","p0-6|g05|top|65|false","p0-7|g02|top|135|false","p0-8|g03|top|70|false","p0-9|g09|top|85|false"],"draft_hero":"","boss_lane":"","undo":0},{"gold":180,"draft_gold":180,"ready":true,"earned":825,"spent":865,"next_seq":8,"roster":["p1-1|w06|mid|195","p1-2|w03|mid|75","p1-3|w07|mid|100","p1-4|w06|mid|195","p1-5|w02|mid|150","p1-6|w09|mid|90","p1-7|w05|mid|60"],"hero":"","bookings":[],"new_bookings":[],"draft_roster":["p1-1|w06|mid|195|false","p1-2|w03|mid|75|false","p1-3|w07|mid|100|false","p1-4|w06|mid|195|false","p1-5|w02|mid|150|false","p1-6|w09|mid|90|false","p1-7|w05|mid|60|false"],"draft_hero":"","boss_lane":"","undo":0},{"gold":185,"draft_gold":185,"ready":true,"earned":825,"spent":860,"next_seq":9,"roster":["p2-1|g03|bot|70","p2-2|g06|bot|205","p2-3|g02|bot|135","p2-4|g09|bot|85","p2-5|g03|top|70","p2-6|g07|bot|95","p2-7|g05|bot|65","p2-8|g02|bot|135"],"hero":"","bookings":[],"new_bookings":[],"draft_roster":["p2-1|g03|bot|70|false","p2-2|g06|bot|205|false","p2-3|g02|bot|135|false","p2-4|g09|bot|85|false","p2-5|g03|top|70|false","p2-6|g07|bot|95|false","p2-7|g05|bot|65|false","p2-8|g02|bot|135|false"],"draft_hero":"","boss_lane":"","undo":0},{"gold":260,"draft_gold":260,"ready":true,"earned":875,"spent":835,"next_seq":8,"roster":["p3-1|w03|top|75","p3-2|w02|top|150","p3-3|w06|top|195","p3-4|w03|top|75","p3-5|w07|top|100","p3-6|w09|top|90","p3-7|w02|top|150"],"hero":"","bookings":[],"new_bookings":[],"draft_roster":["p3-1|w03|top|75|false","p3-2|w02|top|150|false","p3-3|w06|top|195|false","p3-4|w03|top|75|false","p3-5|w07|top|100|false","p3-6|w09|top|90|false","p3-7|w02|top|150|false"],"draft_hero":"","boss_lane":"","undo":0},{"gold":235,"draft_gold":235,"ready":true,"earned":875,"spent":860,"next_seq":9,"roster":["p4-1|g03|mid|70","p4-2|g02|mid|135","p4-3|g06|mid|205","p4-4|g07|mid|95","p4-5|g03|mid|70","p4-6|g09|mid|85","p4-7|g02|mid|135","p4-8|g05|mid|65"],"hero":"","bookings":[],"new_bookings":[],"draft_roster":["p4-1|g03|mid|70|false","p4-2|g02|mid|135|false","p4-3|g06|mid|205|false","p4-4|g07|mid|95|false","p4-5|g03|mid|70|false","p4-6|g09|mid|85|false","p4-7|g02|mid|135|false","p4-8|g05|mid|65|false"],"draft_hero":"","boss_lane":"","undo":0},{"gold":215,"draft_gold":215,"ready":true,"earned":875,"spent":880,"next_seq":8,"roster":["p5-1|w03|bot|75","p5-2|w06|bot|195","p5-3|w02|bot|150","p5-4|w03|bot|75","p5-5|w07|bot|100","p5-6|w09|bot|90","p5-7|w06|bot|195"],"hero":"","bookings":[],"new_bookings":[],"draft_roster":["p5-1|w03|bot|75|false","p5-2|w06|bot|195|false","p5-3|w02|bot|150|false","p5-4|w03|bot|75|false","p5-5|w07|bot|100|false","p5-6|w09|bot|90|false","p5-7|w06|bot|195|false"],"draft_hero":"","boss_lane":"","undo":0}],"buildings":[7500.0,5970.1,7500.0,5867.087999999998,6786.299999999998,0.0,9000.0,9000.0,12000.0,7500.0,407.00736000000694,7500.0,2660.405000000012,7500.0,6000.0,9000.0,9000.0,12000.0],"boss":{"next":1,"settled":7,"claim":""},"boss_log":[],"announcements":[],"settlement":{"round":7,"gains":[58,58,58,108,108,108],"income":94,"lost":["blau_bot_outer"],"end_reason":"cleared","combat_time":66.49999999999837,"boss":"none","lane_kills":{"mid":10,"bot":10,"top":10},"xp":{}},"combat":{"round":7,"steps":1330,"elapsed":66.49999999999837,"finished":true,"end_reason":"cleared","destroyed":[],"grotto":"none|-1|-1|true","grotto_boss":"","grotto_boss_hp":0.0,"events":77,"mobile":[0,0,0]}},{"label":"round-8","phase":0,"round":9,"winner":-2,"end_note":"","players":[{"gold":280,"draft_gold":280,"ready":true,"earned":1100,"spent":1040,"next_seq":11,"roster":["p0-1|g02|top|135","p0-2|g06|top|205","p0-3|g03|top|70","p0-4|g07|top|95","p0-5|g02|top|135","p0-6|g05|top|65","p0-7|g02|top|135","p0-8|g03|top|70","p0-9|g09|top|85","p0-10|g01|top|45"],"hero":"","bookings":[],"new_bookings":[],"draft_roster":["p0-1|g02|top|135|false","p0-2|g06|top|205|false","p0-3|g03|top|70|false","p0-4|g07|top|95|false","p0-5|g02|top|135|false","p0-6|g05|top|65|false","p0-7|g02|top|135|false","p0-8|g03|top|70|false","p0-9|g09|top|85|false","p0-10|g01|top|45|false"],"draft_hero":"","boss_lane":"","undo":0},{"gold":320,"draft_gold":320,"ready":true,"earned":1100,"spent":1000,"next_seq":8,"roster":["p1-1|w06|mid|195","p1-2|w03|mid|75","p1-3|w07|mid|100","p1-4|w06|mid|195","p1-5|w02|mid|150","p1-6|w09|mid|90","p1-7|w06|mid|195"],"hero":"","bookings":[],"new_bookings":[],"draft_roster":["p1-1|w06|mid|195|false","p1-2|w03|mid|75|false","p1-3|w07|mid|100|false","p1-4|w06|mid|195|false","p1-5|w02|mid|150|false","p1-6|w09|mid|90|false","p1-7|w06|mid|195|false"],"draft_hero":"","boss_lane":"","undo":0},{"gold":320,"draft_gold":320,"ready":true,"earned":1100,"spent":1000,"next_seq":9,"roster":["p2-1|g03|bot|70","p2-2|g06|bot|205","p2-3|g02|bot|135","p2-4|g09|bot|85","p2-5|g03|top|70","p2-6|g07|bot|95","p2-7|g06|bot|205","p2-8|g02|bot|135"],"hero":"","bookings":[],"new_bookings":[],"draft_roster":["p2-1|g03|bot|70|false","p2-2|g06|bot|205|false","p2-3|g02|bot|135|false","p2-4|g09|bot|85|false","p2-5|g03|top|70|false","p2-6|g07|bot|95|false","p2-7|g06|bot|205|false","p2-8|g02|bot|135|false"],"draft_hero":"","boss_lane":"","undo":0},{"gold":155,"draft_gold":155,"ready":true,"earned":1030,"spent":1095,"next_seq":9,"roster":["p3-1|w03|top|75","p3-2|w02|top|150","p3-3|w06|top|195","p3-4|w03|top|75","p3-5|w07|top|100","p3-6|w09|top|90","p3-7|w02|top|150"],"hero":"h3-8|held_ringborke|308|top|||260|false|","bookings":[],"new_bookings":[],"draft_roster":["p3-1|w03|top|75|false","p3-2|w02|top|150|false","p3-3|w06|top|195|false","p3-4|w03|top|75|false","p3-5|w07|top|100|false","p3-6|w09|top|90|false","p3-7|w02|top|150|false"],"draft_hero":"h3-8|held_ringborke|308|top|||260|false|","boss_lane":"","undo":0},{"gold":180,"draft_gold":180,"ready":true,"earned":1030,"spent":1070,"next_seq":10,"roster":["p4-1|g03|mid|70","p4-2|g02|mid|135","p4-3|g06|mid|205","p4-4|g07|mid|95","p4-5|g03|mid|70","p4-6|g09|mid|85","p4-7|g02|mid|135","p4-8|g06|mid|205","p4-9|g03|mid|70"],"hero":"","bookings":[],"new_bookings":[],"draft_roster":["p4-1|g03|mid|70|false","p4-2|g02|mid|135|false","p4-3|g06|mid|205|false","p4-4|g07|mid|95|false","p4-5|g03|mid|70|false","p4-6|g09|mid|85|false","p4-7|g02|mid|135|false","p4-8|g06|mid|205|false","p4-9|g03|mid|70|false"],"draft_hero":"","boss_lane":"","undo":0},{"gold":220,"draft_gold":220,"ready":true,"earned":1030,"spent":1030,"next_seq":9,"roster":["p5-1|w03|bot|75","p5-2|w06|bot|195","p5-3|w02|bot|150","p5-4|w03|bot|75","p5-5|w07|bot|100","p5-6|w09|bot|90","p5-7|w06|bot|195"],"hero":"","bookings":["c5-8|ch_schutz|bot|150|9"],"new_bookings":[],"draft_roster":["p5-1|w03|bot|75|false","p5-2|w06|bot|195|false","p5-3|w02|bot|150|false","p5-4|w03|bot|75|false","p5-5|w07|bot|100|false","p5-6|w09|bot|90|false","p5-7|w06|bot|195|false"],"draft_hero":"","boss_lane":"","undo":0}],"buildings":[7500.0,5970.1,7500.0,5381.212999999998,6786.299999999998,0.0,9000.0,9000.0,12000.0,0.0,0.0,7500.0,2660.405000000012,7500.0,5429.625,4588.102704999993,9000.0,12000.0],"boss":{"next":12,"settled":8,"claim":"1|8|9|3|top"},"boss_log":["8|won|1||3"],"announcements":["champion|1|5|bot|ch_schutz|0","boss|1|3|top||1060"],"settlement":{"round":8,"gains":[177,177,177,57,57,57],"income":98,"lost":["rot_top_outer","rot_top_inner"],"end_reason":"cleared","combat_time":89.64999999999705,"boss":"won","lane_kills":{"mid":10,"bot":10,"top":10},"xp":{"h3-8":308}},"combat":{"round":8,"steps":1793,"elapsed":89.64999999999705,"finished":true,"end_reason":"cleared","destroyed":[],"grotto":"success|1|1|true","grotto_boss":"false|false|97","grotto_boss_hp":0.0,"events":79,"mobile":[0,3,0]}},{"label":"round-9","phase":2,"round":9,"winner":1,"end_note":"Ancient von Blau zerstört.","players":[{"gold":102,"draft_gold":20,"ready":true,"earned":1182,"spent":1300,"next_seq":12,"roster":["p0-1|g02|top|135","p0-2|g06|top|205","p0-3|g03|top|70","p0-4|g07|top|95","p0-5|g02|top|135","p0-6|g05|top|65","p0-7|g02|top|135","p0-8|g03|top|70","p0-9|g09|top|85","p0-10|g01|top|45"],"hero":"h0-11|held_funkenlanze|319|top|||260|false|","bookings":[],"new_bookings":[],"draft_roster":["p0-1|g02|top|135|false","p0-2|g06|top|205|false","p0-3|g03|top|70|false","p0-4|g07|top|95|false","p0-5|g02|top|135|false","p0-6|g05|top|65|false","p0-7|g02|top|135|false","p0-8|g03|top|70|false","p0-9|g09|top|85|false","p0-10|g01|top|45|false"],"draft_hero":"h0-11|held_funkenlanze|0|top|||260|true|","boss_lane":"","undo":0},{"gold":142,"draft_gold":60,"ready":true,"earned":1182,"spent":1260,"next_seq":9,"roster":["p1-1|w06|mid|195","p1-2|w03|mid|75","p1-3|w07|mid|100","p1-4|w06|mid|195","p1-5|w02|mid|150","p1-6|w09|mid|90","p1-7|w06|mid|195"],"hero":"h1-8|held_funkenlanze|304|mid|||260|false|","bookings":[],"new_bookings":[],"draft_roster":["p1-1|w06|mid|195|false","p1-2|w03|mid|75|false","p1-3|w07|mid|100|false","p1-4|w06|mid|195|false","p1-5|w02|mid|150|false","p1-6|w09|mid|90|false","p1-7|w06|mid|195|false"],"draft_hero":"h1-8|held_funkenlanze|0|mid|||260|true|","boss_lane":"","undo":0},{"gold":189,"draft_gold":60,"ready":true,"earned":1229,"spent":1260,"next_seq":10,"roster":["p2-1|g03|bot|70","p2-2|g06|bot|205","p2-3|g02|bot|135","p2-4|g09|bot|85","p2-5|g03|top|70","p2-6|g07|bot|95","p2-7|g06|bot|205","p2-8|g02|bot|135"],"hero":"h2-9|held_quellgeflecht|145|bot|||260|false|","bookings":[],"new_bookings":[],"draft_roster":["p2-1|g03|bot|70|false","p2-2|g06|bot|205|false","p2-3|g02|bot|135|false","p2-4|g09|bot|85|false","p2-5|g03|top|70|false","p2-6|g07|bot|95|false","p2-7|g06|bot|205|false","p2-8|g02|bot|135|false"],"draft_hero":"h2-9|held_quellgeflecht|0|bot|||260|true|","boss_lane":"","undo":0},{"gold":316,"draft_gold":0,"ready":true,"earned":1346,"spent":1250,"next_seq":9,"roster":["p3-1|w04|top|230","p3-2|w02|top|150","p3-3|w06|top|195","p3-4|w03|top|75","p3-5|w07|top|100","p3-6|w09|top|90","p3-7|w02|top|150"],"hero":"h3-8|held_ringborke|534|top||schutzwurzeln|260|false|","bookings":[],"new_bookings":[],"draft_roster":["p3-1|w04|top|230|false","p3-2|w02|top|150|false","p3-3|w06|top|195|false","p3-4|w03|top|75|false","p3-5|w07|top|100|false","p3-6|w09|top|90|false","p3-7|w02|top|150|false"],"draft_hero":"h3-8|held_ringborke|308|top||schutzwurzeln|260|false|","boss_lane":"bot","undo":0},{"gold":346,"draft_gold":30,"ready":true,"earned":1346,"spent":1220,"next_seq":10,"roster":["p4-1|g04|mid|220","p4-2|g02|mid|135","p4-3|g06|mid|205","p4-4|g07|mid|95","p4-5|g03|mid|70","p4-6|g09|mid|85","p4-7|g02|mid|135","p4-8|g06|mid|205","p4-9|g03|mid|70"],"hero":"","bookings":[],"new_bookings":[],"draft_roster":["p4-1|g04|mid|220|false","p4-2|g02|mid|135|false","p4-3|g06|mid|205|false","p4-4|g07|mid|95|false","p4-5|g03|mid|70|false","p4-6|g09|mid|85|false","p4-7|g02|mid|135|false","p4-8|g06|mid|205|false","p4-9|g03|mid|70|false"],"draft_hero":"","boss_lane":"","undo":0},{"gold":381,"draft_gold":65,"ready":true,"earned":1346,"spent":1185,"next_seq":9,"roster":["p5-1|w04|bot|230","p5-2|w06|bot|195","p5-3|w02|bot|150","p5-4|w03|bot|75","p5-5|w07|bot|100","p5-6|w09|bot|90","p5-7|w06|bot|195"],"hero":"","bookings":[],"new_bookings":[],"draft_roster":["p5-1|w04|bot|230|false","p5-2|w06|bot|195|false","p5-3|w02|bot|150|false","p5-4|w03|bot|75|false","p5-5|w07|bot|100|false","p5-6|w09|bot|90|false","p5-7|w06|bot|195|false"],"draft_hero":"","boss_lane":"","undo":0}],"buildings":[7500.0,5970.1,7500.0,5381.212999999998,0.0,0.0,0.0,0.0,0.0,0.0,0.0,7500.0,2184.605000000011,7500.0,5429.625,3162.6527049999922,9000.0,12000.0],"boss":{"next":12,"settled":9,"claim":""},"boss_log":["8|won|1||3","9|deployed|1|bot|-1"],"announcements":[],"settlement":{"round":9,"gains":[82,82,129,316,316,316],"income":102,"lost":["blau_bot_inner","blau_base_2","blau_base_1","blau_ancient"],"end_reason":"core","combat_time":136.5499999999968,"boss":"deployed","lane_kills":{"mid":10,"bot":9,"top":10},"xp":{"h1-8":304,"h2-9":145,"h0-11":319,"h3-8":226}},"combat":{"round":9,"steps":2731,"elapsed":136.5499999999968,"finished":true,"end_reason":"core","destroyed":[0],"grotto":"none|-1|-1|true","grotto_boss":"","grotto_boss_hp":0.0,"events":81,"mobile":[0,7,0]}}],"results":[]},"bot_match_3":{"title":"Vollständige Bot-Partie Seed 3 bis zum Ancient-Fall","snapshots":[{"label":"round-1","phase":0,"round":2,"winner":-2,"end_note":"","players":[{"gold":173,"draft_gold":173,"ready":true,"earned":88,"spent":135,"next_seq":3,"roster":["p0-1|w05|top|60","p0-2|w03|top|75"],"hero":"","bookings":[],"new_bookings":[],"draft_roster":["p0-1|w05|top|60|false","p0-2|w03|top|75|false"],"draft_hero":"","boss_lane":"","undo":0},{"gold":128,"draft_gold":128,"ready":true,"earned":88,"spent":180,"next_seq":4,"roster":["p1-1|g03|mid|70","p1-2|g05|mid|65","p1-3|g01|mid|45"],"hero":"","bookings":[],"new_bookings":[],"draft_roster":["p1-1|g03|mid|70|false","p1-2|g05|mid|65|false","p1-3|g01|mid|45|false"],"draft_hero":"","boss_lane":"","undo":0},{"gold":123,"draft_gold":123,"ready":true,"earned":88,"spent":185,"next_seq":4,"roster":["p2-1|w03|bot|75","p2-2|w01|bot|50","p2-3|w05|bot|60"],"hero":"","bookings":[],"new_bookings":[],"draft_roster":["p2-1|w03|bot|75|false","p2-2|w01|bot|50|false","p2-3|w05|bot|60|false"],"draft_hero":"","boss_lane":"","undo":0},{"gold":128,"draft_gold":128,"ready":true,"earned":88,"spent":180,"next_seq":4,"roster":["p3-1|g03|top|70","p3-2|g01|top|45","p3-3|g05|top|65"],"hero":"","bookings":[],"new_bookings":[],"draft_roster":["p3-1|g03|top|70|false","p3-2|g01|top|45|false","p3-3|g05|top|65|false"],"draft_hero":"","boss_lane":"","undo":0},{"gold":123,"draft_gold":123,"ready":true,"earned":88,"spent":185,"next_seq":4,"roster":["p4-1|w03|mid|75","p4-2|w05|mid|60","p4-3|w01|mid|50"],"hero":"","bookings":[],"new_bookings":[],"draft_roster":["p4-1|w03|mid|75|false","p4-2|w05|mid|60|false","p4-3|w01|mid|50|false"],"draft_hero":"","boss_lane":"","undo":0},{"gold":128,"draft_gold":128,"ready":true,"earned":88,"spent":180,"next_seq":4,"roster":["p5-1|g01|bot|45","p5-2|g05|bot|65","p5-3|g03|bot|70"],"hero":"","bookings":[],"new_bookings":[],"draft_roster":["p5-1|g01|bot|45|false","p5-2|g05|bot|65|false","p5-3|g03|bot|70|false"],"draft_hero":"","boss_lane":"","undo":0}],"buildings":[7500.0,5851.35,7500.0,6000.0,7500.0,6000.0,9000.0,9000.0,12000.0,7500.0,6000.0,7500.0,6000.0,7500.0,5970.1,9000.0,9000.0,12000.0],"boss":{"next":1,"settled":1,"claim":""},"boss_log":[],"announcements":[],"settlement":{"round":1,"gains":[18,18,18,18,18,18],"income":70,"lost":[],"end_reason":"cleared","combat_time":43.499999999999666,"boss":"none","lane_kills":{"mid":6,"bot":6,"top":6},"xp":{}},"combat":{"round":1,"steps":870,"elapsed":43.499999999999666,"finished":true,"end_reason":"cleared","destroyed":[],"grotto":"none|-1|-1|true","grotto_boss":"","grotto_boss_hp":0.0,"events":35,"mobile":[0,0,0]}},{"label":"round-2","phase":0,"round":3,"winner":-2,"end_note":"","players":[{"gold":105,"draft_gold":105,"ready":true,"earned":180,"spent":295,"next_seq":5,"roster":["p0-1|w05|top|60","p0-2|w03|top|75","p0-3|w07|top|100","p0-4|w05|top|60"],"hero":"","bookings":[],"new_bookings":[],"draft_roster":["p0-1|w05|top|60|false","p0-2|w03|top|75|false","p0-3|w07|top|100|false","p0-4|w05|top|60|false"],"draft_hero":"","boss_lane":"","undo":0},{"gold":135,"draft_gold":135,"ready":true,"earned":180,"spent":265,"next_seq":5,"roster":["p1-1|g03|mid|70","p1-2|g05|mid|65","p1-3|g01|mid|45","p1-4|g09|mid|85"],"hero":"","bookings":[],"new_bookings":[],"draft_roster":["p1-1|g03|mid|70|false","p1-2|g05|mid|65|false","p1-3|g01|mid|45|false","p1-4|g09|mid|85|false"],"draft_hero":"","boss_lane":"","undo":0},{"gold":140,"draft_gold":140,"ready":true,"earned":180,"spent":260,"next_seq":5,"roster":["p2-1|w03|bot|75","p2-2|w01|bot|50","p2-3|w05|bot|60","p2-4|w03|bot|75"],"hero":"","bookings":[],"new_bookings":[],"draft_roster":["p2-1|w03|bot|75|false","p2-2|w01|bot|50|false","p2-3|w05|bot|60|false","p2-4|w03|bot|75|false"],"draft_hero":"","boss_lane":"","undo":0},{"gold":125,"draft_gold":125,"ready":true,"earned":180,"spent":275,"next_seq":5,"roster":["p3-1|g03|top|70","p3-2|g01|top|45","p3-3|g05|top|65","p3-4|g07|top|95"],"hero":"","bookings":[],"new_bookings":[],"draft_roster":["p3-1|g03|top|70|false","p3-2|g01|top|45|false","p3-3|g05|top|65|false","p3-4|g07|top|95|false"],"draft_hero":"","boss_lane":"","undo":0},{"gold":140,"draft_gold":140,"ready":true,"earned":180,"spent":260,"next_seq":5,"roster":["p4-1|w03|mid|75","p4-2|w05|mid|60","p4-3|w01|mid|50","p4-4|w03|mid|75"],"hero":"","bookings":[],"new_bookings":[],"draft_roster":["p4-1|w03|mid|75|false","p4-2|w05|mid|60|false","p4-3|w01|mid|50|false","p4-4|w03|mid|75|false"],"draft_hero":"","boss_lane":"","undo":0},{"gold":125,"draft_gold":125,"ready":true,"earned":180,"spent":275,"next_seq":5,"roster":["p5-1|g01|bot|45","p5-2|g05|bot|65","p5-3|g03|bot|70","p5-4|g07|bot|95"],"hero":"","bookings":[],"new_bookings":[],"draft_roster":["p5-1|g01|bot|45|false","p5-2|g05|bot|65|false","p5-3|g03|bot|70|false","p5-4|g07|bot|95|false"],"draft_hero":"","boss_lane":"","undo":0}],"buildings":[7500.0,5851.35,7500.0,6000.0,7500.0,6000.0,9000.0,9000.0,12000.0,7500.0,5850.500000000002,7500.0,5878.8,7500.0,5910.300000000001,9000.0,9000.0,12000.0],"boss":{"next":1,"settled":2,"claim":""},"boss_log":[],"announcements":[],"settlement":{"round":2,"gains":[18,18,18,18,18,18],"income":74,"lost":[],"end_reason":"cleared","combat_time":49.699999999999314,"boss":"none","lane_kills":{"mid":6,"bot":6,"top":6},"xp":{}},"combat":{"round":2,"steps":994,"elapsed":49.699999999999314,"finished":true,"end_reason":"cleared","destroyed":[],"grotto":"none|-1|-1|true","grotto_boss":"","grotto_boss_hp":0.0,"events":42,"mobile":[0,0,0]}},{"label":"round-3","phase":0,"round":4,"winner":-2,"end_note":"","players":[{"gold":165,"draft_gold":165,"ready":true,"earned":290,"spent":345,"next_seq":6,"roster":["p0-1|w05|top|60","p0-2|w03|top|75","p0-3|w07|top|100","p0-4|w05|top|60","p0-5|w01|top|50"],"hero":"","bookings":[],"new_bookings":[],"draft_roster":["p0-1|w05|top|60|false","p0-2|w03|top|75|false","p0-3|w07|top|100|false","p0-4|w05|top|60|false","p0-5|w01|top|50|false"],"draft_hero":"","boss_lane":"","undo":0},{"gold":175,"draft_gold":175,"ready":true,"earned":290,"spent":335,"next_seq":6,"roster":["p1-1|g03|mid|70","p1-2|g05|mid|65","p1-3|g01|mid|45","p1-4|g09|mid|85","p1-5|g03|mid|70"],"hero":"","bookings":[],"new_bookings":[],"draft_roster":["p1-1|g03|mid|70|false","p1-2|g05|mid|65|false","p1-3|g01|mid|45|false","p1-4|g09|mid|85|false","p1-5|g03|mid|70|false"],"draft_hero":"","boss_lane":"","undo":0},{"gold":150,"draft_gold":150,"ready":true,"earned":290,"spent":360,"next_seq":6,"roster":["p2-1|w03|bot|75","p2-2|w01|bot|50","p2-3|w05|bot|60","p2-4|w03|bot|75","p2-5|w07|bot|100"],"hero":"","bookings":[],"new_bookings":[],"draft_roster":["p2-1|w03|bot|75|false","p2-2|w01|bot|50|false","p2-3|w05|bot|60|false","p2-4|w03|bot|75|false","p2-5|w07|bot|100|false"],"draft_hero":"","boss_lane":"","undo":0},{"gold":165,"draft_gold":165,"ready":true,"earned":290,"spent":345,"next_seq":6,"roster":["p3-1|g03|top|70","p3-2|g01|top|45","p3-3|g05|top|65","p3-4|g07|top|95","p3-5|g03|top|70"],"hero":"","bookings":[],"new_bookings":[],"draft_roster":["p3-1|g03|top|70|false","p3-2|g01|top|45|false","p3-3|g05|top|65|false","p3-4|g07|top|95|false","p3-5|g03|top|70|false"],"draft_hero":"","boss_lane":"","undo":0},{"gold":150,"draft_gold":150,"ready":true,"earned":290,"spent":360,"next_seq":6,"roster":["p4-1|w03|mid|75","p4-2|w05|mid|60","p4-3|w01|mid|50","p4-4|w03|mid|75","p4-5|w07|mid|100"],"hero":"","bookings":[],"new_bookings":[],"draft_roster":["p4-1|w03|mid|75|false","p4-2|w05|mid|60|false","p4-3|w01|mid|50|false","p4-4|w03|mid|75|false","p4-5|w07|mid|100|false"],"draft_hero":"","boss_lane":"","undo":0},{"gold":125,"draft_gold":125,"ready":true,"earned":290,"spent":385,"next_seq":7,"roster":["p5-1|g01|bot|45","p5-2|g05|bot|65","p5-3|g03|bot|70","p5-4|g07|bot|95","p5-5|g01|bot|45","p5-6|g05|bot|65"],"hero":"","bookings":[],"new_bookings":[],"draft_roster":["p5-1|g01|bot|45|false","p5-2|g05|bot|65|false","p5-3|g03|bot|70|false","p5-4|g07|bot|95|false","p5-5|g01|bot|45|false","p5-6|g05|bot|65|false"],"draft_hero":"","boss_lane":"","undo":0}],"buildings":[7500.0,5851.35,7500.0,5836.4000000000015,7500.0,5672.4000000000005,9000.0,9000.0,12000.0,7500.0,5730.900000000003,7500.0,5878.8,7500.0,5910.300000000001,9000.0,9000.0,12000.0],"boss":{"next":1,"settled":3,"claim":""},"boss_log":[],"announcements":[],"settlement":{"round":3,"gains":[32,32,32,32,32,32],"income":78,"lost":[],"end_reason":"cleared","combat_time":51.39999999999922,"boss":"none","lane_kills":{"mid":6,"top":6,"bot":6},"xp":{}},"combat":{"round":3,"steps":1028,"elapsed":51.39999999999922,"finished":true,"end_reason":"cleared","destroyed":[],"grotto":"none|-1|-1|true","grotto_boss":"","grotto_boss_hp":0.0,"events":49,"mobile":[0,0,0]}},{"label":"round-4","phase":0,"round":5,"winner":-2,"end_note":"","players":[{"gold":137,"draft_gold":137,"ready":true,"earned":412,"spent":495,"next_seq":8,"roster":["p0-1|w05|top|60","p0-2|w03|top|75","p0-3|w07|top|100","p0-4|w05|top|60","p0-5|w01|top|50","p0-6|w09|top|90","p0-7|w05|top|60"],"hero":"","bookings":[],"new_bookings":[],"draft_roster":["p0-1|w05|top|60|false","p0-2|w03|top|75|false","p0-3|w07|top|100|false","p0-4|w05|top|60|false","p0-5|w01|top|50|false","p0-6|w09|top|90|false","p0-7|w05|top|60|false"],"draft_hero":"","boss_lane":"","undo":0},{"gold":137,"draft_gold":137,"ready":true,"earned":412,"spent":495,"next_seq":8,"roster":["p1-1|g03|mid|70","p1-2|g05|mid|65","p1-3|g01|mid|45","p1-4|g09|mid|85","p1-5|g03|mid|70","p1-6|g07|top|95","p1-7|g05|top|65"],"hero":"","bookings":[],"new_bookings":[],"draft_roster":["p1-1|g03|mid|70|false","p1-2|g05|mid|65|false","p1-3|g01|mid|45|false","p1-4|g09|mid|85|false","p1-5|g03|mid|70|false","p1-6|g07|top|95|false","p1-7|g05|top|65|false"],"draft_hero":"","boss_lane":"","undo":0},{"gold":132,"draft_gold":132,"ready":true,"earned":412,"spent":500,"next_seq":8,"roster":["p2-1|w03|bot|75","p2-2|w01|bot|50","p2-3|w05|bot|60","p2-4|w03|bot|75","p2-5|w07|bot|100","p2-6|w09|bot|90","p2-7|w01|bot|50"],"hero":"","bookings":[],"new_bookings":[],"draft_roster":["p2-1|w03|bot|75|false","p2-2|w01|bot|50|false","p2-3|w05|bot|60|false","p2-4|w03|bot|75|false","p2-5|w07|bot|100|false","p2-6|w09|bot|90|false","p2-7|w01|bot|50|false"],"draft_hero":"","boss_lane":"","undo":0},{"gold":157,"draft_gold":157,"ready":true,"earned":412,"spent":475,"next_seq":8,"roster":["p3-1|g03|top|70","p3-2|g01|top|45","p3-3|g05|top|65","p3-4|g07|top|95","p3-5|g03|top|70","p3-6|g09|top|85","p3-7|g01|top|45"],"hero":"","bookings":[],"new_bookings":[],"draft_roster":["p3-1|g03|top|70|false","p3-2|g01|top|45|false","p3-3|g05|top|65|false","p3-4|g07|top|95|false","p3-5|g03|top|70|false","p3-6|g09|top|85|false","p3-7|g01|top|45|false"],"draft_hero":"","boss_lane":"","undo":0},{"gold":122,"draft_gold":122,"ready":true,"earned":412,"spent":510,"next_seq":8,"roster":["p4-1|w03|mid|75","p4-2|w05|mid|60","p4-3|w01|mid|50","p4-4|w03|mid|75","p4-5|w07|mid|100","p4-6|w09|mid|90","p4-7|w05|mid|60"],"hero":"","bookings":[],"new_bookings":[],"draft_roster":["p4-1|w03|mid|75|false","p4-2|w05|mid|60|false","p4-3|w01|mid|50|false","p4-4|w03|mid|75|false","p4-5|w07|mid|100|false","p4-6|w09|mid|90|false","p4-7|w05|mid|60|false"],"draft_hero":"","boss_lane":"","undo":0},{"gold":132,"draft_gold":132,"ready":true,"earned":412,"spent":500,"next_seq":9,"roster":["p5-1|g01|bot|45","p5-2|g05|bot|65","p5-3|g03|bot|70","p5-4|g07|bot|95","p5-5|g01|bot|45","p5-6|g05|bot|65","p5-7|g01|bot|45","p5-8|g03|bot|70"],"hero":"","bookings":[],"new_bookings":[],"draft_roster":["p5-1|g01|bot|45|false","p5-2|g05|bot|65|false","p5-3|g03|bot|70|false","p5-4|g07|bot|95|false","p5-5|g01|bot|45|false","p5-6|g05|bot|65|false","p5-7|g01|bot|45|false","p5-8|g03|bot|70|false"],"draft_hero":"","boss_lane":"","undo":0}],"buildings":[7500.0,5851.35,7500.0,3942.840200000014,7500.0,5384.200000000002,9000.0,9000.0,12000.0,7500.0,2201.200000000007,7500.0,5878.8,7500.0,5910.300000000001,9000.0,9000.0,12000.0],"boss":{"next":1,"settled":4,"claim":""},"boss_log":[],"announcements":[],"settlement":{"round":4,"gains":[40,40,40,40,40,40],"income":82,"lost":[],"end_reason":"cleared","combat_time":67.6999999999983,"boss":"none","lane_kills":{"mid":8,"bot":8,"top":8},"xp":{}},"combat":{"round":4,"steps":1354,"elapsed":67.6999999999983,"finished":true,"end_reason":"cleared","destroyed":[],"grotto":"none|-1|-1|true","grotto_boss":"","grotto_boss_hp":0.0,"events":67,"mobile":[0,0,0]}},{"label":"round-5","phase":0,"round":6,"winner":-2,"end_note":"","players":[{"gold":168,"draft_gold":168,"ready":true,"earned":543,"spent":595,"next_seq":8,"roster":["p0-1|w05|top|60","p0-2|w03|top|75","p0-3|w07|top|100","p0-4|w05|top|60","p0-5|w02|top|150","p0-6|w09|top|90","p0-7|w05|top|60"],"hero":"","bookings":[],"new_bookings":[],"draft_roster":["p0-1|w05|top|60|false","p0-2|w03|top|75|false","p0-3|w07|top|100|false","p0-4|w05|top|60|false","p0-5|w02|top|150|false","p0-6|w09|top|90|false","p0-7|w05|top|60|false"],"draft_hero":"","boss_lane":"","undo":0},{"gold":133,"draft_gold":133,"ready":true,"earned":543,"spent":630,"next_seq":9,"roster":["p1-1|g03|mid|70","p1-2|g05|mid|65","p1-3|g02|mid|135","p1-4|g09|mid|85","p1-5|g03|mid|70","p1-6|g07|top|95","p1-7|g05|top|65","p1-8|g01|mid|45"],"hero":"","bookings":[],"new_bookings":[],"draft_roster":["p1-1|g03|mid|70|false","p1-2|g05|mid|65|false","p1-3|g02|mid|135|false","p1-4|g09|mid|85|false","p1-5|g03|mid|70|false","p1-6|g07|top|95|false","p1-7|g05|top|65|false","p1-8|g01|mid|45|false"],"draft_hero":"","boss_lane":"","undo":0},{"gold":163,"draft_gold":163,"ready":true,"earned":543,"spent":600,"next_seq":8,"roster":["p2-1|w03|bot|75","p2-2|w02|bot|150","p2-3|w05|bot|60","p2-4|w03|bot|75","p2-5|w07|bot|100","p2-6|w09|bot|90","p2-7|w01|bot|50"],"hero":"","bookings":[],"new_bookings":[],"draft_roster":["p2-1|w03|bot|75|false","p2-2|w02|bot|150|false","p2-3|w05|bot|60|false","p2-4|w03|bot|75|false","p2-5|w07|bot|100|false","p2-6|w09|bot|90|false","p2-7|w01|bot|50|false"],"draft_hero":"","boss_lane":"","undo":0},{"gold":133,"draft_gold":133,"ready":true,"earned":543,"spent":630,"next_seq":9,"roster":["p3-1|g03|top|70","p3-2|g02|top|135","p3-3|g05|top|65","p3-4|g07|top|95","p3-5|g03|top|70","p3-6|g09|top|85","p3-7|g01|top|45","p3-8|g05|top|65"],"hero":"","bookings":[],"new_bookings":[],"draft_roster":["p3-1|g03|top|70|false","p3-2|g02|top|135|false","p3-3|g05|top|65|false","p3-4|g07|top|95|false","p3-5|g03|top|70|false","p3-6|g09|top|85|false","p3-7|g01|top|45|false","p3-8|g05|top|65|false"],"draft_hero":"","boss_lane":"","undo":0},{"gold":153,"draft_gold":153,"ready":true,"earned":543,"spent":610,"next_seq":8,"roster":["p4-1|w03|mid|75","p4-2|w05|mid|60","p4-3|w02|mid|150","p4-4|w03|mid|75","p4-5|w07|mid|100","p4-6|w09|mid|90","p4-7|w05|mid|60"],"hero":"","bookings":[],"new_bookings":[],"draft_roster":["p4-1|w03|mid|75|false","p4-2|w05|mid|60|false","p4-3|w02|mid|150|false","p4-4|w03|mid|75|false","p4-5|w07|mid|100|false","p4-6|w09|mid|90|false","p4-7|w05|mid|60|false"],"draft_hero":"","boss_lane":"","undo":0},{"gold":173,"draft_gold":173,"ready":true,"earned":543,"spent":590,"next_seq":9,"roster":["p5-1|g02|bot|135","p5-2|g05|bot|65","p5-3|g03|bot|70","p5-4|g07|bot|95","p5-5|g01|bot|45","p5-6|g05|bot|65","p5-7|g01|bot|45","p5-8|g03|bot|70"],"hero":"","bookings":[],"new_bookings":[],"draft_roster":["p5-1|g02|bot|135|false","p5-2|g05|bot|65|false","p5-3|g03|bot|70|false","p5-4|g07|bot|95|false","p5-5|g01|bot|45|false","p5-6|g05|bot|65|false","p5-7|g01|bot|45|false","p5-8|g03|bot|70|false"],"draft_hero":"","boss_lane":"","undo":0}],"buildings":[7500.0,5851.35,7500.0,2376.813800000012,7500.0,4913.579199999994,9000.0,9000.0,12000.0,7500.0,15.6520000000051,7500.0,5878.8,7500.0,5910.300000000001,9000.0,9000.0,12000.0],"boss":{"next":1,"settled":5,"claim":""},"boss_log":[],"announcements":[],"settlement":{"round":5,"gains":[45,45,45,45,45,45],"income":86,"lost":[],"end_reason":"cleared","combat_time":61.69999999999863,"boss":"none","lane_kills":{"mid":8,"bot":8,"top":8},"xp":{}},"combat":{"round":5,"steps":1234,"elapsed":61.69999999999863,"finished":true,"end_reason":"cleared","destroyed":[],"grotto":"none|-1|-1|true","grotto_boss":"","grotto_boss_hp":0.0,"events":69,"mobile":[0,0,0]}},{"label":"round-6","phase":0,"round":7,"winner":-2,"end_note":"","players":[{"gold":213,"draft_gold":213,"ready":true,"earned":723,"spent":730,"next_seq":8,"roster":["p0-1|w06|top|195","p0-2|w03|top|75","p0-3|w07|top|100","p0-4|w05|top|60","p0-5|w02|top|150","p0-6|w09|top|90","p0-7|w05|top|60"],"hero":"","bookings":[],"new_bookings":[],"draft_roster":["p0-1|w06|top|195|false","p0-2|w03|top|75|false","p0-3|w07|top|100|false","p0-4|w05|top|60|false","p0-5|w02|top|150|false","p0-6|w09|top|90|false","p0-7|w05|top|60|false"],"draft_hero":"","boss_lane":"","undo":0},{"gold":223,"draft_gold":223,"ready":true,"earned":723,"spent":720,"next_seq":9,"roster":["p1-1|g03|mid|70","p1-2|g05|mid|65","p1-3|g02|mid|135","p1-4|g09|mid|85","p1-5|g03|mid|70","p1-6|g07|top|95","p1-7|g05|top|65","p1-8|g02|mid|135"],"hero":"","bookings":[],"new_bookings":[],"draft_roster":["p1-1|g03|mid|70|false","p1-2|g05|mid|65|false","p1-3|g02|mid|135|false","p1-4|g09|mid|85|false","p1-5|g03|mid|70|false","p1-6|g07|top|95|false","p1-7|g05|top|65|false","p1-8|g02|mid|135|false"],"draft_hero":"","boss_lane":"","undo":0},{"gold":243,"draft_gold":243,"ready":true,"earned":723,"spent":700,"next_seq":8,"roster":["p2-1|w03|bot|75","p2-2|w02|bot|150","p2-3|w05|bot|60","p2-4|w03|bot|75","p2-5|w07|bot|100","p2-6|w09|bot|90","p2-7|w02|bot|150"],"hero":"","bookings":[],"new_bookings":[],"draft_roster":["p2-1|w03|bot|75|false","p2-2|w02|bot|150|false","p2-3|w05|bot|60|false","p2-4|w03|bot|75|false","p2-5|w07|bot|100|false","p2-6|w09|bot|90|false","p2-7|w02|bot|150|false"],"draft_hero":"","boss_lane":"","undo":0},{"gold":223,"draft_gold":223,"ready":true,"earned":723,"spent":720,"next_seq":9,"roster":["p3-1|g03|top|70","p3-2|g02|top|135","p3-3|g05|top|65","p3-4|g07|top|95","p3-5|g03|top|70","p3-6|g09|top|85","p3-7|g02|top|135","p3-8|g05|top|65"],"hero":"","bookings":[],"new_bookings":[],"draft_roster":["p3-1|g03|top|70|false","p3-2|g02|top|135|false","p3-3|g05|top|65|false","p3-4|g07|top|95|false","p3-5|g03|top|70|false","p3-6|g09|top|85|false","p3-7|g02|top|135|false","p3-8|g05|top|65|false"],"draft_hero":"","boss_lane":"","undo":0},{"gold":198,"draft_gold":198,"ready":true,"earned":723,"spent":745,"next_seq":8,"roster":["p4-1|w03|mid|75","p4-2|w06|mid|195","p4-3|w02|mid|150","p4-4|w03|mid|75","p4-5|w07|mid|100","p4-6|w09|mid|90","p4-7|w05|mid|60"],"hero":"","bookings":[],"new_bookings":[],"draft_roster":["p4-1|w03|mid|75|false","p4-2|w06|mid|195|false","p4-3|w02|mid|150|false","p4-4|w03|mid|75|false","p4-5|w07|mid|100|false","p4-6|w09|mid|90|false","p4-7|w05|mid|60|false"],"draft_hero":"","boss_lane":"","undo":0},{"gold":263,"draft_gold":263,"ready":true,"earned":723,"spent":680,"next_seq":9,"roster":["p5-1|g02|bot|135","p5-2|g05|bot|65","p5-3|g03|bot|70","p5-4|g07|bot|95","p5-5|g02|bot|135","p5-6|g05|bot|65","p5-7|g01|bot|45","p5-8|g03|bot|70"],"hero":"","bookings":[],"new_bookings":[],"draft_roster":["p5-1|g02|bot|135|false","p5-2|g05|bot|65|false","p5-3|g03|bot|70|false","p5-4|g07|bot|95|false","p5-5|g02|bot|135|false","p5-6|g05|bot|65|false","p5-7|g01|bot|45|false","p5-8|g03|bot|70|false"],"draft_hero":"","boss_lane":"","undo":0}],"buildings":[7500.0,5851.35,7103.499999999999,0.0,7500.0,4453.019199999991,9000.0,9000.0,12000.0,3828.309999999995,0.0,7500.0,5878.8,7500.0,5910.300000000001,9000.0,9000.0,12000.0],"boss":{"next":1,"settled":6,"claim":""},"boss_log":[],"announcements":[],"settlement":{"round":6,"gains":[90,90,90,90,90,90],"income":90,"lost":["rot_top_outer","blau_mid_outer"],"end_reason":"cleared","combat_time":68.74999999999824,"boss":"none","lane_kills":{"mid":8,"bot":8,"top":8},"xp":{}},"combat":{"round":6,"steps":1375,"elapsed":68.74999999999824,"finished":true,"end_reason":"cleared","destroyed":[],"grotto":"none|-1|-1|true","grotto_boss":"","grotto_boss_hp":0.0,"events":71,"mobile":[0,0,0]}},{"label":"round-7","phase":0,"round":8,"winner":-2,"end_note":"","players":[{"gold":215,"draft_gold":215,"ready":true,"earned":875,"spent":880,"next_seq":9,"roster":["p0-1|w06|top|195","p0-2|w03|top|75","p0-3|w07|top|100","p0-4|w05|top|60","p0-5|w02|top|150","p0-6|w09|top|90","p0-7|w05|top|60"],"hero":"","bookings":["c0-8|ch_druck|top|150|8"],"new_bookings":[],"draft_roster":["p0-1|w06|top|195|false","p0-2|w03|top|75|false","p0-3|w07|top|100|false","p0-4|w05|top|60|false","p0-5|w02|top|150|false","p0-6|w09|top|90|false","p0-7|w05|top|60|false"],"draft_hero":"","boss_lane":"","undo":0},{"gold":155,"draft_gold":155,"ready":true,"earned":875,"spent":940,"next_seq":11,"roster":["p1-1|g03|mid|70","p1-2|g05|mid|65","p1-3|g02|mid|135","p1-4|g09|mid|85","p1-5|g03|mid|70","p1-6|g07|top|95","p1-7|g05|top|65","p1-8|g02|mid|135","p1-10|g03|mid|70"],"hero":"","bookings":["c1-9|ch_schutz|mid|150|8"],"new_bookings":[],"draft_roster":["p1-1|g03|mid|70|false","p1-2|g05|mid|65|false","p1-3|g02|mid|135|false","p1-4|g09|mid|85|false","p1-5|g03|mid|70|false","p1-6|g07|top|95|false","p1-7|g05|top|65|false","p1-8|g02|mid|135|false","p1-10|g03|mid|70|false"],"draft_hero":"","boss_lane":"","undo":0},{"gold":215,"draft_gold":215,"ready":true,"earned":875,"spent":880,"next_seq":9,"roster":["p2-1|w03|bot|75","p2-2|w02|bot|150","p2-3|w05|bot|60","p2-4|w03|bot|75","p2-5|w07|bot|100","p2-6|w09|bot|90","p2-7|w02|bot|150"],"hero":"","bookings":["c2-8|ch_belagerung|bot|180|8"],"new_bookings":[],"draft_roster":["p2-1|w03|bot|75|false","p2-2|w02|bot|150|false","p2-3|w05|bot|60|false","p2-4|w03|bot|75|false","p2-5|w07|bot|100|false","p2-6|w09|bot|90|false","p2-7|w02|bot|150|false"],"draft_hero":"","boss_lane":"","undo":0},{"gold":165,"draft_gold":165,"ready":true,"earned":875,"spent":930,"next_seq":10,"roster":["p3-1|g03|top|70","p3-2|g02|top|135","p3-3|g06|top|205","p3-4|g07|top|95","p3-5|g03|top|70","p3-6|g09|top|85","p3-7|g02|top|135","p3-8|g05|top|65","p3-9|g03|top|70"],"hero":"","bookings":[],"new_bookings":[],"draft_roster":["p3-1|g03|top|70|false","p3-2|g02|top|135|false","p3-3|g06|top|205|false","p3-4|g07|top|95|false","p3-5|g03|top|70|false","p3-6|g09|top|85|false","p3-7|g02|top|135|false","p3-8|g05|top|65|false","p3-9|g03|top|70|false"],"draft_hero":"","boss_lane":"","undo":0},{"gold":200,"draft_gold":200,"ready":true,"earned":875,"spent":895,"next_seq":9,"roster":["p4-1|w03|mid|75","p4-2|w06|mid|195","p4-3|w02|mid|150","p4-4|w03|mid|75","p4-5|w07|mid|100","p4-6|w09|mid|90","p4-7|w05|mid|60"],"hero":"","bookings":["c4-8|ch_schutz|mid|150|8"],"new_bookings":[],"draft_roster":["p4-1|w03|mid|75|false","p4-2|w06|mid|195|false","p4-3|w02|mid|150|false","p4-4|w03|mid|75|false","p4-5|w07|mid|100|false","p4-6|w09|mid|90|false","p4-7|w05|mid|60|false"],"draft_hero":"","boss_lane":"","undo":0},{"gold":155,"draft_gold":155,"ready":true,"earned":875,"spent":940,"next_seq":10,"roster":["p5-1|g02|bot|135","p5-2|g05|bot|65","p5-3|g03|bot|70","p5-4|g07|bot|95","p5-5|g02|bot|135","p5-6|g05|bot|65","p5-7|g01|bot|45","p5-8|g03|bot|70"],"hero":"h5-9|held_funkenlanze|282|bot|||260|false|","bookings":[],"new_bookings":[],"draft_roster":["p5-1|g02|bot|135|false","p5-2|g05|bot|65|false","p5-3|g03|bot|70|false","p5-4|g07|bot|95|false","p5-5|g02|bot|135|false","p5-6|g05|bot|65|false","p5-7|g01|bot|45|false","p5-8|g03|bot|70|false"],"draft_hero":"h5-9|held_funkenlanze|282|bot|||260|false|","boss_lane":"","undo":0}],"buildings":[7500.0,4833.611200000001,3301.181200000009,0.0,7500.0,396.15279999999217,9000.0,9000.0,12000.0,3828.309999999995,0.0,7500.0,5878.8,7500.0,5910.300000000001,9000.0,9000.0,12000.0],"boss":{"next":1,"settled":7,"claim":""},"boss_log":[],"announcements":["champion|0|0|top|ch_druck|0","champion|0|1|mid|ch_schutz|0","champion|0|2|bot|ch_belagerung|0","champion|1|4|mid|ch_schutz|0"],"settlement":{"round":7,"gains":[58,58,58,58,58,58],"income":94,"lost":[],"end_reason":"cleared","combat_time":70.74999999999812,"boss":"none","lane_kills":{"mid":10,"bot":10,"top":10},"xp":{"h5-9":282}},"combat":{"round":7,"steps":1415,"elapsed":70.74999999999812,"finished":true,"end_reason":"cleared","destroyed":[],"grotto":"none|-1|-1|true","grotto_boss":"","grotto_boss_hp":0.0,"events":78,"mobile":[0,0,0]}},{"label":"round-8","phase":0,"round":9,"winner":-2,"end_note":"","players":[{"gold":250,"draft_gold":250,"ready":true,"earned":1120,"spent":1090,"next_seq":10,"roster":["p0-1|w06|top|195","p0-2|w03|top|75","p0-3|w07|top|100","p0-4|w06|top|195","p0-5|w02|top|150","p0-6|w09|top|90","p0-7|w05|top|60","p0-9|w03|top|75"],"hero":"","bookings":[],"new_bookings":[],"draft_roster":["p0-1|w06|top|195|false","p0-2|w03|top|75|false","p0-3|w07|top|100|false","p0-4|w06|top|195|false","p0-5|w02|top|150|false","p0-6|w09|top|90|false","p0-7|w05|top|60|false","p0-9|w03|top|75|false"],"draft_hero":"","boss_lane":"","undo":0},{"gold":319,"draft_gold":319,"ready":true,"earned":1179,"spent":1080,"next_seq":11,"roster":["p1-1|g03|mid|70","p1-2|g06|mid|205","p1-3|g02|mid|135","p1-4|g09|mid|85","p1-5|g03|mid|70","p1-6|g07|top|95","p1-7|g05|top|65","p1-8|g02|mid|135","p1-10|g03|mid|70"],"hero":"","bookings":[],"new_bookings":[],"draft_roster":["p1-1|g03|mid|70|false","p1-2|g06|mid|205|false","p1-3|g02|mid|135|false","p1-4|g09|mid|85|false","p1-5|g03|mid|70|false","p1-6|g07|top|95|false","p1-7|g05|top|65|false","p1-8|g02|mid|135|false","p1-10|g03|mid|70|false"],"draft_hero":"","boss_lane":"","undo":0},{"gold":249,"draft_gold":249,"ready":true,"earned":1119,"spent":1090,"next_seq":10,"roster":["p2-1|w03|bot|75","p2-2|w02|bot|150","p2-3|w06|bot|195","p2-4|w03|bot|75","p2-5|w07|bot|100","p2-6|w09|bot|90","p2-7|w02|bot|150","p2-9|w03|mid|75"],"hero":"","bookings":[],"new_bookings":[],"draft_roster":["p2-1|w03|bot|75|false","p2-2|w02|bot|150|false","p2-3|w06|bot|195|false","p2-4|w03|bot|75|false","p2-5|w07|bot|100|false","p2-6|w09|bot|90|false","p2-7|w02|bot|150|false","p2-9|w03|mid|75|false"],"draft_hero":"","boss_lane":"","undo":0},{"gold":298,"draft_gold":298,"ready":true,"earned":1148,"spent":1070,"next_seq":10,"roster":["p3-1|g03|top|70","p3-2|g02|top|135","p3-3|g06|top|205","p3-4|g07|top|95","p3-5|g03|top|70","p3-6|g09|top|85","p3-7|g02|top|135","p3-8|g06|top|205","p3-9|g03|top|70"],"hero":"","bookings":[],"new_bookings":[],"draft_roster":["p3-1|g03|top|70|false","p3-2|g02|top|135|false","p3-3|g06|top|205|false","p3-4|g07|top|95|false","p3-5|g03|top|70|false","p3-6|g09|top|85|false","p3-7|g02|top|135|false","p3-8|g06|top|205|false","p3-9|g03|top|70|false"],"draft_hero":"","boss_lane":"","undo":0},{"gold":338,"draft_gold":338,"ready":true,"earned":1148,"spent":1030,"next_seq":9,"roster":["p4-1|w03|mid|75","p4-2|w06|mid|195","p4-3|w02|mid|150","p4-4|w03|mid|75","p4-5|w07|mid|100","p4-6|w09|mid|90","p4-7|w06|mid|195"],"hero":"","bookings":[],"new_bookings":[],"draft_roster":["p4-1|w03|mid|75|false","p4-2|w06|mid|195|false","p4-3|w02|mid|150|false","p4-4|w03|mid|75|false","p4-5|w07|mid|100|false","p4-6|w09|mid|90|false","p4-7|w06|mid|195|false"],"draft_hero":"","boss_lane":"","undo":0},{"gold":338,"draft_gold":338,"ready":true,"earned":1148,"spent":1030,"next_seq":10,"roster":["p5-1|g02|bot|135","p5-2|g05|bot|65","p5-3|g03|bot|70","p5-4|g07|bot|95","p5-5|g02|bot|135","p5-6|g05|bot|65","p5-7|g02|bot|135","p5-8|g03|bot|70"],"hero":"h5-9|held_funkenlanze|536|bot||splitterschuss|260|false|","bookings":[],"new_bookings":[],"draft_roster":["p5-1|g02|bot|135|false","p5-2|g05|bot|65|false","p5-3|g03|bot|70|false","p5-4|g07|bot|95|false","p5-5|g02|bot|135|false","p5-6|g05|bot|65|false","p5-7|g02|bot|135|false","p5-8|g03|bot|70|false"],"draft_hero":"h5-9|held_funkenlanze|536|bot||splitterschuss|260|false|","boss_lane":"","undo":0}],"buildings":[7500.0,4833.611200000001,1245.5094000000074,0.0,7500.0,396.15279999999217,9000.0,9000.0,12000.0,0.0,0.0,7500.0,5878.8,7500.0,3623.788,6543.4000000000005,9000.0,12000.0],"boss":{"next":1,"settled":8,"claim":""},"boss_log":[],"announcements":[],"settlement":{"round":8,"gains":[147,206,146,175,175,175],"income":98,"lost":["rot_top_inner"],"end_reason":"cleared","combat_time":82.69999999999744,"boss":"none","lane_kills":{"mid":12,"bot":11,"top":11},"xp":{"h5-9":254}},"combat":{"round":8,"steps":1654,"elapsed":82.69999999999744,"finished":true,"end_reason":"cleared","destroyed":[],"grotto":"none|-1|-1|true","grotto_boss":"","grotto_boss_hp":0.0,"events":85,"mobile":[0,0,0]}},{"label":"round-9","phase":0,"round":10,"winner":-2,"end_note":"","players":[{"gold":223,"draft_gold":223,"ready":true,"earned":1288,"spent":1285,"next_seq":11,"roster":["p0-1|w06|top|195","p0-2|w03|top|75","p0-3|w07|top|100","p0-4|w06|top|195","p0-5|w02|top|150","p0-6|w09|top|90","p0-7|w06|top|195","p0-9|w03|top|75","p0-10|w05|top|60"],"hero":"","bookings":[],"new_bookings":[],"draft_roster":["p0-1|w06|top|195|false","p0-2|w03|top|75|false","p0-3|w07|top|100|false","p0-4|w06|top|195|false","p0-5|w02|top|150|false","p0-6|w09|top|90|false","p0-7|w06|top|195|false","p0-9|w03|top|75|false","p0-10|w05|top|60|false"],"draft_hero":"","boss_lane":"","undo":0},{"gold":227,"draft_gold":227,"ready":true,"earned":1347,"spent":1340,"next_seq":12,"roster":["p1-1|g03|mid|70","p1-2|g06|mid|205","p1-3|g02|mid|135","p1-4|g09|mid|85","p1-5|g03|mid|70","p1-6|g07|top|95","p1-7|g05|top|65","p1-8|g02|mid|135","p1-10|g03|mid|70"],"hero":"h1-11|held_quellgeflecht|181|mid|||260|false|","bookings":[],"new_bookings":[],"draft_roster":["p1-1|g03|mid|70|false","p1-2|g06|mid|205|false","p1-3|g02|mid|135|false","p1-4|g09|mid|85|false","p1-5|g03|mid|70|false","p1-6|g07|top|95|false","p1-7|g05|top|65|false","p1-8|g02|mid|135|false","p1-10|g03|mid|70|false"],"draft_hero":"h1-11|held_quellgeflecht|181|mid|||260|false|","boss_lane":"","undo":0},{"gold":202,"draft_gold":202,"ready":true,"earned":1287,"spent":1305,"next_seq":11,"roster":["p2-1|w04|bot|230","p2-2|w02|bot|150","p2-3|w06|bot|195","p2-4|w03|bot|75","p2-5|w07|bot|100","p2-6|w09|bot|90","p2-7|w02|bot|150","p2-9|w03|mid|75","p2-10|w05|bot|60"],"hero":"","bookings":[],"new_bookings":[],"draft_roster":["p2-1|w04|bot|230|false","p2-2|w02|bot|150|false","p2-3|w06|bot|195|false","p2-4|w03|bot|75|false","p2-5|w07|bot|100|false","p2-6|w09|bot|90|false","p2-7|w02|bot|150|false","p2-9|w03|mid|75|false","p2-10|w05|bot|60|false"],"draft_hero":"","boss_lane":"","undo":0},{"gold":326,"draft_gold":326,"ready":true,"earned":1436,"spent":1330,"next_seq":11,"roster":["p3-1|g03|top|70","p3-2|g02|top|135","p3-3|g06|top|205","p3-4|g07|top|95","p3-5|g03|top|70","p3-6|g09|top|85","p3-7|g02|top|135","p3-8|g06|top|205","p3-9|g03|top|70"],"hero":"h3-10|held_ringborke|145|top|||260|false|","bookings":[],"new_bookings":[],"draft_roster":["p3-1|g03|top|70|false","p3-2|g02|top|135|false","p3-3|g06|top|205|false","p3-4|g07|top|95|false","p3-5|g03|top|70|false","p3-6|g09|top|85|false","p3-7|g02|top|135|false","p3-8|g06|top|205|false","p3-9|g03|top|70|false"],"draft_hero":"h3-10|held_ringborke|145|top|||260|false|","boss_lane":"","undo":0},{"gold":291,"draft_gold":291,"ready":true,"earned":1436,"spent":1365,"next_seq":11,"roster":["p4-1|w03|mid|75","p4-2|w06|mid|195","p4-3|w02|mid|150","p4-4|w03|mid|75","p4-5|w07|mid|100","p4-6|w09|mid|90","p4-7|w06|mid|195","p4-10|w03|mid|75"],"hero":"h4-9|held_ringborke|298|mid|||260|false|","bookings":[],"new_bookings":[],"draft_roster":["p4-1|w03|mid|75|false","p4-2|w06|mid|195|false","p4-3|w02|mid|150|false","p4-4|w03|mid|75|false","p4-5|w07|mid|100|false","p4-6|w09|mid|90|false","p4-7|w06|mid|195|false","p4-10|w03|mid|75|false"],"draft_hero":"h4-9|held_ringborke|298|mid|||260|false|","boss_lane":"","undo":0},{"gold":306,"draft_gold":306,"ready":true,"earned":1436,"spent":1350,"next_seq":10,"roster":["p5-1|g02|bot|135","p5-2|g06|bot|205","p5-3|g03|bot|70","p5-4|g07|bot|95","p5-5|g02|bot|135","p5-6|g05|bot|65","p5-7|g02|bot|135","p5-8|g03|bot|70"],"hero":"h5-9|held_funkenlanze|975|bot|glutklinge|splitterschuss|260|false|","bookings":[],"new_bookings":[],"draft_roster":["p5-1|g02|bot|135|false","p5-2|g06|bot|205|false","p5-3|g03|bot|70|false","p5-4|g07|bot|95|false","p5-5|g02|bot|135|false","p5-6|g05|bot|65|false","p5-7|g02|bot|135|false","p5-8|g03|bot|70|false"],"draft_hero":"h5-9|held_funkenlanze|975|bot|glutklinge|splitterschuss|260|false|","boss_lane":"","undo":0}],"buildings":[7500.0,3523.861200000001,0.0,0.0,2608.2853399999967,0.0,8716.3328,6691.832000000001,12000.0,0.0,0.0,7500.0,5878.8,7500.0,3623.788,6543.4000000000005,9000.0,12000.0],"boss":{"next":1,"settled":9,"claim":""},"boss_log":[],"announcements":[],"settlement":{"round":9,"gains":[66,66,66,186,186,186],"income":102,"lost":["blau_bot_outer","blau_mid_inner"],"end_reason":"cleared","combat_time":78.64999999999768,"boss":"none","lane_kills":{"mid":10,"bot":10,"top":10},"xp":{"h4-9":298,"h1-11":181,"h5-9":439,"h3-10":145}},"combat":{"round":9,"steps":1573,"elapsed":78.64999999999768,"finished":true,"end_reason":"cleared","destroyed":[],"grotto":"none|-1|-1|true","grotto_boss":"","grotto_boss_hp":0.0,"events":88,"mobile":[0,0,0]}},{"label":"round-10","phase":0,"round":11,"winner":-2,"end_note":"","players":[{"gold":255,"draft_gold":255,"ready":true,"earned":1470,"spent":1435,"next_seq":12,"roster":["p0-1|w06|top|195","p0-2|w03|top|75","p0-3|w07|top|100","p0-4|w06|top|195","p0-5|w02|top|150","p0-6|w09|top|90","p0-7|w06|top|195","p0-9|w03|top|75","p0-10|w05|top|60"],"hero":"","bookings":["c0-11|ch_druck|top|150|11"],"new_bookings":[],"draft_roster":["p0-1|w06|top|195|false","p0-2|w03|top|75|false","p0-3|w07|top|100|false","p0-4|w06|top|195|false","p0-5|w02|top|150|false","p0-6|w09|top|90|false","p0-7|w06|top|195|false","p0-9|w03|top|75|false","p0-10|w05|top|60|false"],"draft_hero":"","boss_lane":"","undo":0},{"gold":194,"draft_gold":194,"ready":true,"earned":1529,"spent":1555,"next_seq":14,"roster":["p1-1|g03|mid|70","p1-2|g06|mid|205","p1-3|g02|mid|135","p1-4|g09|mid|85","p1-5|g03|mid|70","p1-6|g07|top|95","p1-7|g05|top|65","p1-8|g02|mid|135","p1-10|g03|mid|70","p1-13|g05|mid|65"],"hero":"h1-11|held_quellgeflecht|407|mid|||260|false|","bookings":["c1-12|ch_schutz|mid|150|11"],"new_bookings":[],"draft_roster":["p1-1|g03|mid|70|false","p1-2|g06|mid|205|false","p1-3|g02|mid|135|false","p1-4|g09|mid|85|false","p1-5|g03|mid|70|false","p1-6|g07|top|95|false","p1-7|g05|top|65|false","p1-8|g02|mid|135|false","p1-10|g03|mid|70|false","p1-13|g05|mid|65|false"],"draft_hero":"h1-11|held_quellgeflecht|407|mid|||260|false|","boss_lane":"","undo":0},{"gold":249,"draft_gold":249,"ready":true,"earned":1469,"spent":1440,"next_seq":11,"roster":["p2-1|w04|bot|230","p2-2|w02|bot|150","p2-3|w06|bot|195","p2-4|w03|bot|75","p2-5|w07|bot|100","p2-6|w09|bot|90","p2-7|w02|bot|150","p2-9|w03|mid|75","p2-10|w06|bot|195"],"hero":"","bookings":[],"new_bookings":[],"draft_roster":["p2-1|w04|bot|230|false","p2-2|w02|bot|150|false","p2-3|w06|bot|195|false","p2-4|w03|bot|75|false","p2-5|w07|bot|100|false","p2-6|w09|bot|90|false","p2-7|w02|bot|150|false","p2-9|w03|mid|75|false","p2-10|w06|bot|195|false"],"draft_hero":"","boss_lane":"","undo":0},{"gold":313,"draft_gold":313,"ready":true,"earned":1738,"spent":1645,"next_seq":12,"roster":["p3-1|g03|top|70","p3-2|g02|top|135","p3-3|g06|top|205","p3-4|g07|top|95","p3-5|g03|top|70","p3-6|g09|top|85","p3-7|g02|top|135","p3-8|g06|top|205","p3-9|g03|top|70","p3-11|g02|top|135"],"hero":"h3-10|held_ringborke|467|top|basaltschild||260|false|","bookings":[],"new_bookings":[],"draft_roster":["p3-1|g03|top|70|false","p3-2|g02|top|135|false","p3-3|g06|top|205|false","p3-4|g07|top|95|false","p3-5|g03|top|70|false","p3-6|g09|top|85|false","p3-7|g02|top|135|false","p3-8|g06|top|205|false","p3-9|g03|top|70|false","p3-11|g02|top|135|false"],"draft_hero":"h3-10|held_ringborke|467|top|basaltschild||260|false|","boss_lane":"","undo":0},{"gold":363,"draft_gold":363,"ready":true,"earned":1738,"spent":1595,"next_seq":12,"roster":["p4-1|w03|mid|75","p4-2|w06|mid|195","p4-3|w02|mid|150","p4-4|w03|mid|75","p4-5|w07|mid|100","p4-6|w09|mid|90","p4-7|w06|mid|195","p4-10|w03|mid|75","p4-11|w01|mid|50"],"hero":"h4-9|held_ringborke|680|mid|basaltschild|schutzwurzeln|260|false|","bookings":[],"new_bookings":[],"draft_roster":["p4-1|w03|mid|75|false","p4-2|w06|mid|195|false","p4-3|w02|mid|150|false","p4-4|w03|mid|75|false","p4-5|w07|mid|100|false","p4-6|w09|mid|90|false","p4-7|w06|mid|195|false","p4-10|w03|mid|75|false","p4-11|w01|mid|50|false"],"draft_hero":"h4-9|held_ringborke|680|mid|basaltschild|schutzwurzeln|260|false|","boss_lane":"","undo":0},{"gold":343,"draft_gold":343,"ready":true,"earned":1738,"spent":1615,"next_seq":12,"roster":["p5-1|g02|bot|135","p5-2|g06|bot|205","p5-3|g03|bot|70","p5-4|g07|bot|95","p5-5|g02|bot|135","p5-6|g05|bot|65","p5-7|g02|bot|135","p5-8|g03|bot|70","p5-11|g09|bot|85"],"hero":"h5-9|held_funkenlanze|1387|bot|glutklinge|splitterschuss|260|false|","bookings":["c5-10|ch_belagerung|bot|180|11"],"new_bookings":[],"draft_roster":["p5-1|g02|bot|135|false","p5-2|g06|bot|205|false","p5-3|g03|bot|70|false","p5-4|g07|bot|95|false","p5-5|g02|bot|135|false","p5-6|g05|bot|65|false","p5-7|g02|bot|135|false","p5-8|g03|bot|70|false","p5-11|g09|bot|85|false"],"draft_hero":"h5-9|held_funkenlanze|1387|bot|glutklinge|splitterschuss|260|false|","boss_lane":"","undo":0}],"buildings":[5493.125,0.0,0.0,0.0,0.0,0.0,7176.275400000004,2151.376600000007,12000.0,0.0,0.0,7500.0,5878.8,7500.0,3623.788,6543.4000000000005,9000.0,12000.0],"boss":{"next":1,"settled":10,"claim":""},"boss_log":[],"announcements":["champion|0|0|top|ch_druck|0","champion|0|1|mid|ch_schutz|0","champion|1|5|bot|ch_belagerung|0"],"settlement":{"round":10,"gains":[76,76,76,196,196,196],"income":106,"lost":["blau_top_outer","blau_bot_inner"],"end_reason":"cleared","combat_time":83.14999999999742,"boss":"none","lane_kills":{"mid":12,"bot":12,"top":12},"xp":{"h1-11":226,"h4-9":382,"h3-10":322,"h5-9":412}},"combat":{"round":10,"steps":1663,"elapsed":83.14999999999742,"finished":true,"end_reason":"cleared","destroyed":[],"grotto":"none|-1|-1|true","grotto_boss":"","grotto_boss_hp":0.0,"events":98,"mobile":[0,0,0]}},{"label":"round-11","phase":2,"round":11,"winner":1,"end_note":"Ancient von Blau zerstört.","players":[{"gold":240,"draft_gold":45,"ready":true,"earned":1665,"spent":1645,"next_seq":13,"roster":["p0-1|w06|top|195","p0-2|w03|top|75","p0-3|w07|top|100","p0-4|w06|top|195","p0-5|w02|top|150","p0-6|w09|top|90","p0-7|w06|top|195","p0-9|w03|top|75","p0-10|w06|top|195","p0-12|w03|top|75"],"hero":"","bookings":[],"new_bookings":[],"draft_roster":["p0-1|w06|top|195|false","p0-2|w03|top|75|false","p0-3|w07|top|100|false","p0-4|w06|top|195|false","p0-5|w02|top|150|false","p0-6|w09|top|90|false","p0-7|w06|top|195|false","p0-9|w03|top|75|false","p0-10|w06|top|195|false","p0-12|w03|top|75|true"],"draft_hero":"","boss_lane":"","undo":0},{"gold":227,"draft_gold":54,"ready":true,"earned":1702,"spent":1695,"next_seq":14,"roster":["p1-1|g03|mid|70","p1-2|g06|mid|205","p1-3|g02|mid|135","p1-4|g09|mid|85","p1-5|g03|mid|70","p1-6|g07|top|95","p1-7|g06|top|205","p1-8|g02|mid|135","p1-10|g03|mid|70","p1-13|g05|mid|65"],"hero":"h1-11|held_quellgeflecht|657|mid||weite_quelle|260|false|","bookings":[],"new_bookings":[],"draft_roster":["p1-1|g03|mid|70|false","p1-2|g06|mid|205|false","p1-3|g02|mid|135|false","p1-4|g09|mid|85|false","p1-5|g03|mid|70|false","p1-6|g07|top|95|false","p1-7|g06|top|205|false","p1-8|g02|mid|135|false","p1-10|g03|mid|70|false","p1-13|g05|mid|65|false"],"draft_hero":"h1-11|held_quellgeflecht|407|mid||weite_quelle|260|false|","boss_lane":"","undo":0},{"gold":311,"draft_gold":69,"ready":true,"earned":1711,"spent":1620,"next_seq":12,"roster":["p2-1|w04|bot|230","p2-2|w02|bot|150","p2-3|w06|bot|195","p2-4|w03|bot|75","p2-5|w07|bot|100","p2-6|w09|bot|90","p2-7|w02|bot|150","p2-9|w03|mid|75","p2-10|w06|bot|195"],"hero":"","bookings":["c2-11|ch_belagerung|bot|180|12"],"new_bookings":["c2-11|ch_belagerung|bot|180"],"draft_roster":["p2-1|w04|bot|230|false","p2-2|w02|bot|150|false","p2-3|w06|bot|195|false","p2-4|w03|bot|75|false","p2-5|w07|bot|100|false","p2-6|w09|bot|90|false","p2-7|w02|bot|150|false","p2-9|w03|mid|75|false","p2-10|w06|bot|195|false"],"draft_hero":"","boss_lane":"","undo":0},{"gold":460,"draft_gold":68,"ready":true,"earned":2130,"spent":1890,"next_seq":13,"roster":["p3-1|g03|top|70","p3-2|g02|top|135","p3-3|g06|top|205","p3-4|g07|top|95","p3-5|g03|top|70","p3-6|g09|top|85","p3-7|g02|top|135","p3-8|g06|top|205","p3-9|g03|top|70","p3-11|g02|top|135","p3-12|g05|top|65"],"hero":"h3-10|held_ringborke|679|top|basaltschild+glutklinge|borkenhaut|260|false|","bookings":[],"new_bookings":[],"draft_roster":["p3-1|g03|top|70|false","p3-2|g02|top|135|false","p3-3|g06|top|205|false","p3-4|g07|top|95|false","p3-5|g03|top|70|false","p3-6|g09|top|85|false","p3-7|g02|top|135|false","p3-8|g06|top|205|false","p3-9|g03|top|70|false","p3-11|g02|top|135|false","p3-12|g05|top|65|true"],"draft_hero":"h3-10|held_ringborke|467|top|basaltschild+glutklinge|borkenhaut|260|false|glutklinge","boss_lane":"","undo":0},{"gold":454,"draft_gold":63,"ready":true,"earned":2129,"spent":1895,"next_seq":12,"roster":["p4-1|w03|mid|75","p4-2|w06|mid|195","p4-3|w02|mid|150","p4-4|w03|mid|75","p4-5|w07|mid|100","p4-6|w09|mid|90","p4-7|w06|mid|195","p4-10|w03|mid|75","p4-11|w02|mid|150"],"hero":"h4-9|held_ringborke|1096|mid|basaltschild+rankenmantel|schutzwurzeln|260|false|","bookings":[],"new_bookings":[],"draft_roster":["p4-1|w03|mid|75|false","p4-2|w06|mid|195|false","p4-3|w02|mid|150|false","p4-4|w03|mid|75|false","p4-5|w07|mid|100|false","p4-6|w09|mid|90|false","p4-7|w06|mid|195|false","p4-10|w03|mid|75|false","p4-11|w02|mid|150|false"],"draft_hero":"h4-9|held_ringborke|680|mid|basaltschild+rankenmantel|schutzwurzeln|260|false|rankenmantel","boss_lane":"","undo":0},{"gold":326,"draft_gold":3,"ready":true,"earned":2061,"spent":1955,"next_seq":12,"roster":["p5-1|g02|bot|135","p5-2|g06|bot|205","p5-3|g03|bot|70","p5-4|g07|bot|95","p5-5|g02|bot|135","p5-6|g06|bot|205","p5-7|g02|bot|135","p5-8|g03|bot|70","p5-11|g09|bot|85"],"hero":"h5-9|held_funkenlanze|1931|bot|glutklinge+funkenfokus|splitterschuss+glutsalve|260|false|","bookings":[],"new_bookings":[],"draft_roster":["p5-1|g02|bot|135|false","p5-2|g06|bot|205|false","p5-3|g03|bot|70|false","p5-4|g07|bot|95|false","p5-5|g02|bot|135|false","p5-6|g06|bot|205|false","p5-7|g02|bot|135|false","p5-8|g03|bot|70|false","p5-11|g09|bot|85|false"],"draft_hero":"h5-9|held_funkenlanze|1387|bot|glutklinge+funkenfokus|splitterschuss+glutsalve|260|false|funkenfokus","boss_lane":"","undo":0}],"buildings":[5493.125,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,7500.0,5878.8,7500.0,3623.788,0.0,8360.725000000002,12000.0],"boss":{"next":1,"settled":11,"claim":""},"boss_log":[],"announcements":[],"settlement":{"round":11,"gains":[195,173,242,392,391,323],"income":110,"lost":["blau_base_2","blau_base_1","rot_base_1","blau_ancient"],"end_reason":"core","combat_time":85.59999999999728,"boss":"none","lane_kills":{"mid":10,"bot":10,"top":13},"xp":{"h1-11":250,"h4-9":416,"h5-9":544,"h3-10":212}},"combat":{"round":11,"steps":1712,"elapsed":85.59999999999728,"finished":true,"end_reason":"core","destroyed":[0],"grotto":"none|-1|-1|true","grotto_boss":"","grotto_boss_hp":0.0,"events":88,"mobile":[2,15,0]}}],"results":[]},"bot_match_11":{"title":"Vollständige Bot-Partie Seed 11 bis zum Ancient-Fall","snapshots":[{"label":"round-1","phase":0,"round":2,"winner":-2,"end_note":"","players":[{"gold":123,"draft_gold":123,"ready":true,"earned":88,"spent":185,"next_seq":4,"roster":["p0-1|w03|top|75","p0-2|w01|top|50","p0-3|w05|top|60"],"hero":"","bookings":[],"new_bookings":[],"draft_roster":["p0-1|w03|top|75|false","p0-2|w01|top|50|false","p0-3|w05|top|60|false"],"draft_hero":"","boss_lane":"","undo":0},{"gold":128,"draft_gold":128,"ready":true,"earned":88,"spent":180,"next_seq":4,"roster":["p1-1|g03|mid|70","p1-2|g01|mid|45","p1-3|g05|mid|65"],"hero":"","bookings":[],"new_bookings":[],"draft_roster":["p1-1|g03|mid|70|false","p1-2|g01|mid|45|false","p1-3|g05|mid|65|false"],"draft_hero":"","boss_lane":"","undo":0},{"gold":123,"draft_gold":123,"ready":true,"earned":88,"spent":185,"next_seq":4,"roster":["p2-1|w03|bot|75","p2-2|w05|bot|60","p2-3|w01|bot|50"],"hero":"","bookings":[],"new_bookings":[],"draft_roster":["p2-1|w03|bot|75|false","p2-2|w05|bot|60|false","p2-3|w01|bot|50|false"],"draft_hero":"","boss_lane":"","undo":0},{"gold":128,"draft_gold":128,"ready":true,"earned":88,"spent":180,"next_seq":4,"roster":["p3-1|g01|top|45","p3-2|g05|top|65","p3-3|g03|top|70"],"hero":"","bookings":[],"new_bookings":[],"draft_roster":["p3-1|g01|top|45|false","p3-2|g05|top|65|false","p3-3|g03|top|70|false"],"draft_hero":"","boss_lane":"","undo":0},{"gold":173,"draft_gold":173,"ready":true,"earned":88,"spent":135,"next_seq":3,"roster":["p4-1|w05|mid|60","p4-2|w03|mid|75"],"hero":"","bookings":[],"new_bookings":[],"draft_roster":["p4-1|w05|mid|60|false","p4-2|w03|mid|75|false"],"draft_hero":"","boss_lane":"","undo":0},{"gold":128,"draft_gold":128,"ready":true,"earned":88,"spent":180,"next_seq":4,"roster":["p5-1|g03|bot|70","p5-2|g05|bot|65","p5-3|g01|bot|45"],"hero":"","bookings":[],"new_bookings":[],"draft_roster":["p5-1|g03|bot|70|false","p5-2|g05|bot|65|false","p5-3|g01|bot|45|false"],"draft_hero":"","boss_lane":"","undo":0}],"buildings":[7500.0,6000.0,7500.0,6000.0,7500.0,6000.0,9000.0,9000.0,12000.0,7500.0,5970.1,7500.0,5968.8,7500.0,5940.200000000001,9000.0,9000.0,12000.0],"boss":{"next":1,"settled":1,"claim":""},"boss_log":[],"announcements":[],"settlement":{"round":1,"gains":[18,18,18,18,18,18],"income":70,"lost":[],"end_reason":"cleared","combat_time":44.89999999999959,"boss":"none","lane_kills":{"mid":6,"bot":6,"top":6},"xp":{}},"combat":{"round":1,"steps":898,"elapsed":44.89999999999959,"finished":true,"end_reason":"cleared","destroyed":[],"grotto":"none|-1|-1|true","grotto_boss":"","grotto_boss_hp":0.0,"events":35,"mobile":[0,0,0]}},{"label":"round-2","phase":0,"round":3,"winner":-2,"end_note":"","players":[{"gold":140,"draft_gold":140,"ready":true,"earned":180,"spent":260,"next_seq":5,"roster":["p0-1|w03|top|75","p0-2|w01|top|50","p0-3|w05|top|60","p0-4|w03|top|75"],"hero":"","bookings":[],"new_bookings":[],"draft_roster":["p0-1|w03|top|75|false","p0-2|w01|top|50|false","p0-3|w05|top|60|false","p0-4|w03|top|75|false"],"draft_hero":"","boss_lane":"","undo":0},{"gold":125,"draft_gold":125,"ready":true,"earned":180,"spent":275,"next_seq":5,"roster":["p1-1|g03|mid|70","p1-2|g01|mid|45","p1-3|g05|mid|65","p1-4|g07|mid|95"],"hero":"","bookings":[],"new_bookings":[],"draft_roster":["p1-1|g03|mid|70|false","p1-2|g01|mid|45|false","p1-3|g05|mid|65|false","p1-4|g07|mid|95|false"],"draft_hero":"","boss_lane":"","undo":0},{"gold":140,"draft_gold":140,"ready":true,"earned":180,"spent":260,"next_seq":5,"roster":["p2-1|w03|bot|75","p2-2|w05|bot|60","p2-3|w01|bot|50","p2-4|w03|bot|75"],"hero":"","bookings":[],"new_bookings":[],"draft_roster":["p2-1|w03|bot|75|false","p2-2|w05|bot|60|false","p2-3|w01|bot|50|false","p2-4|w03|bot|75|false"],"draft_hero":"","boss_lane":"","undo":0},{"gold":125,"draft_gold":125,"ready":true,"earned":180,"spent":275,"next_seq":5,"roster":["p3-1|g01|top|45","p3-2|g05|top|65","p3-3|g03|top|70","p3-4|g07|top|95"],"hero":"","bookings":[],"new_bookings":[],"draft_roster":["p3-1|g01|top|45|false","p3-2|g05|top|65|false","p3-3|g03|top|70|false","p3-4|g07|top|95|false"],"draft_hero":"","boss_lane":"","undo":0},{"gold":105,"draft_gold":105,"ready":true,"earned":180,"spent":295,"next_seq":5,"roster":["p4-1|w05|mid|60","p4-2|w03|mid|75","p4-3|w07|mid|100","p4-4|w05|mid|60"],"hero":"","bookings":[],"new_bookings":[],"draft_roster":["p4-1|w05|mid|60|false","p4-2|w03|mid|75|false","p4-3|w07|mid|100|false","p4-4|w05|mid|60|false"],"draft_hero":"","boss_lane":"","undo":0},{"gold":135,"draft_gold":135,"ready":true,"earned":180,"spent":265,"next_seq":5,"roster":["p5-1|g03|bot|70","p5-2|g05|bot|65","p5-3|g01|bot|45","p5-4|g09|bot|85"],"hero":"","bookings":[],"new_bookings":[],"draft_roster":["p5-1|g03|bot|70|false","p5-2|g05|bot|65|false","p5-3|g01|bot|45|false","p5-4|g09|bot|85|false"],"draft_hero":"","boss_lane":"","undo":0}],"buildings":[7500.0,6000.0,7500.0,5730.900000000003,7500.0,6000.0,9000.0,9000.0,12000.0,7500.0,5970.1,7500.0,5968.8,7500.0,5910.300000000001,9000.0,9000.0,12000.0],"boss":{"next":1,"settled":2,"claim":""},"boss_log":[],"announcements":[],"settlement":{"round":2,"gains":[18,18,18,18,18,18],"income":74,"lost":[],"end_reason":"cleared","combat_time":57.09999999999889,"boss":"none","lane_kills":{"mid":6,"bot":6,"top":6},"xp":{}},"combat":{"round":2,"steps":1142,"elapsed":57.09999999999889,"finished":true,"end_reason":"cleared","destroyed":[],"grotto":"none|-1|-1|true","grotto_boss":"","grotto_boss_hp":0.0,"events":42,"mobile":[0,0,0]}},{"label":"round-3","phase":0,"round":4,"winner":-2,"end_note":"","players":[{"gold":150,"draft_gold":150,"ready":true,"earned":290,"spent":360,"next_seq":6,"roster":["p0-1|w03|top|75","p0-2|w01|top|50","p0-3|w05|top|60","p0-4|w03|top|75","p0-5|w07|top|100"],"hero":"","bookings":[],"new_bookings":[],"draft_roster":["p0-1|w03|top|75|false","p0-2|w01|top|50|false","p0-3|w05|top|60|false","p0-4|w03|top|75|false","p0-5|w07|top|100|false"],"draft_hero":"","boss_lane":"","undo":0},{"gold":165,"draft_gold":165,"ready":true,"earned":290,"spent":345,"next_seq":6,"roster":["p1-1|g03|mid|70","p1-2|g01|mid|45","p1-3|g05|mid|65","p1-4|g07|mid|95","p1-5|g03|mid|70"],"hero":"","bookings":[],"new_bookings":[],"draft_roster":["p1-1|g03|mid|70|false","p1-2|g01|mid|45|false","p1-3|g05|mid|65|false","p1-4|g07|mid|95|false","p1-5|g03|mid|70|false"],"draft_hero":"","boss_lane":"","undo":0},{"gold":150,"draft_gold":150,"ready":true,"earned":290,"spent":360,"next_seq":6,"roster":["p2-1|w03|bot|75","p2-2|w05|bot|60","p2-3|w01|bot|50","p2-4|w03|bot|75","p2-5|w07|bot|100"],"hero":"","bookings":[],"new_bookings":[],"draft_roster":["p2-1|w03|bot|75|false","p2-2|w05|bot|60|false","p2-3|w01|bot|50|false","p2-4|w03|bot|75|false","p2-5|w07|bot|100|false"],"draft_hero":"","boss_lane":"","undo":0},{"gold":125,"draft_gold":125,"ready":true,"earned":290,"spent":385,"next_seq":7,"roster":["p3-1|g01|top|45","p3-2|g05|top|65","p3-3|g03|top|70","p3-4|g07|top|95","p3-5|g01|top|45","p3-6|g05|top|65"],"hero":"","bookings":[],"new_bookings":[],"draft_roster":["p3-1|g01|top|45|false","p3-2|g05|top|65|false","p3-3|g03|top|70|false","p3-4|g07|top|95|false","p3-5|g01|top|45|false","p3-6|g05|top|65|false"],"draft_hero":"","boss_lane":"","undo":0},{"gold":165,"draft_gold":165,"ready":true,"earned":290,"spent":345,"next_seq":6,"roster":["p4-1|w05|mid|60","p4-2|w03|mid|75","p4-3|w07|mid|100","p4-4|w05|mid|60","p4-5|w01|mid|50"],"hero":"","bookings":[],"new_bookings":[],"draft_roster":["p4-1|w05|mid|60|false","p4-2|w03|mid|75|false","p4-3|w07|mid|100|false","p4-4|w05|mid|60|false","p4-5|w01|mid|50|false"],"draft_hero":"","boss_lane":"","undo":0},{"gold":175,"draft_gold":175,"ready":true,"earned":290,"spent":335,"next_seq":6,"roster":["p5-1|g03|bot|70","p5-2|g05|bot|65","p5-3|g01|bot|45","p5-4|g09|bot|85","p5-5|g03|top|70"],"hero":"","bookings":[],"new_bookings":[],"draft_roster":["p5-1|g03|bot|70|false","p5-2|g05|bot|65|false","p5-3|g01|bot|45|false","p5-4|g09|bot|85|false","p5-5|g03|top|70|false"],"draft_hero":"","boss_lane":"","undo":0}],"buildings":[7500.0,5078.983600000002,7500.0,5551.5000000000055,7500.0,6000.0,9000.0,9000.0,12000.0,7500.0,5970.1,7500.0,5968.8,7500.0,4879.193400000009,9000.0,9000.0,12000.0],"boss":{"next":1,"settled":3,"claim":""},"boss_log":[],"announcements":[],"settlement":{"round":3,"gains":[32,32,32,32,32,32],"income":78,"lost":[],"end_reason":"cleared","combat_time":54.09999999999906,"boss":"none","lane_kills":{"mid":6,"top":6,"bot":6},"xp":{}},"combat":{"round":3,"steps":1082,"elapsed":54.09999999999906,"finished":true,"end_reason":"cleared","destroyed":[],"grotto":"none|-1|-1|true","grotto_boss":"","grotto_boss_hp":0.0,"events":49,"mobile":[0,0,0]}},{"label":"round-4","phase":0,"round":5,"winner":-2,"end_note":"","players":[{"gold":132,"draft_gold":132,"ready":true,"earned":412,"spent":500,"next_seq":8,"roster":["p0-1|w03|top|75","p0-2|w01|top|50","p0-3|w05|top|60","p0-4|w03|top|75","p0-5|w07|top|100","p0-6|w09|top|90","p0-7|w01|top|50"],"hero":"","bookings":[],"new_bookings":[],"draft_roster":["p0-1|w03|top|75|false","p0-2|w01|top|50|false","p0-3|w05|top|60|false","p0-4|w03|top|75|false","p0-5|w07|top|100|false","p0-6|w09|top|90|false","p0-7|w01|top|50|false"],"draft_hero":"","boss_lane":"","undo":0},{"gold":157,"draft_gold":157,"ready":true,"earned":412,"spent":475,"next_seq":8,"roster":["p1-1|g03|mid|70","p1-2|g01|mid|45","p1-3|g05|mid|65","p1-4|g07|mid|95","p1-5|g03|mid|70","p1-6|g09|mid|85","p1-7|g01|mid|45"],"hero":"","bookings":[],"new_bookings":[],"draft_roster":["p1-1|g03|mid|70|false","p1-2|g01|mid|45|false","p1-3|g05|mid|65|false","p1-4|g07|mid|95|false","p1-5|g03|mid|70|false","p1-6|g09|mid|85|false","p1-7|g01|mid|45|false"],"draft_hero":"","boss_lane":"","undo":0},{"gold":122,"draft_gold":122,"ready":true,"earned":412,"spent":510,"next_seq":8,"roster":["p2-1|w03|bot|75","p2-2|w05|bot|60","p2-3|w01|bot|50","p2-4|w03|bot|75","p2-5|w07|bot|100","p2-6|w09|bot|90","p2-7|w05|bot|60"],"hero":"","bookings":[],"new_bookings":[],"draft_roster":["p2-1|w03|bot|75|false","p2-2|w05|bot|60|false","p2-3|w01|bot|50|false","p2-4|w03|bot|75|false","p2-5|w07|bot|100|false","p2-6|w09|bot|90|false","p2-7|w05|bot|60|false"],"draft_hero":"","boss_lane":"","undo":0},{"gold":132,"draft_gold":132,"ready":true,"earned":412,"spent":500,"next_seq":9,"roster":["p3-1|g01|top|45","p3-2|g05|top|65","p3-3|g03|top|70","p3-4|g07|top|95","p3-5|g01|top|45","p3-6|g05|top|65","p3-7|g01|top|45","p3-8|g03|top|70"],"hero":"","bookings":[],"new_bookings":[],"draft_roster":["p3-1|g01|top|45|false","p3-2|g05|top|65|false","p3-3|g03|top|70|false","p3-4|g07|top|95|false","p3-5|g01|top|45|false","p3-6|g05|top|65|false","p3-7|g01|top|45|false","p3-8|g03|top|70|false"],"draft_hero":"","boss_lane":"","undo":0},{"gold":137,"draft_gold":137,"ready":true,"earned":412,"spent":495,"next_seq":8,"roster":["p4-1|w05|mid|60","p4-2|w03|mid|75","p4-3|w07|mid|100","p4-4|w05|mid|60","p4-5|w01|mid|50","p4-6|w09|mid|90","p4-7|w05|mid|60"],"hero":"","bookings":[],"new_bookings":[],"draft_roster":["p4-1|w05|mid|60|false","p4-2|w03|mid|75|false","p4-3|w07|mid|100|false","p4-4|w05|mid|60|false","p4-5|w01|mid|50|false","p4-6|w09|mid|90|false","p4-7|w05|mid|60|false"],"draft_hero":"","boss_lane":"","undo":0},{"gold":137,"draft_gold":137,"ready":true,"earned":412,"spent":495,"next_seq":8,"roster":["p5-1|g03|bot|70","p5-2|g05|bot|65","p5-3|g01|bot|45","p5-4|g09|bot|85","p5-5|g03|top|70","p5-6|g07|bot|95","p5-7|g05|bot|65"],"hero":"","bookings":[],"new_bookings":[],"draft_roster":["p5-1|g03|bot|70|false","p5-2|g05|bot|65|false","p5-3|g01|bot|45|false","p5-4|g09|bot|85|false","p5-5|g03|top|70|false","p5-6|g07|bot|95|false","p5-7|g05|bot|65|false"],"draft_hero":"","boss_lane":"","undo":0}],"buildings":[7500.0,4003.983600000005,7500.0,4644.400000000016,7500.0,6000.0,9000.0,9000.0,12000.0,7500.0,5970.1,7500.0,5968.8,7500.0,3905.693400000015,9000.0,9000.0,12000.0],"boss":{"next":1,"settled":4,"claim":""},"boss_log":[],"announcements":[],"settlement":{"round":4,"gains":[40,40,40,40,40,40],"income":82,"lost":[],"end_reason":"cleared","combat_time":62.89999999999856,"boss":"none","lane_kills":{"mid":8,"bot":8,"top":8},"xp":{}},"combat":{"round":4,"steps":1258,"elapsed":62.89999999999856,"finished":true,"end_reason":"cleared","destroyed":[],"grotto":"none|-1|-1|true","grotto_boss":"","grotto_boss_hp":0.0,"events":67,"mobile":[0,0,0]}},{"label":"round-5","phase":0,"round":6,"winner":-2,"end_note":"","players":[{"gold":163,"draft_gold":163,"ready":true,"earned":543,"spent":600,"next_seq":8,"roster":["p0-1|w03|top|75","p0-2|w02|top|150","p0-3|w05|top|60","p0-4|w03|top|75","p0-5|w07|top|100","p0-6|w09|top|90","p0-7|w01|top|50"],"hero":"","bookings":[],"new_bookings":[],"draft_roster":["p0-1|w03|top|75|false","p0-2|w02|top|150|false","p0-3|w05|top|60|false","p0-4|w03|top|75|false","p0-5|w07|top|100|false","p0-6|w09|top|90|false","p0-7|w01|top|50|false"],"draft_hero":"","boss_lane":"","undo":0},{"gold":133,"draft_gold":133,"ready":true,"earned":543,"spent":630,"next_seq":9,"roster":["p1-1|g03|mid|70","p1-2|g02|mid|135","p1-3|g05|mid|65","p1-4|g07|mid|95","p1-5|g03|mid|70","p1-6|g09|mid|85","p1-7|g01|mid|45","p1-8|g05|mid|65"],"hero":"","bookings":[],"new_bookings":[],"draft_roster":["p1-1|g03|mid|70|false","p1-2|g02|mid|135|false","p1-3|g05|mid|65|false","p1-4|g07|mid|95|false","p1-5|g03|mid|70|false","p1-6|g09|mid|85|false","p1-7|g01|mid|45|false","p1-8|g05|mid|65|false"],"draft_hero":"","boss_lane":"","undo":0},{"gold":153,"draft_gold":153,"ready":true,"earned":543,"spent":610,"next_seq":8,"roster":["p2-1|w03|bot|75","p2-2|w05|bot|60","p2-3|w02|bot|150","p2-4|w03|bot|75","p2-5|w07|bot|100","p2-6|w09|bot|90","p2-7|w05|bot|60"],"hero":"","bookings":[],"new_bookings":[],"draft_roster":["p2-1|w03|bot|75|false","p2-2|w05|bot|60|false","p2-3|w02|bot|150|false","p2-4|w03|bot|75|false","p2-5|w07|bot|100|false","p2-6|w09|bot|90|false","p2-7|w05|bot|60|false"],"draft_hero":"","boss_lane":"","undo":0},{"gold":173,"draft_gold":173,"ready":true,"earned":543,"spent":590,"next_seq":9,"roster":["p3-1|g02|top|135","p3-2|g05|top|65","p3-3|g03|top|70","p3-4|g07|top|95","p3-5|g01|top|45","p3-6|g05|top|65","p3-7|g01|top|45","p3-8|g03|top|70"],"hero":"","bookings":[],"new_bookings":[],"draft_roster":["p3-1|g02|top|135|false","p3-2|g05|top|65|false","p3-3|g03|top|70|false","p3-4|g07|top|95|false","p3-5|g01|top|45|false","p3-6|g05|top|65|false","p3-7|g01|top|45|false","p3-8|g03|top|70|false"],"draft_hero":"","boss_lane":"","undo":0},{"gold":168,"draft_gold":168,"ready":true,"earned":543,"spent":595,"next_seq":8,"roster":["p4-1|w05|mid|60","p4-2|w03|mid|75","p4-3|w07|mid|100","p4-4|w05|mid|60","p4-5|w02|mid|150","p4-6|w09|mid|90","p4-7|w05|mid|60"],"hero":"","bookings":[],"new_bookings":[],"draft_roster":["p4-1|w05|mid|60|false","p4-2|w03|mid|75|false","p4-3|w07|mid|100|false","p4-4|w05|mid|60|false","p4-5|w02|mid|150|false","p4-6|w09|mid|90|false","p4-7|w05|mid|60|false"],"draft_hero":"","boss_lane":"","undo":0},{"gold":133,"draft_gold":133,"ready":true,"earned":543,"spent":630,"next_seq":9,"roster":["p5-1|g03|bot|70","p5-2|g05|bot|65","p5-3|g02|bot|135","p5-4|g09|bot|85","p5-5|g03|top|70","p5-6|g07|bot|95","p5-7|g05|bot|65","p5-8|g01|bot|45"],"hero":"","bookings":[],"new_bookings":[],"draft_roster":["p5-1|g03|bot|70|false","p5-2|g05|bot|65|false","p5-3|g02|bot|135|false","p5-4|g09|bot|85|false","p5-5|g03|top|70|false","p5-6|g07|bot|95|false","p5-7|g05|bot|65|false","p5-8|g01|bot|45|false"],"draft_hero":"","boss_lane":"","undo":0}],"buildings":[7500.0,2949.738800000006,7500.0,4644.400000000016,7500.0,6000.0,9000.0,9000.0,12000.0,7500.0,5970.1,7500.0,5867.087999999998,7500.0,2885.7726000000134,9000.0,9000.0,12000.0],"boss":{"next":1,"settled":5,"claim":""},"boss_log":[],"announcements":[],"settlement":{"round":5,"gains":[45,45,45,45,45,45],"income":86,"lost":[],"end_reason":"cleared","combat_time":60.69999999999869,"boss":"none","lane_kills":{"mid":8,"bot":8,"top":8},"xp":{}},"combat":{"round":5,"steps":1214,"elapsed":60.69999999999869,"finished":true,"end_reason":"cleared","destroyed":[],"grotto":"none|-1|-1|true","grotto_boss":"","grotto_boss_hp":0.0,"events":69,"mobile":[0,0,0]}},{"label":"round-6","phase":0,"round":7,"winner":-2,"end_note":"","players":[{"gold":193,"draft_gold":193,"ready":true,"earned":673,"spent":700,"next_seq":8,"roster":["p0-1|w03|top|75","p0-2|w02|top|150","p0-3|w05|top|60","p0-4|w03|top|75","p0-5|w07|top|100","p0-6|w09|top|90","p0-7|w02|top|150"],"hero":"","bookings":[],"new_bookings":[],"draft_roster":["p0-1|w03|top|75|false","p0-2|w02|top|150|false","p0-3|w05|top|60|false","p0-4|w03|top|75|false","p0-5|w07|top|100|false","p0-6|w09|top|90|false","p0-7|w02|top|150|false"],"draft_hero":"","boss_lane":"","undo":0},{"gold":173,"draft_gold":173,"ready":true,"earned":673,"spent":720,"next_seq":9,"roster":["p1-1|g03|mid|70","p1-2|g02|mid|135","p1-3|g05|mid|65","p1-4|g07|mid|95","p1-5|g03|mid|70","p1-6|g09|mid|85","p1-7|g02|mid|135","p1-8|g05|mid|65"],"hero":"","bookings":[],"new_bookings":[],"draft_roster":["p1-1|g03|mid|70|false","p1-2|g02|mid|135|false","p1-3|g05|mid|65|false","p1-4|g07|mid|95|false","p1-5|g03|mid|70|false","p1-6|g09|mid|85|false","p1-7|g02|mid|135|false","p1-8|g05|mid|65|false"],"draft_hero":"","boss_lane":"","undo":0},{"gold":148,"draft_gold":148,"ready":true,"earned":673,"spent":745,"next_seq":8,"roster":["p2-1|w03|bot|75","p2-2|w06|bot|195","p2-3|w02|bot|150","p2-4|w03|bot|75","p2-5|w07|bot|100","p2-6|w09|bot|90","p2-7|w05|bot|60"],"hero":"","bookings":[],"new_bookings":[],"draft_roster":["p2-1|w03|bot|75|false","p2-2|w06|bot|195|false","p2-3|w02|bot|150|false","p2-4|w03|bot|75|false","p2-5|w07|bot|100|false","p2-6|w09|bot|90|false","p2-7|w05|bot|60|false"],"draft_hero":"","boss_lane":"","undo":0},{"gold":213,"draft_gold":213,"ready":true,"earned":673,"spent":680,"next_seq":9,"roster":["p3-1|g02|top|135","p3-2|g05|top|65","p3-3|g03|top|70","p3-4|g07|top|95","p3-5|g02|top|135","p3-6|g05|top|65","p3-7|g01|top|45","p3-8|g03|top|70"],"hero":"","bookings":[],"new_bookings":[],"draft_roster":["p3-1|g02|top|135|false","p3-2|g05|top|65|false","p3-3|g03|top|70|false","p3-4|g07|top|95|false","p3-5|g02|top|135|false","p3-6|g05|top|65|false","p3-7|g01|top|45|false","p3-8|g03|top|70|false"],"draft_hero":"","boss_lane":"","undo":0},{"gold":163,"draft_gold":163,"ready":true,"earned":673,"spent":730,"next_seq":8,"roster":["p4-1|w06|mid|195","p4-2|w03|mid|75","p4-3|w07|mid|100","p4-4|w05|mid|60","p4-5|w02|mid|150","p4-6|w09|mid|90","p4-7|w05|mid|60"],"hero":"","bookings":[],"new_bookings":[],"draft_roster":["p4-1|w06|mid|195|false","p4-2|w03|mid|75|false","p4-3|w07|mid|100|false","p4-4|w05|mid|60|false","p4-5|w02|mid|150|false","p4-6|w09|mid|90|false","p4-7|w05|mid|60|false"],"draft_hero":"","boss_lane":"","undo":0},{"gold":173,"draft_gold":173,"ready":true,"earned":673,"spent":720,"next_seq":9,"roster":["p5-1|g03|bot|70","p5-2|g05|bot|65","p5-3|g02|bot|135","p5-4|g09|bot|85","p5-5|g03|top|70","p5-6|g07|bot|95","p5-7|g05|bot|65","p5-8|g02|bot|135"],"hero":"","bookings":[],"new_bookings":[],"draft_roster":["p5-1|g03|bot|70|false","p5-2|g05|bot|65|false","p5-3|g02|bot|135|false","p5-4|g09|bot|85|false","p5-5|g03|top|70|false","p5-6|g07|bot|95|false","p5-7|g05|bot|65|false","p5-8|g02|bot|135|false"],"draft_hero":"","boss_lane":"","undo":0}],"buildings":[7500.0,1732.5088000000076,7500.0,3691.3050000000144,7500.0,6000.0,9000.0,9000.0,12000.0,7500.0,5970.1,7500.0,5867.087999999998,7500.0,635.7826000000118,9000.0,9000.0,12000.0],"boss":{"next":1,"settled":6,"claim":""},"boss_log":[],"announcements":[],"settlement":{"round":6,"gains":[40,40,40,40,40,40],"income":90,"lost":[],"end_reason":"cleared","combat_time":62.09999999999861,"boss":"none","lane_kills":{"mid":8,"bot":8,"top":8},"xp":{}},"combat":{"round":6,"steps":1242,"elapsed":62.09999999999861,"finished":true,"end_reason":"cleared","destroyed":[],"grotto":"none|-1|-1|true","grotto_boss":"","grotto_boss_hp":0.0,"events":69,"mobile":[0,0,0]}},{"label":"round-7","phase":0,"round":8,"winner":-2,"end_note":"","players":[{"gold":260,"draft_gold":260,"ready":true,"earned":875,"spent":835,"next_seq":8,"roster":["p0-1|w03|top|75","p0-2|w02|top|150","p0-3|w06|top|195","p0-4|w03|top|75","p0-5|w07|top|100","p0-6|w09|top|90","p0-7|w02|top|150"],"hero":"","bookings":[],"new_bookings":[],"draft_roster":["p0-1|w03|top|75|false","p0-2|w02|top|150|false","p0-3|w06|top|195|false","p0-4|w03|top|75|false","p0-5|w07|top|100|false","p0-6|w09|top|90|false","p0-7|w02|top|150|false"],"draft_hero":"","boss_lane":"","undo":0},{"gold":235,"draft_gold":235,"ready":true,"earned":875,"spent":860,"next_seq":9,"roster":["p1-1|g03|mid|70","p1-2|g02|mid|135","p1-3|g06|mid|205","p1-4|g07|mid|95","p1-5|g03|mid|70","p1-6|g09|mid|85","p1-7|g02|mid|135","p1-8|g05|mid|65"],"hero":"","bookings":[],"new_bookings":[],"draft_roster":["p1-1|g03|mid|70|false","p1-2|g02|mid|135|false","p1-3|g06|mid|205|false","p1-4|g07|mid|95|false","p1-5|g03|mid|70|false","p1-6|g09|mid|85|false","p1-7|g02|mid|135|false","p1-8|g05|mid|65|false"],"draft_hero":"","boss_lane":"","undo":0},{"gold":215,"draft_gold":215,"ready":true,"earned":875,"spent":880,"next_seq":8,"roster":["p2-1|w03|bot|75","p2-2|w06|bot|195","p2-3|w02|bot|150","p2-4|w03|bot|75","p2-5|w07|bot|100","p2-6|w09|bot|90","p2-7|w06|bot|195"],"hero":"","bookings":[],"new_bookings":[],"draft_roster":["p2-1|w03|bot|75|false","p2-2|w06|bot|195|false","p2-3|w02|bot|150|false","p2-4|w03|bot|75|false","p2-5|w07|bot|100|false","p2-6|w09|bot|90|false","p2-7|w06|bot|195|false"],"draft_hero":"","boss_lane":"","undo":0},{"gold":190,"draft_gold":190,"ready":true,"earned":825,"spent":855,"next_seq":10,"roster":["p3-1|g02|top|135","p3-2|g05|top|65","p3-3|g03|top|70","p3-4|g07|top|95","p3-5|g02|top|135","p3-6|g05|top|65","p3-7|g02|top|135","p3-8|g03|top|70","p3-9|g09|top|85"],"hero":"","bookings":[],"new_bookings":[],"draft_roster":["p3-1|g02|top|135|false","p3-2|g05|top|65|false","p3-3|g03|top|70|false","p3-4|g07|top|95|false","p3-5|g02|top|135|false","p3-6|g05|top|65|false","p3-7|g02|top|135|false","p3-8|g03|top|70|false","p3-9|g09|top|85|false"],"draft_hero":"","boss_lane":"","undo":0},{"gold":180,"draft_gold":180,"ready":true,"earned":825,"spent":865,"next_seq":8,"roster":["p4-1|w06|mid|195","p4-2|w03|mid|75","p4-3|w07|mid|100","p4-4|w06|mid|195","p4-5|w02|mid|150","p4-6|w09|mid|90","p4-7|w05|mid|60"],"hero":"","bookings":[],"new_bookings":[],"draft_roster":["p4-1|w06|mid|195|false","p4-2|w03|mid|75|false","p4-3|w07|mid|100|false","p4-4|w06|mid|195|false","p4-5|w02|mid|150|false","p4-6|w09|mid|90|false","p4-7|w05|mid|60|false"],"draft_hero":"","boss_lane":"","undo":0},{"gold":185,"draft_gold":185,"ready":true,"earned":825,"spent":860,"next_seq":9,"roster":["p5-1|g03|bot|70","p5-2|g06|bot|205","p5-3|g02|bot|135","p5-4|g09|bot|85","p5-5|g03|top|70","p5-6|g07|bot|95","p5-7|g05|bot|65","p5-8|g02|bot|135"],"hero":"","bookings":[],"new_bookings":[],"draft_roster":["p5-1|g03|bot|70|false","p5-2|g06|bot|205|false","p5-3|g02|bot|135|false","p5-4|g09|bot|85|false","p5-5|g03|top|70|false","p5-6|g07|bot|95|false","p5-7|g05|bot|65|false","p5-8|g02|bot|135|false"],"draft_hero":"","boss_lane":"","undo":0}],"buildings":[7500.0,407.00736000000694,7500.0,2660.405000000012,7500.0,6000.0,9000.0,9000.0,12000.0,7500.0,5970.1,7500.0,5867.087999999998,6786.299999999998,0.0,9000.0,9000.0,12000.0],"boss":{"next":1,"settled":7,"claim":""},"boss_log":[],"announcements":[],"settlement":{"round":7,"gains":[108,108,108,58,58,58],"income":94,"lost":["rot_bot_outer"],"end_reason":"cleared","combat_time":66.49999999999837,"boss":"none","lane_kills":{"mid":10,"bot":10,"top":10},"xp":{}},"combat":{"round":7,"steps":1330,"elapsed":66.49999999999837,"finished":true,"end_reason":"cleared","destroyed":[],"grotto":"none|-1|-1|true","grotto_boss":"","grotto_boss_hp":0.0,"events":77,"mobile":[0,0,0]}},{"label":"round-8","phase":0,"round":9,"winner":-2,"end_note":"","players":[{"gold":155,"draft_gold":155,"ready":true,"earned":1030,"spent":1095,"next_seq":9,"roster":["p0-1|w03|top|75","p0-2|w02|top|150","p0-3|w06|top|195","p0-4|w03|top|75","p0-5|w07|top|100","p0-6|w09|top|90","p0-7|w02|top|150"],"hero":"h0-8|held_ringborke|308|top|||260|false|","bookings":[],"new_bookings":[],"draft_roster":["p0-1|w03|top|75|false","p0-2|w02|top|150|false","p0-3|w06|top|195|false","p0-4|w03|top|75|false","p0-5|w07|top|100|false","p0-6|w09|top|90|false","p0-7|w02|top|150|false"],"draft_hero":"h0-8|held_ringborke|308|top|||260|false|","boss_lane":"","undo":0},{"gold":180,"draft_gold":180,"ready":true,"earned":1030,"spent":1070,"next_seq":10,"roster":["p1-1|g03|mid|70","p1-2|g02|mid|135","p1-3|g06|mid|205","p1-4|g07|mid|95","p1-5|g03|mid|70","p1-6|g09|mid|85","p1-7|g02|mid|135","p1-8|g06|mid|205","p1-9|g03|mid|70"],"hero":"","bookings":[],"new_bookings":[],"draft_roster":["p1-1|g03|mid|70|false","p1-2|g02|mid|135|false","p1-3|g06|mid|205|false","p1-4|g07|mid|95|false","p1-5|g03|mid|70|false","p1-6|g09|mid|85|false","p1-7|g02|mid|135|false","p1-8|g06|mid|205|false","p1-9|g03|mid|70|false"],"draft_hero":"","boss_lane":"","undo":0},{"gold":220,"draft_gold":220,"ready":true,"earned":1030,"spent":1030,"next_seq":9,"roster":["p2-1|w03|bot|75","p2-2|w06|bot|195","p2-3|w02|bot|150","p2-4|w03|bot|75","p2-5|w07|bot|100","p2-6|w09|bot|90","p2-7|w06|bot|195"],"hero":"","bookings":["c2-8|ch_schutz|bot|150|9"],"new_bookings":[],"draft_roster":["p2-1|w03|bot|75|false","p2-2|w06|bot|195|false","p2-3|w02|bot|150|false","p2-4|w03|bot|75|false","p2-5|w07|bot|100|false","p2-6|w09|bot|90|false","p2-7|w06|bot|195|false"],"draft_hero":"","boss_lane":"","undo":0},{"gold":280,"draft_gold":280,"ready":true,"earned":1100,"spent":1040,"next_seq":11,"roster":["p3-1|g02|top|135","p3-2|g06|top|205","p3-3|g03|top|70","p3-4|g07|top|95","p3-5|g02|top|135","p3-6|g05|top|65","p3-7|g02|top|135","p3-8|g03|top|70","p3-9|g09|top|85","p3-10|g01|top|45"],"hero":"","bookings":[],"new_bookings":[],"draft_roster":["p3-1|g02|top|135|false","p3-2|g06|top|205|false","p3-3|g03|top|70|false","p3-4|g07|top|95|false","p3-5|g02|top|135|false","p3-6|g05|top|65|false","p3-7|g02|top|135|false","p3-8|g03|top|70|false","p3-9|g09|top|85|false","p3-10|g01|top|45|false"],"draft_hero":"","boss_lane":"","undo":0},{"gold":320,"draft_gold":320,"ready":true,"earned":1100,"spent":1000,"next_seq":8,"roster":["p4-1|w06|mid|195","p4-2|w03|mid|75","p4-3|w07|mid|100","p4-4|w06|mid|195","p4-5|w02|mid|150","p4-6|w09|mid|90","p4-7|w06|mid|195"],"hero":"","bookings":[],"new_bookings":[],"draft_roster":["p4-1|w06|mid|195|false","p4-2|w03|mid|75|false","p4-3|w07|mid|100|false","p4-4|w06|mid|195|false","p4-5|w02|mid|150|false","p4-6|w09|mid|90|false","p4-7|w06|mid|195|false"],"draft_hero":"","boss_lane":"","undo":0},{"gold":320,"draft_gold":320,"ready":true,"earned":1100,"spent":1000,"next_seq":9,"roster":["p5-1|g03|bot|70","p5-2|g06|bot|205","p5-3|g02|bot|135","p5-4|g09|bot|85","p5-5|g03|top|70","p5-6|g07|bot|95","p5-7|g06|bot|205","p5-8|g02|bot|135"],"hero":"","bookings":[],"new_bookings":[],"draft_roster":["p5-1|g03|bot|70|false","p5-2|g06|bot|205|false","p5-3|g02|bot|135|false","p5-4|g09|bot|85|false","p5-5|g03|top|70|false","p5-6|g07|bot|95|false","p5-7|g06|bot|205|false","p5-8|g02|bot|135|false"],"draft_hero":"","boss_lane":"","undo":0}],"buildings":[0.0,0.0,7500.0,2660.405000000012,7500.0,5429.625,4588.102704999993,9000.0,12000.0,7500.0,5970.1,7500.0,5381.212999999998,6786.299999999998,0.0,9000.0,9000.0,12000.0],"boss":{"next":12,"settled":8,"claim":"0|8|9|0|top"},"boss_log":["8|won|0||0"],"announcements":["champion|0|2|bot|ch_schutz|0","boss|0|0|top||1060"],"settlement":{"round":8,"gains":[57,57,57,177,177,177],"income":98,"lost":["blau_top_outer","blau_top_inner"],"end_reason":"cleared","combat_time":89.64999999999705,"boss":"won","lane_kills":{"mid":10,"bot":10,"top":10},"xp":{"h0-8":308}},"combat":{"round":8,"steps":1793,"elapsed":89.64999999999705,"finished":true,"end_reason":"cleared","destroyed":[],"grotto":"success|0|0|true","grotto_boss":"false|false|97","grotto_boss_hp":0.0,"events":79,"mobile":[3,0,0]}},{"label":"round-9","phase":2,"round":9,"winner":0,"end_note":"Ancient von Rot zerstört.","players":[{"gold":316,"draft_gold":0,"ready":true,"earned":1346,"spent":1250,"next_seq":9,"roster":["p0-1|w04|top|230","p0-2|w02|top|150","p0-3|w06|top|195","p0-4|w03|top|75","p0-5|w07|top|100","p0-6|w09|top|90","p0-7|w02|top|150"],"hero":"h0-8|held_ringborke|534|top||schutzwurzeln|260|false|","bookings":[],"new_bookings":[],"draft_roster":["p0-1|w04|top|230|false","p0-2|w02|top|150|false","p0-3|w06|top|195|false","p0-4|w03|top|75|false","p0-5|w07|top|100|false","p0-6|w09|top|90|false","p0-7|w02|top|150|false"],"draft_hero":"h0-8|held_ringborke|308|top||schutzwurzeln|260|false|","boss_lane":"bot","undo":0},{"gold":346,"draft_gold":30,"ready":true,"earned":1346,"spent":1220,"next_seq":10,"roster":["p1-1|g04|mid|220","p1-2|g02|mid|135","p1-3|g06|mid|205","p1-4|g07|mid|95","p1-5|g03|mid|70","p1-6|g09|mid|85","p1-7|g02|mid|135","p1-8|g06|mid|205","p1-9|g03|mid|70"],"hero":"","bookings":[],"new_bookings":[],"draft_roster":["p1-1|g04|mid|220|false","p1-2|g02|mid|135|false","p1-3|g06|mid|205|false","p1-4|g07|mid|95|false","p1-5|g03|mid|70|false","p1-6|g09|mid|85|false","p1-7|g02|mid|135|false","p1-8|g06|mid|205|false","p1-9|g03|mid|70|false"],"draft_hero":"","boss_lane":"","undo":0},{"gold":381,"draft_gold":65,"ready":true,"earned":1346,"spent":1185,"next_seq":9,"roster":["p2-1|w04|bot|230","p2-2|w06|bot|195","p2-3|w02|bot|150","p2-4|w03|bot|75","p2-5|w07|bot|100","p2-6|w09|bot|90","p2-7|w06|bot|195"],"hero":"","bookings":[],"new_bookings":[],"draft_roster":["p2-1|w04|bot|230|false","p2-2|w06|bot|195|false","p2-3|w02|bot|150|false","p2-4|w03|bot|75|false","p2-5|w07|bot|100|false","p2-6|w09|bot|90|false","p2-7|w06|bot|195|false"],"draft_hero":"","boss_lane":"","undo":0},{"gold":102,"draft_gold":20,"ready":true,"earned":1182,"spent":1300,"next_seq":12,"roster":["p3-1|g02|top|135","p3-2|g06|top|205","p3-3|g03|top|70","p3-4|g07|top|95","p3-5|g02|top|135","p3-6|g05|top|65","p3-7|g02|top|135","p3-8|g03|top|70","p3-9|g09|top|85","p3-10|g01|top|45"],"hero":"h3-11|held_funkenlanze|319|top|||260|false|","bookings":[],"new_bookings":[],"draft_roster":["p3-1|g02|top|135|false","p3-2|g06|top|205|false","p3-3|g03|top|70|false","p3-4|g07|top|95|false","p3-5|g02|top|135|false","p3-6|g05|top|65|false","p3-7|g02|top|135|false","p3-8|g03|top|70|false","p3-9|g09|top|85|false","p3-10|g01|top|45|false"],"draft_hero":"h3-11|held_funkenlanze|0|top|||260|true|","boss_lane":"","undo":0},{"gold":142,"draft_gold":60,"ready":true,"earned":1182,"spent":1260,"next_seq":9,"roster":["p4-1|w06|mid|195","p4-2|w03|mid|75","p4-3|w07|mid|100","p4-4|w06|mid|195","p4-5|w02|mid|150","p4-6|w09|mid|90","p4-7|w06|mid|195"],"hero":"h4-8|held_funkenlanze|304|mid|||260|false|","bookings":[],"new_bookings":[],"draft_roster":["p4-1|w06|mid|195|false","p4-2|w03|mid|75|false","p4-3|w07|mid|100|false","p4-4|w06|mid|195|false","p4-5|w02|mid|150|false","p4-6|w09|mid|90|false","p4-7|w06|mid|195|false"],"draft_hero":"h4-8|held_funkenlanze|0|mid|||260|true|","boss_lane":"","undo":0},{"gold":189,"draft_gold":60,"ready":true,"earned":1229,"spent":1260,"next_seq":10,"roster":["p5-1|g03|bot|70","p5-2|g06|bot|205","p5-3|g02|bot|135","p5-4|g09|bot|85","p5-5|g03|top|70","p5-6|g07|bot|95","p5-7|g06|bot|205","p5-8|g02|bot|135"],"hero":"h5-9|held_quellgeflecht|145|bot|||260|false|","bookings":[],"new_bookings":[],"draft_roster":["p5-1|g03|bot|70|false","p5-2|g06|bot|205|false","p5-3|g02|bot|135|false","p5-4|g09|bot|85|false","p5-5|g03|top|70|false","p5-6|g07|bot|95|false","p5-7|g06|bot|205|false","p5-8|g02|bot|135|false"],"draft_hero":"h5-9|held_quellgeflecht|0|bot|||260|true|","boss_lane":"","undo":0}],"buildings":[0.0,0.0,7500.0,2184.605000000011,7500.0,5429.625,3162.6527049999922,9000.0,12000.0,7500.0,5970.1,7500.0,5381.212999999998,0.0,0.0,0.0,0.0,0.0],"boss":{"next":12,"settled":9,"claim":""},"boss_log":["8|won|0||0","9|deployed|0|bot|-1"],"announcements":[],"settlement":{"round":9,"gains":[316,316,316,82,82,129],"income":102,"lost":["rot_bot_inner","rot_base_2","rot_base_1","rot_ancient"],"end_reason":"core","combat_time":136.5499999999968,"boss":"deployed","lane_kills":{"mid":10,"bot":9,"top":10},"xp":{"h4-8":304,"h5-9":145,"h3-11":319,"h0-8":226}},"combat":{"round":9,"steps":2731,"elapsed":136.5499999999968,"finished":true,"end_reason":"core","destroyed":[1],"grotto":"none|-1|-1|true","grotto_boss":"","grotto_boss_hp":0.0,"events":81,"mobile":[7,0,0]}}],"results":[]},"bot_match_28":{"title":"Vollständige Bot-Partie Seed 28 (Bots mit Helden, Champions und Grotte)","snapshots":[{"label":"round-1","phase":0,"round":2,"winner":-2,"end_note":"","players":[{"gold":128,"draft_gold":128,"ready":true,"earned":88,"spent":180,"next_seq":4,"roster":["p0-1|g03|top|70","p0-2|g05|top|65","p0-3|g01|top|45"],"hero":"","bookings":[],"new_bookings":[],"draft_roster":["p0-1|g03|top|70|false","p0-2|g05|top|65|false","p0-3|g01|top|45|false"],"draft_hero":"","boss_lane":"","undo":0},{"gold":123,"draft_gold":123,"ready":true,"earned":88,"spent":185,"next_seq":4,"roster":["p1-1|w03|mid|75","p1-2|w01|mid|50","p1-3|w05|mid|60"],"hero":"","bookings":[],"new_bookings":[],"draft_roster":["p1-1|w03|mid|75|false","p1-2|w01|mid|50|false","p1-3|w05|mid|60|false"],"draft_hero":"","boss_lane":"","undo":0},{"gold":128,"draft_gold":128,"ready":true,"earned":88,"spent":180,"next_seq":4,"roster":["p2-1|g03|bot|70","p2-2|g01|bot|45","p2-3|g05|bot|65"],"hero":"","bookings":[],"new_bookings":[],"draft_roster":["p2-1|g03|bot|70|false","p2-2|g01|bot|45|false","p2-3|g05|bot|65|false"],"draft_hero":"","boss_lane":"","undo":0},{"gold":123,"draft_gold":123,"ready":true,"earned":88,"spent":185,"next_seq":4,"roster":["p3-1|w03|top|75","p3-2|w05|top|60","p3-3|w01|top|50"],"hero":"","bookings":[],"new_bookings":[],"draft_roster":["p3-1|w03|top|75|false","p3-2|w05|top|60|false","p3-3|w01|top|50|false"],"draft_hero":"","boss_lane":"","undo":0},{"gold":128,"draft_gold":128,"ready":true,"earned":88,"spent":180,"next_seq":4,"roster":["p4-1|g01|mid|45","p4-2|g05|mid|65","p4-3|g03|mid|70"],"hero":"","bookings":[],"new_bookings":[],"draft_roster":["p4-1|g01|mid|45|false","p4-2|g05|mid|65|false","p4-3|g03|mid|70|false"],"draft_hero":"","boss_lane":"","undo":0},{"gold":173,"draft_gold":173,"ready":true,"earned":88,"spent":135,"next_seq":3,"roster":["p5-1|w05|bot|60","p5-2|w03|bot|75"],"hero":"","bookings":[],"new_bookings":[],"draft_roster":["p5-1|w05|bot|60|false","p5-2|w03|bot|75|false"],"draft_hero":"","boss_lane":"","undo":0}],"buildings":[7500.0,5970.1,7500.0,6000.0,7500.0,6000.0,9000.0,9000.0,12000.0,7500.0,6000.0,7500.0,6000.0,7500.0,5882.55,9000.0,9000.0,12000.0],"boss":{"next":1,"settled":1,"claim":""},"boss_log":[],"announcements":[],"settlement":{"round":1,"gains":[18,18,18,18,18,18],"income":70,"lost":[],"end_reason":"cleared","combat_time":44.89999999999959,"boss":"none","lane_kills":{"mid":6,"bot":6,"top":6},"xp":{}},"combat":{"round":1,"steps":898,"elapsed":44.89999999999959,"finished":true,"end_reason":"cleared","destroyed":[],"grotto":"none|-1|-1|true","grotto_boss":"","grotto_boss_hp":0.0,"events":35,"mobile":[0,0,0]}},{"label":"round-2","phase":0,"round":3,"winner":-2,"end_note":"","players":[{"gold":135,"draft_gold":135,"ready":true,"earned":180,"spent":265,"next_seq":5,"roster":["p0-1|g03|top|70","p0-2|g05|top|65","p0-3|g01|top|45","p0-4|g09|top|85"],"hero":"","bookings":[],"new_bookings":[],"draft_roster":["p0-1|g03|top|70|false","p0-2|g05|top|65|false","p0-3|g01|top|45|false","p0-4|g09|top|85|false"],"draft_hero":"","boss_lane":"","undo":0},{"gold":140,"draft_gold":140,"ready":true,"earned":180,"spent":260,"next_seq":5,"roster":["p1-1|w03|mid|75","p1-2|w01|mid|50","p1-3|w05|mid|60","p1-4|w03|mid|75"],"hero":"","bookings":[],"new_bookings":[],"draft_roster":["p1-1|w03|mid|75|false","p1-2|w01|mid|50|false","p1-3|w05|mid|60|false","p1-4|w03|mid|75|false"],"draft_hero":"","boss_lane":"","undo":0},{"gold":125,"draft_gold":125,"ready":true,"earned":180,"spent":275,"next_seq":5,"roster":["p2-1|g03|bot|70","p2-2|g01|bot|45","p2-3|g05|bot|65","p2-4|g07|bot|95"],"hero":"","bookings":[],"new_bookings":[],"draft_roster":["p2-1|g03|bot|70|false","p2-2|g01|bot|45|false","p2-3|g05|bot|65|false","p2-4|g07|bot|95|false"],"draft_hero":"","boss_lane":"","undo":0},{"gold":140,"draft_gold":140,"ready":true,"earned":180,"spent":260,"next_seq":5,"roster":["p3-1|w03|top|75","p3-2|w05|top|60","p3-3|w01|top|50","p3-4|w03|top|75"],"hero":"","bookings":[],"new_bookings":[],"draft_roster":["p3-1|w03|top|75|false","p3-2|w05|top|60|false","p3-3|w01|top|50|false","p3-4|w03|top|75|false"],"draft_hero":"","boss_lane":"","undo":0},{"gold":125,"draft_gold":125,"ready":true,"earned":180,"spent":275,"next_seq":5,"roster":["p4-1|g01|mid|45","p4-2|g05|mid|65","p4-3|g03|mid|70","p4-4|g07|mid|95"],"hero":"","bookings":[],"new_bookings":[],"draft_roster":["p4-1|g01|mid|45|false","p4-2|g05|mid|65|false","p4-3|g03|mid|70|false","p4-4|g07|mid|95|false"],"draft_hero":"","boss_lane":"","undo":0},{"gold":105,"draft_gold":105,"ready":true,"earned":180,"spent":295,"next_seq":5,"roster":["p5-1|w05|bot|60","p5-2|w03|bot|75","p5-3|w07|bot|100","p5-4|w05|bot|60"],"hero":"","bookings":[],"new_bookings":[],"draft_roster":["p5-1|w05|bot|60|false","p5-2|w03|bot|75|false","p5-3|w07|bot|100|false","p5-4|w05|bot|60|false"],"draft_hero":"","boss_lane":"","undo":0}],"buildings":[7500.0,5970.1,7500.0,5890.8,7500.0,5790.700000000003,9000.0,9000.0,12000.0,7500.0,6000.0,7500.0,6000.0,7500.0,5882.55,9000.0,9000.0,12000.0],"boss":{"next":1,"settled":2,"claim":""},"boss_log":[],"announcements":[],"settlement":{"round":2,"gains":[18,18,18,18,18,18],"income":74,"lost":[],"end_reason":"cleared","combat_time":54.69999999999903,"boss":"none","lane_kills":{"mid":6,"bot":6,"top":6},"xp":{}},"combat":{"round":2,"steps":1094,"elapsed":54.69999999999903,"finished":true,"end_reason":"cleared","destroyed":[],"grotto":"none|-1|-1|true","grotto_boss":"","grotto_boss_hp":0.0,"events":42,"mobile":[0,0,0]}},{"label":"round-3","phase":0,"round":4,"winner":-2,"end_note":"","players":[{"gold":175,"draft_gold":175,"ready":true,"earned":290,"spent":335,"next_seq":6,"roster":["p0-1|g03|top|70","p0-2|g05|top|65","p0-3|g01|top|45","p0-4|g09|top|85","p0-5|g03|top|70"],"hero":"","bookings":[],"new_bookings":[],"draft_roster":["p0-1|g03|top|70|false","p0-2|g05|top|65|false","p0-3|g01|top|45|false","p0-4|g09|top|85|false","p0-5|g03|top|70|false"],"draft_hero":"","boss_lane":"","undo":0},{"gold":150,"draft_gold":150,"ready":true,"earned":290,"spent":360,"next_seq":6,"roster":["p1-1|w03|mid|75","p1-2|w01|mid|50","p1-3|w05|mid|60","p1-4|w03|mid|75","p1-5|w07|mid|100"],"hero":"","bookings":[],"new_bookings":[],"draft_roster":["p1-1|w03|mid|75|false","p1-2|w01|mid|50|false","p1-3|w05|mid|60|false","p1-4|w03|mid|75|false","p1-5|w07|mid|100|false"],"draft_hero":"","boss_lane":"","undo":0},{"gold":165,"draft_gold":165,"ready":true,"earned":290,"spent":345,"next_seq":6,"roster":["p2-1|g03|bot|70","p2-2|g01|bot|45","p2-3|g05|bot|65","p2-4|g07|bot|95","p2-5|g03|bot|70"],"hero":"","bookings":[],"new_bookings":[],"draft_roster":["p2-1|g03|bot|70|false","p2-2|g01|bot|45|false","p2-3|g05|bot|65|false","p2-4|g07|bot|95|false","p2-5|g03|bot|70|false"],"draft_hero":"","boss_lane":"","undo":0},{"gold":150,"draft_gold":150,"ready":true,"earned":290,"spent":360,"next_seq":6,"roster":["p3-1|w03|top|75","p3-2|w05|top|60","p3-3|w01|top|50","p3-4|w03|top|75","p3-5|w07|top|100"],"hero":"","bookings":[],"new_bookings":[],"draft_roster":["p3-1|w03|top|75|false","p3-2|w05|top|60|false","p3-3|w01|top|50|false","p3-4|w03|top|75|false","p3-5|w07|top|100|false"],"draft_hero":"","boss_lane":"","undo":0},{"gold":125,"draft_gold":125,"ready":true,"earned":290,"spent":385,"next_seq":7,"roster":["p4-1|g01|mid|45","p4-2|g05|mid|65","p4-3|g03|mid|70","p4-4|g07|mid|95","p4-5|g01|mid|45","p4-6|g05|mid|65"],"hero":"","bookings":[],"new_bookings":[],"draft_roster":["p4-1|g01|mid|45|false","p4-2|g05|mid|65|false","p4-3|g03|mid|70|false","p4-4|g07|mid|95|false","p4-5|g01|mid|45|false","p4-6|g05|mid|65|false"],"draft_hero":"","boss_lane":"","undo":0},{"gold":165,"draft_gold":165,"ready":true,"earned":290,"spent":345,"next_seq":6,"roster":["p5-1|w05|bot|60","p5-2|w03|bot|75","p5-3|w07|bot|100","p5-4|w05|bot|60","p5-5|w01|bot|50"],"hero":"","bookings":[],"new_bookings":[],"draft_roster":["p5-1|w05|bot|60|false","p5-2|w03|bot|75|false","p5-3|w07|bot|100|false","p5-4|w05|bot|60|false","p5-5|w01|bot|50|false"],"draft_hero":"","boss_lane":"","undo":0}],"buildings":[7500.0,5497.4000000000015,7500.0,5579.6,7500.0,5641.200000000004,9000.0,9000.0,12000.0,7500.0,6000.0,7500.0,6000.0,7500.0,5882.55,9000.0,9000.0,12000.0],"boss":{"next":1,"settled":3,"claim":""},"boss_log":[],"announcements":[],"settlement":{"round":3,"gains":[32,32,32,32,32,32],"income":78,"lost":[],"end_reason":"cleared","combat_time":60.29999999999871,"boss":"none","lane_kills":{"mid":6,"bot":6,"top":6},"xp":{}},"combat":{"round":3,"steps":1206,"elapsed":60.29999999999871,"finished":true,"end_reason":"cleared","destroyed":[],"grotto":"none|-1|-1|true","grotto_boss":"","grotto_boss_hp":0.0,"events":49,"mobile":[0,0,0]}},{"label":"round-4","phase":0,"round":5,"winner":-2,"end_note":"","players":[{"gold":137,"draft_gold":137,"ready":true,"earned":412,"spent":495,"next_seq":8,"roster":["p0-1|g03|top|70","p0-2|g05|top|65","p0-3|g01|top|45","p0-4|g09|top|85","p0-5|g03|top|70","p0-6|g07|top|95","p0-7|g05|top|65"],"hero":"","bookings":[],"new_bookings":[],"draft_roster":["p0-1|g03|top|70|false","p0-2|g05|top|65|false","p0-3|g01|top|45|false","p0-4|g09|top|85|false","p0-5|g03|top|70|false","p0-6|g07|top|95|false","p0-7|g05|top|65|false"],"draft_hero":"","boss_lane":"","undo":0},{"gold":132,"draft_gold":132,"ready":true,"earned":412,"spent":500,"next_seq":8,"roster":["p1-1|w03|mid|75","p1-2|w01|mid|50","p1-3|w05|mid|60","p1-4|w03|mid|75","p1-5|w07|mid|100","p1-6|w09|mid|90","p1-7|w01|mid|50"],"hero":"","bookings":[],"new_bookings":[],"draft_roster":["p1-1|w03|mid|75|false","p1-2|w01|mid|50|false","p1-3|w05|mid|60|false","p1-4|w03|mid|75|false","p1-5|w07|mid|100|false","p1-6|w09|mid|90|false","p1-7|w01|mid|50|false"],"draft_hero":"","boss_lane":"","undo":0},{"gold":157,"draft_gold":157,"ready":true,"earned":412,"spent":475,"next_seq":8,"roster":["p2-1|g03|bot|70","p2-2|g01|bot|45","p2-3|g05|bot|65","p2-4|g07|bot|95","p2-5|g03|bot|70","p2-6|g09|bot|85","p2-7|g01|bot|45"],"hero":"","bookings":[],"new_bookings":[],"draft_roster":["p2-1|g03|bot|70|false","p2-2|g01|bot|45|false","p2-3|g05|bot|65|false","p2-4|g07|bot|95|false","p2-5|g03|bot|70|false","p2-6|g09|bot|85|false","p2-7|g01|bot|45|false"],"draft_hero":"","boss_lane":"","undo":0},{"gold":122,"draft_gold":122,"ready":true,"earned":412,"spent":510,"next_seq":8,"roster":["p3-1|w03|top|75","p3-2|w05|top|60","p3-3|w01|top|50","p3-4|w03|top|75","p3-5|w07|top|100","p3-6|w09|top|90","p3-7|w05|top|60"],"hero":"","bookings":[],"new_bookings":[],"draft_roster":["p3-1|w03|top|75|false","p3-2|w05|top|60|false","p3-3|w01|top|50|false","p3-4|w03|top|75|false","p3-5|w07|top|100|false","p3-6|w09|top|90|false","p3-7|w05|top|60|false"],"draft_hero":"","boss_lane":"","undo":0},{"gold":132,"draft_gold":132,"ready":true,"earned":412,"spent":500,"next_seq":9,"roster":["p4-1|g01|mid|45","p4-2|g05|mid|65","p4-3|g03|mid|70","p4-4|g07|mid|95","p4-5|g01|mid|45","p4-6|g05|mid|65","p4-7|g01|mid|45","p4-8|g03|mid|70"],"hero":"","bookings":[],"new_bookings":[],"draft_roster":["p4-1|g01|mid|45|false","p4-2|g05|mid|65|false","p4-3|g03|mid|70|false","p4-4|g07|mid|95|false","p4-5|g01|mid|45|false","p4-6|g05|mid|65|false","p4-7|g01|mid|45|false","p4-8|g03|mid|70|false"],"draft_hero":"","boss_lane":"","undo":0},{"gold":137,"draft_gold":137,"ready":true,"earned":412,"spent":495,"next_seq":8,"roster":["p5-1|w05|bot|60","p5-2|w03|bot|75","p5-3|w07|bot|100","p5-4|w05|bot|60","p5-5|w01|bot|50","p5-6|w09|bot|90","p5-7|w05|bot|60"],"hero":"","bookings":[],"new_bookings":[],"draft_roster":["p5-1|w05|bot|60|false","p5-2|w03|bot|75|false","p5-3|w07|bot|100|false","p5-4|w05|bot|60|false","p5-5|w01|bot|50|false","p5-6|w09|bot|90|false","p5-7|w05|bot|60|false"],"draft_hero":"","boss_lane":"","undo":0}],"buildings":[7500.0,5288.100000000004,7500.0,5376.800000000001,7500.0,4973.300000000012,9000.0,9000.0,12000.0,7500.0,6000.0,7500.0,6000.0,7500.0,5882.55,9000.0,9000.0,12000.0],"boss":{"next":1,"settled":4,"claim":""},"boss_log":[],"announcements":[],"settlement":{"round":4,"gains":[40,40,40,40,40,40],"income":82,"lost":[],"end_reason":"cleared","combat_time":61.69999999999863,"boss":"none","lane_kills":{"mid":8,"bot":8,"top":8},"xp":{}},"combat":{"round":4,"steps":1234,"elapsed":61.69999999999863,"finished":true,"end_reason":"cleared","destroyed":[],"grotto":"none|-1|-1|true","grotto_boss":"","grotto_boss_hp":0.0,"events":67,"mobile":[0,0,0]}},{"label":"round-5","phase":0,"round":6,"winner":-2,"end_note":"","players":[{"gold":133,"draft_gold":133,"ready":true,"earned":543,"spent":630,"next_seq":9,"roster":["p0-1|g03|top|70","p0-2|g05|top|65","p0-3|g02|top|135","p0-4|g09|top|85","p0-5|g03|top|70","p0-6|g07|top|95","p0-7|g05|top|65","p0-8|g01|top|45"],"hero":"","bookings":[],"new_bookings":[],"draft_roster":["p0-1|g03|top|70|false","p0-2|g05|top|65|false","p0-3|g02|top|135|false","p0-4|g09|top|85|false","p0-5|g03|top|70|false","p0-6|g07|top|95|false","p0-7|g05|top|65|false","p0-8|g01|top|45|false"],"draft_hero":"","boss_lane":"","undo":0},{"gold":163,"draft_gold":163,"ready":true,"earned":543,"spent":600,"next_seq":8,"roster":["p1-1|w03|mid|75","p1-2|w02|mid|150","p1-3|w05|mid|60","p1-4|w03|mid|75","p1-5|w07|mid|100","p1-6|w09|mid|90","p1-7|w01|mid|50"],"hero":"","bookings":[],"new_bookings":[],"draft_roster":["p1-1|w03|mid|75|false","p1-2|w02|mid|150|false","p1-3|w05|mid|60|false","p1-4|w03|mid|75|false","p1-5|w07|mid|100|false","p1-6|w09|mid|90|false","p1-7|w01|mid|50|false"],"draft_hero":"","boss_lane":"","undo":0},{"gold":133,"draft_gold":133,"ready":true,"earned":543,"spent":630,"next_seq":9,"roster":["p2-1|g03|bot|70","p2-2|g02|bot|135","p2-3|g05|bot|65","p2-4|g07|bot|95","p2-5|g03|bot|70","p2-6|g09|bot|85","p2-7|g01|bot|45","p2-8|g05|bot|65"],"hero":"","bookings":[],"new_bookings":[],"draft_roster":["p2-1|g03|bot|70|false","p2-2|g02|bot|135|false","p2-3|g05|bot|65|false","p2-4|g07|bot|95|false","p2-5|g03|bot|70|false","p2-6|g09|bot|85|false","p2-7|g01|bot|45|false","p2-8|g05|bot|65|false"],"draft_hero":"","boss_lane":"","undo":0},{"gold":153,"draft_gold":153,"ready":true,"earned":543,"spent":610,"next_seq":8,"roster":["p3-1|w03|top|75","p3-2|w05|top|60","p3-3|w02|top|150","p3-4|w03|top|75","p3-5|w07|top|100","p3-6|w09|top|90","p3-7|w05|top|60"],"hero":"","bookings":[],"new_bookings":[],"draft_roster":["p3-1|w03|top|75|false","p3-2|w05|top|60|false","p3-3|w02|top|150|false","p3-4|w03|top|75|false","p3-5|w07|top|100|false","p3-6|w09|top|90|false","p3-7|w05|top|60|false"],"draft_hero":"","boss_lane":"","undo":0},{"gold":173,"draft_gold":173,"ready":true,"earned":543,"spent":590,"next_seq":9,"roster":["p4-1|g02|mid|135","p4-2|g05|mid|65","p4-3|g03|mid|70","p4-4|g07|mid|95","p4-5|g01|mid|45","p4-6|g05|mid|65","p4-7|g01|mid|45","p4-8|g03|mid|70"],"hero":"","bookings":[],"new_bookings":[],"draft_roster":["p4-1|g02|mid|135|false","p4-2|g05|mid|65|false","p4-3|g03|mid|70|false","p4-4|g07|mid|95|false","p4-5|g01|mid|45|false","p4-6|g05|mid|65|false","p4-7|g01|mid|45|false","p4-8|g03|mid|70|false"],"draft_hero":"","boss_lane":"","undo":0},{"gold":168,"draft_gold":168,"ready":true,"earned":543,"spent":595,"next_seq":8,"roster":["p5-1|w05|bot|60","p5-2|w03|bot|75","p5-3|w07|bot|100","p5-4|w05|bot|60","p5-5|w02|bot|150","p5-6|w09|bot|90","p5-7|w05|bot|60"],"hero":"","bookings":[],"new_bookings":[],"draft_roster":["p5-1|w05|bot|60|false","p5-2|w03|bot|75|false","p5-3|w07|bot|100|false","p5-4|w05|bot|60|false","p5-5|w02|bot|150|false","p5-6|w09|bot|90|false","p5-7|w05|bot|60|false"],"draft_hero":"","boss_lane":"","undo":0}],"buildings":[7500.0,5288.100000000004,7500.0,5376.800000000001,7500.0,4973.300000000012,9000.0,9000.0,12000.0,7500.0,5614.118399999997,7500.0,5979.6576,7500.0,5590.268399999996,9000.0,9000.0,12000.0],"boss":{"next":1,"settled":5,"claim":""},"boss_log":[],"announcements":[],"settlement":{"round":5,"gains":[45,45,45,45,45,45],"income":86,"lost":[],"end_reason":"cleared","combat_time":56.49999999999893,"boss":"none","lane_kills":{"mid":8,"bot":8,"top":8},"xp":{}},"combat":{"round":5,"steps":1130,"elapsed":56.49999999999893,"finished":true,"end_reason":"cleared","destroyed":[],"grotto":"none|-1|-1|true","grotto_boss":"","grotto_boss_hp":0.0,"events":69,"mobile":[0,0,0]}},{"label":"round-6","phase":0,"round":7,"winner":-2,"end_note":"","players":[{"gold":173,"draft_gold":173,"ready":true,"earned":673,"spent":720,"next_seq":9,"roster":["p0-1|g03|top|70","p0-2|g05|top|65","p0-3|g02|top|135","p0-4|g09|top|85","p0-5|g03|top|70","p0-6|g07|top|95","p0-7|g05|top|65","p0-8|g02|top|135"],"hero":"","bookings":[],"new_bookings":[],"draft_roster":["p0-1|g03|top|70|false","p0-2|g05|top|65|false","p0-3|g02|top|135|false","p0-4|g09|top|85|false","p0-5|g03|top|70|false","p0-6|g07|top|95|false","p0-7|g05|top|65|false","p0-8|g02|top|135|false"],"draft_hero":"","boss_lane":"","undo":0},{"gold":193,"draft_gold":193,"ready":true,"earned":673,"spent":700,"next_seq":8,"roster":["p1-1|w03|mid|75","p1-2|w02|mid|150","p1-3|w05|mid|60","p1-4|w03|mid|75","p1-5|w07|mid|100","p1-6|w09|mid|90","p1-7|w02|mid|150"],"hero":"","bookings":[],"new_bookings":[],"draft_roster":["p1-1|w03|mid|75|false","p1-2|w02|mid|150|false","p1-3|w05|mid|60|false","p1-4|w03|mid|75|false","p1-5|w07|mid|100|false","p1-6|w09|mid|90|false","p1-7|w02|mid|150|false"],"draft_hero":"","boss_lane":"","undo":0},{"gold":173,"draft_gold":173,"ready":true,"earned":673,"spent":720,"next_seq":9,"roster":["p2-1|g03|bot|70","p2-2|g02|bot|135","p2-3|g05|bot|65","p2-4|g07|bot|95","p2-5|g03|bot|70","p2-6|g09|bot|85","p2-7|g02|bot|135","p2-8|g05|bot|65"],"hero":"","bookings":[],"new_bookings":[],"draft_roster":["p2-1|g03|bot|70|false","p2-2|g02|bot|135|false","p2-3|g05|bot|65|false","p2-4|g07|bot|95|false","p2-5|g03|bot|70|false","p2-6|g09|bot|85|false","p2-7|g02|bot|135|false","p2-8|g05|bot|65|false"],"draft_hero":"","boss_lane":"","undo":0},{"gold":148,"draft_gold":148,"ready":true,"earned":673,"spent":745,"next_seq":8,"roster":["p3-1|w03|top|75","p3-2|w06|top|195","p3-3|w02|top|150","p3-4|w03|top|75","p3-5|w07|top|100","p3-6|w09|top|90","p3-7|w05|top|60"],"hero":"","bookings":[],"new_bookings":[],"draft_roster":["p3-1|w03|top|75|false","p3-2|w06|top|195|false","p3-3|w02|top|150|false","p3-4|w03|top|75|false","p3-5|w07|top|100|false","p3-6|w09|top|90|false","p3-7|w05|top|60|false"],"draft_hero":"","boss_lane":"","undo":0},{"gold":213,"draft_gold":213,"ready":true,"earned":673,"spent":680,"next_seq":9,"roster":["p4-1|g02|mid|135","p4-2|g05|mid|65","p4-3|g03|mid|70","p4-4|g07|mid|95","p4-5|g02|mid|135","p4-6|g05|mid|65","p4-7|g01|mid|45","p4-8|g03|mid|70"],"hero":"","bookings":[],"new_bookings":[],"draft_roster":["p4-1|g02|mid|135|false","p4-2|g05|mid|65|false","p4-3|g03|mid|70|false","p4-4|g07|mid|95|false","p4-5|g02|mid|135|false","p4-6|g05|mid|65|false","p4-7|g01|mid|45|false","p4-8|g03|mid|70|false"],"draft_hero":"","boss_lane":"","undo":0},{"gold":163,"draft_gold":163,"ready":true,"earned":673,"spent":730,"next_seq":8,"roster":["p5-1|w06|bot|195","p5-2|w03|bot|75","p5-3|w07|bot|100","p5-4|w05|bot|60","p5-5|w02|bot|150","p5-6|w09|bot|90","p5-7|w05|bot|60"],"hero":"","bookings":[],"new_bookings":[],"draft_roster":["p5-1|w06|bot|195|false","p5-2|w03|bot|75|false","p5-3|w07|bot|100|false","p5-4|w05|bot|60|false","p5-5|w02|bot|150|false","p5-6|w09|bot|90|false","p5-7|w05|bot|60|false"],"draft_hero":"","boss_lane":"","undo":0}],"buildings":[7500.0,4122.065000000002,7500.0,4954.039999999998,7500.0,3861.800000000013,9000.0,9000.0,12000.0,7500.0,5614.118399999997,7500.0,5979.6576,7500.0,5590.268399999996,9000.0,9000.0,12000.0],"boss":{"next":1,"settled":6,"claim":""},"boss_log":[],"announcements":[],"settlement":{"round":6,"gains":[40,40,40,40,40,40],"income":90,"lost":[],"end_reason":"cleared","combat_time":59.09999999999878,"boss":"none","lane_kills":{"mid":8,"bot":8,"top":8},"xp":{}},"combat":{"round":6,"steps":1182,"elapsed":59.09999999999878,"finished":true,"end_reason":"cleared","destroyed":[],"grotto":"none|-1|-1|true","grotto_boss":"","grotto_boss_hp":0.0,"events":69,"mobile":[0,0,0]}},{"label":"round-7","phase":0,"round":8,"winner":-2,"end_note":"","players":[{"gold":185,"draft_gold":185,"ready":true,"earned":825,"spent":860,"next_seq":9,"roster":["p0-1|g03|top|70","p0-2|g06|top|205","p0-3|g02|top|135","p0-4|g09|top|85","p0-5|g03|top|70","p0-6|g07|top|95","p0-7|g05|top|65","p0-8|g02|top|135"],"hero":"","bookings":[],"new_bookings":[],"draft_roster":["p0-1|g03|top|70|false","p0-2|g06|top|205|false","p0-3|g02|top|135|false","p0-4|g09|top|85|false","p0-5|g03|top|70|false","p0-6|g07|top|95|false","p0-7|g05|top|65|false","p0-8|g02|top|135|false"],"draft_hero":"","boss_lane":"","undo":0},{"gold":210,"draft_gold":210,"ready":true,"earned":825,"spent":835,"next_seq":8,"roster":["p1-1|w03|mid|75","p1-2|w02|mid|150","p1-3|w06|mid|195","p1-4|w03|mid|75","p1-5|w07|mid|100","p1-6|w09|mid|90","p1-7|w02|mid|150"],"hero":"","bookings":[],"new_bookings":[],"draft_roster":["p1-1|w03|mid|75|false","p1-2|w02|mid|150|false","p1-3|w06|mid|195|false","p1-4|w03|mid|75|false","p1-5|w07|mid|100|false","p1-6|w09|mid|90|false","p1-7|w02|mid|150|false"],"draft_hero":"","boss_lane":"","undo":0},{"gold":185,"draft_gold":185,"ready":true,"earned":825,"spent":860,"next_seq":9,"roster":["p2-1|g03|bot|70","p2-2|g02|bot|135","p2-3|g06|bot|205","p2-4|g07|bot|95","p2-5|g03|bot|70","p2-6|g09|bot|85","p2-7|g02|bot|135","p2-8|g05|bot|65"],"hero":"","bookings":[],"new_bookings":[],"draft_roster":["p2-1|g03|bot|70|false","p2-2|g02|bot|135|false","p2-3|g06|bot|205|false","p2-4|g07|bot|95|false","p2-5|g03|bot|70|false","p2-6|g09|bot|85|false","p2-7|g02|bot|135|false","p2-8|g05|bot|65|false"],"draft_hero":"","boss_lane":"","undo":0},{"gold":165,"draft_gold":165,"ready":true,"earned":825,"spent":880,"next_seq":8,"roster":["p3-1|w03|top|75","p3-2|w06|top|195","p3-3|w02|top|150","p3-4|w03|top|75","p3-5|w07|top|100","p3-6|w09|top|90","p3-7|w06|top|195"],"hero":"","bookings":[],"new_bookings":[],"draft_roster":["p3-1|w03|top|75|false","p3-2|w06|top|195|false","p3-3|w02|top|150|false","p3-4|w03|top|75|false","p3-5|w07|top|100|false","p3-6|w09|top|90|false","p3-7|w06|top|195|false"],"draft_hero":"","boss_lane":"","undo":0},{"gold":190,"draft_gold":190,"ready":true,"earned":825,"spent":855,"next_seq":10,"roster":["p4-1|g02|mid|135","p4-2|g05|mid|65","p4-3|g03|mid|70","p4-4|g07|mid|95","p4-5|g02|mid|135","p4-6|g05|mid|65","p4-7|g02|mid|135","p4-8|g03|mid|70","p4-9|g09|mid|85"],"hero":"","bookings":[],"new_bookings":[],"draft_roster":["p4-1|g02|mid|135|false","p4-2|g05|mid|65|false","p4-3|g03|mid|70|false","p4-4|g07|mid|95|false","p4-5|g02|mid|135|false","p4-6|g05|mid|65|false","p4-7|g02|mid|135|false","p4-8|g03|mid|70|false","p4-9|g09|mid|85|false"],"draft_hero":"","boss_lane":"","undo":0},{"gold":180,"draft_gold":180,"ready":true,"earned":825,"spent":865,"next_seq":8,"roster":["p5-1|w06|bot|195","p5-2|w03|bot|75","p5-3|w07|bot|100","p5-4|w06|bot|195","p5-5|w02|bot|150","p5-6|w09|bot|90","p5-7|w05|bot|60"],"hero":"","bookings":[],"new_bookings":[],"draft_roster":["p5-1|w06|bot|195|false","p5-2|w03|bot|75|false","p5-3|w07|bot|100|false","p5-4|w06|bot|195|false","p5-5|w02|bot|150|false","p5-6|w09|bot|90|false","p5-7|w05|bot|60|false"],"draft_hero":"","boss_lane":"","undo":0}],"buildings":[7500.0,3362.376200000001,7500.0,4536.084800000002,7500.0,3544.600000000012,9000.0,9000.0,12000.0,7500.0,5614.118399999997,7500.0,5979.6576,7500.0,5590.268399999996,9000.0,9000.0,12000.0],"boss":{"next":1,"settled":7,"claim":""},"boss_log":[],"announcements":[],"settlement":{"round":7,"gains":[58,58,58,58,58,58],"income":94,"lost":[],"end_reason":"cleared","combat_time":55.499999999998984,"boss":"none","lane_kills":{"mid":10,"bot":10,"top":10},"xp":{}},"combat":{"round":7,"steps":1110,"elapsed":55.499999999998984,"finished":true,"end_reason":"cleared","destroyed":[],"grotto":"none|-1|-1|true","grotto_boss":"","grotto_boss_hp":0.0,"events":76,"mobile":[0,0,0]}},{"label":"round-8","phase":0,"round":9,"winner":-2,"end_note":"","players":[{"gold":200,"draft_gold":200,"ready":true,"earned":980,"spent":1000,"next_seq":9,"roster":["p0-1|g03|top|70","p0-2|g06|top|205","p0-3|g02|top|135","p0-4|g09|top|85","p0-5|g03|top|70","p0-6|g07|top|95","p0-7|g06|top|205","p0-8|g02|top|135"],"hero":"","bookings":[],"new_bookings":[],"draft_roster":["p0-1|g03|top|70|false","p0-2|g06|top|205|false","p0-3|g02|top|135|false","p0-4|g09|top|85|false","p0-5|g03|top|70|false","p0-6|g07|top|95|false","p0-7|g06|top|205|false","p0-8|g02|top|135|false"],"draft_hero":"","boss_lane":"","undo":0},{"gold":210,"draft_gold":210,"ready":true,"earned":980,"spent":990,"next_seq":8,"roster":["p1-1|w04|mid|230","p1-2|w02|mid|150","p1-3|w06|mid|195","p1-4|w03|mid|75","p1-5|w07|mid|100","p1-6|w09|mid|90","p1-7|w02|mid|150"],"hero":"","bookings":[],"new_bookings":[],"draft_roster":["p1-1|w04|mid|230|false","p1-2|w02|mid|150|false","p1-3|w06|mid|195|false","p1-4|w03|mid|75|false","p1-5|w07|mid|100|false","p1-6|w09|mid|90|false","p1-7|w02|mid|150|false"],"draft_hero":"","boss_lane":"","undo":0},{"gold":200,"draft_gold":200,"ready":true,"earned":980,"spent":1000,"next_seq":9,"roster":["p2-1|g03|bot|70","p2-2|g02|bot|135","p2-3|g06|bot|205","p2-4|g07|bot|95","p2-5|g03|bot|70","p2-6|g09|bot|85","p2-7|g02|bot|135","p2-8|g06|bot|205"],"hero":"","bookings":[],"new_bookings":[],"draft_roster":["p2-1|g03|bot|70|false","p2-2|g02|bot|135|false","p2-3|g06|bot|205|false","p2-4|g07|bot|95|false","p2-5|g03|bot|70|false","p2-6|g09|bot|85|false","p2-7|g02|bot|135|false","p2-8|g06|bot|205|false"],"draft_hero":"","boss_lane":"","undo":0},{"gold":165,"draft_gold":165,"ready":true,"earned":980,"spent":1035,"next_seq":8,"roster":["p3-1|w04|top|230","p3-2|w06|top|195","p3-3|w02|top|150","p3-4|w03|top|75","p3-5|w07|top|100","p3-6|w09|top|90","p3-7|w06|top|195"],"hero":"","bookings":[],"new_bookings":[],"draft_roster":["p3-1|w04|top|230|false","p3-2|w06|top|195|false","p3-3|w02|top|150|false","p3-4|w03|top|75|false","p3-5|w07|top|100|false","p3-6|w09|top|90|false","p3-7|w06|top|195|false"],"draft_hero":"","boss_lane":"","undo":0},{"gold":160,"draft_gold":160,"ready":true,"earned":980,"spent":1040,"next_seq":11,"roster":["p4-1|g02|mid|135","p4-2|g06|mid|205","p4-3|g03|mid|70","p4-4|g07|mid|95","p4-5|g02|mid|135","p4-6|g05|mid|65","p4-7|g02|mid|135","p4-8|g03|mid|70","p4-9|g09|mid|85","p4-10|g01|mid|45"],"hero":"","bookings":[],"new_bookings":[],"draft_roster":["p4-1|g02|mid|135|false","p4-2|g06|mid|205|false","p4-3|g03|mid|70|false","p4-4|g07|mid|95|false","p4-5|g02|mid|135|false","p4-6|g05|mid|65|false","p4-7|g02|mid|135|false","p4-8|g03|mid|70|false","p4-9|g09|mid|85|false","p4-10|g01|mid|45|false"],"draft_hero":"","boss_lane":"","undo":0},{"gold":200,"draft_gold":200,"ready":true,"earned":980,"spent":1000,"next_seq":8,"roster":["p5-1|w06|bot|195","p5-2|w03|bot|75","p5-3|w07|bot|100","p5-4|w06|bot|195","p5-5|w02|bot|150","p5-6|w09|bot|90","p5-7|w06|bot|195"],"hero":"","bookings":[],"new_bookings":[],"draft_roster":["p5-1|w06|bot|195|false","p5-2|w03|bot|75|false","p5-3|w07|bot|100|false","p5-4|w06|bot|195|false","p5-5|w02|bot|150|false","p5-6|w09|bot|90|false","p5-7|w06|bot|195|false"],"draft_hero":"","boss_lane":"","undo":0}],"buildings":[7500.0,2965.8762,7500.0,3157.557000000002,7500.0,2037.900000000009,9000.0,9000.0,12000.0,7500.0,5614.118399999997,7500.0,5979.6576,7500.0,5590.268399999996,9000.0,9000.0,12000.0],"boss":{"next":1,"settled":8,"claim":""},"boss_log":[],"announcements":[],"settlement":{"round":8,"gains":[57,57,57,57,57,57],"income":98,"lost":[],"end_reason":"cleared","combat_time":53.29999999999911,"boss":"none","lane_kills":{"mid":10,"top":10,"bot":10},"xp":{}},"combat":{"round":8,"steps":1066,"elapsed":53.29999999999911,"finished":true,"end_reason":"cleared","destroyed":[],"grotto":"none|-1|-1|true","grotto_boss":"","grotto_boss_hp":0.0,"events":77,"mobile":[0,0,0]}},{"label":"round-9","phase":0,"round":10,"winner":-2,"end_note":"","players":[{"gold":218,"draft_gold":218,"ready":true,"earned":1148,"spent":1150,"next_seq":10,"roster":["p0-1|g03|top|70","p0-2|g06|top|205","p0-3|g02|top|135","p0-4|g09|top|85","p0-5|g03|top|70","p0-6|g07|top|95","p0-7|g06|top|205","p0-8|g02|top|135"],"hero":"","bookings":["c0-9|ch_schutz|top|150|10"],"new_bookings":[],"draft_roster":["p0-1|g03|top|70|false","p0-2|g06|top|205|false","p0-3|g02|top|135|false","p0-4|g09|top|85|false","p0-5|g03|top|70|false","p0-6|g07|top|95|false","p0-7|g06|top|205|false","p0-8|g02|top|135|false"],"draft_hero":"","boss_lane":"","undo":0},{"gold":223,"draft_gold":223,"ready":true,"earned":1148,"spent":1145,"next_seq":8,"roster":["p1-1|w04|mid|230","p1-2|w02|mid|150","p1-3|w06|mid|195","p1-4|w04|mid|230","p1-5|w07|mid|100","p1-6|w09|mid|90","p1-7|w02|mid|150"],"hero":"","bookings":[],"new_bookings":[],"draft_roster":["p1-1|w04|mid|230|false","p1-2|w02|mid|150|false","p1-3|w06|mid|195|false","p1-4|w04|mid|230|false","p1-5|w07|mid|100|false","p1-6|w09|mid|90|false","p1-7|w02|mid|150|false"],"draft_hero":"","boss_lane":"","undo":0},{"gold":218,"draft_gold":218,"ready":true,"earned":1148,"spent":1150,"next_seq":9,"roster":["p2-1|g04|bot|220","p2-2|g02|bot|135","p2-3|g06|bot|205","p2-4|g07|bot|95","p2-5|g03|bot|70","p2-6|g09|bot|85","p2-7|g02|bot|135","p2-8|g06|bot|205"],"hero":"","bookings":[],"new_bookings":[],"draft_roster":["p2-1|g04|bot|220|false","p2-2|g02|bot|135|false","p2-3|g06|bot|205|false","p2-4|g07|bot|95|false","p2-5|g03|bot|70|false","p2-6|g09|bot|85|false","p2-7|g02|bot|135|false","p2-8|g06|bot|205|false"],"draft_hero":"","boss_lane":"","undo":0},{"gold":178,"draft_gold":178,"ready":true,"earned":1148,"spent":1190,"next_seq":8,"roster":["p3-1|w04|top|230","p3-2|w06|top|195","p3-3|w02|top|150","p3-4|w04|top|230","p3-5|w07|top|100","p3-6|w09|top|90","p3-7|w06|top|195"],"hero":"","bookings":[],"new_bookings":[],"draft_roster":["p3-1|w04|top|230|false","p3-2|w06|top|195|false","p3-3|w02|top|150|false","p3-4|w04|top|230|false","p3-5|w07|top|100|false","p3-6|w09|top|90|false","p3-7|w06|top|195|false"],"draft_hero":"","boss_lane":"","undo":0},{"gold":173,"draft_gold":173,"ready":true,"earned":1148,"spent":1195,"next_seq":12,"roster":["p4-1|g02|mid|135","p4-2|g06|mid|205","p4-3|g03|mid|70","p4-4|g07|mid|95","p4-5|g02|mid|135","p4-6|g05|mid|65","p4-7|g02|mid|135","p4-8|g03|mid|70","p4-9|g09|mid|85","p4-10|g02|mid|135","p4-11|g05|mid|65"],"hero":"","bookings":[],"new_bookings":[],"draft_roster":["p4-1|g02|mid|135|false","p4-2|g06|mid|205|false","p4-3|g03|mid|70|false","p4-4|g07|mid|95|false","p4-5|g02|mid|135|false","p4-6|g05|mid|65|false","p4-7|g02|mid|135|false","p4-8|g03|mid|70|false","p4-9|g09|mid|85|false","p4-10|g02|mid|135|false","p4-11|g05|mid|65|false"],"draft_hero":"","boss_lane":"","undo":0},{"gold":218,"draft_gold":218,"ready":true,"earned":1148,"spent":1150,"next_seq":9,"roster":["p5-1|w06|bot|195","p5-2|w03|bot|75","p5-3|w07|bot|100","p5-4|w06|bot|195","p5-5|w02|bot|150","p5-6|w09|bot|90","p5-7|w06|bot|195"],"hero":"","bookings":["c5-8|ch_druck|bot|150|10"],"new_bookings":[],"draft_roster":["p5-1|w06|bot|195|false","p5-2|w03|bot|75|false","p5-3|w07|bot|100|false","p5-4|w06|bot|195|false","p5-5|w02|bot|150|false","p5-6|w09|bot|90|false","p5-7|w06|bot|195|false"],"draft_hero":"","boss_lane":"","undo":0}],"buildings":[7500.0,355.22419999999954,7500.0,156.7788000000039,7500.0,2037.900000000009,9000.0,9000.0,12000.0,7500.0,5614.118399999997,7500.0,5979.6576,7500.0,1170.1655999999975,9000.0,9000.0,12000.0],"boss":{"next":1,"settled":9,"claim":""},"boss_log":[],"announcements":["champion|0|0|top|ch_schutz|0","champion|1|5|bot|ch_druck|0"],"settlement":{"round":9,"gains":[66,66,66,66,66,66],"income":102,"lost":[],"end_reason":"cleared","combat_time":66.29999999999838,"boss":"none","lane_kills":{"mid":10,"bot":10,"top":10},"xp":{}},"combat":{"round":9,"steps":1326,"elapsed":66.29999999999838,"finished":true,"end_reason":"cleared","destroyed":[],"grotto":"none|-1|-1|true","grotto_boss":"","grotto_boss_hp":0.0,"events":78,"mobile":[0,0,0]}},{"label":"round-10","phase":0,"round":11,"winner":-2,"end_note":"","players":[{"gold":272,"draft_gold":272,"ready":true,"earned":1352,"spent":1300,"next_seq":10,"roster":["p0-1|g04|top|220","p0-2|g06|top|205","p0-3|g02|top|135","p0-4|g09|top|85","p0-5|g03|top|70","p0-6|g07|top|95","p0-7|g06|top|205","p0-8|g02|top|135"],"hero":"","bookings":[],"new_bookings":[],"draft_roster":["p0-1|g04|top|220|false","p0-2|g06|top|205|false","p0-3|g02|top|135|false","p0-4|g09|top|85|false","p0-5|g03|top|70|false","p0-6|g07|top|95|false","p0-7|g06|top|205|false","p0-8|g02|top|135|false"],"draft_hero":"","boss_lane":"","undo":0},{"gold":247,"draft_gold":247,"ready":true,"earned":1352,"spent":1325,"next_seq":9,"roster":["p1-1|w04|mid|230","p1-2|w02|mid|150","p1-3|w06|mid|195","p1-4|w04|mid|230","p1-5|w07|mid|100","p1-6|w09|mid|90","p1-7|w02|mid|150"],"hero":"","bookings":["c1-8|ch_belagerung|mid|180|11"],"new_bookings":[],"draft_roster":["p1-1|w04|mid|230|false","p1-2|w02|mid|150|false","p1-3|w06|mid|195|false","p1-4|w04|mid|230|false","p1-5|w07|mid|100|false","p1-6|w09|mid|90|false","p1-7|w02|mid|150|false"],"draft_hero":"","boss_lane":"","undo":0},{"gold":336,"draft_gold":336,"ready":true,"earned":1416,"spent":1300,"next_seq":9,"roster":["p2-1|g04|bot|220","p2-2|g02|bot|135","p2-3|g06|bot|205","p2-4|g07|bot|95","p2-5|g04|bot|220","p2-6|g09|bot|85","p2-7|g02|bot|135","p2-8|g06|bot|205"],"hero":"","bookings":[],"new_bookings":[],"draft_roster":["p2-1|g04|bot|220|false","p2-2|g02|bot|135|false","p2-3|g06|bot|205|false","p2-4|g07|bot|95|false","p2-5|g04|bot|220|false","p2-6|g09|bot|85|false","p2-7|g02|bot|135|false","p2-8|g06|bot|205|false"],"draft_hero":"","boss_lane":"","undo":0},{"gold":422,"draft_gold":422,"ready":true,"earned":1517,"spent":1315,"next_seq":10,"roster":["p3-1|w04|top|230","p3-2|w06|top|195","p3-3|w02|top|150","p3-4|w04|top|230","p3-5|w07|top|100","p3-6|w09|top|90","p3-7|w06|top|195","p3-8|w03|top|75","p3-9|w01|top|50"],"hero":"","bookings":[],"new_bookings":[],"draft_roster":["p3-1|w04|top|230|false","p3-2|w06|top|195|false","p3-3|w02|top|150|false","p3-4|w04|top|230|false","p3-5|w07|top|100|false","p3-6|w09|top|90|false","p3-7|w06|top|195|false","p3-8|w03|top|75|false","p3-9|w01|top|50|false"],"draft_hero":"","boss_lane":"","undo":0},{"gold":337,"draft_gold":337,"ready":true,"earned":1452,"spent":1335,"next_seq":12,"roster":["p4-1|g02|mid|135","p4-2|g06|mid|205","p4-3|g03|mid|70","p4-4|g07|mid|95","p4-5|g02|mid|135","p4-6|g06|mid|205","p4-7|g02|mid|135","p4-8|g03|mid|70","p4-9|g09|mid|85","p4-10|g02|mid|135","p4-11|g05|mid|65"],"hero":"","bookings":[],"new_bookings":[],"draft_roster":["p4-1|g02|mid|135|false","p4-2|g06|mid|205|false","p4-3|g03|mid|70|false","p4-4|g07|mid|95|false","p4-5|g02|mid|135|false","p4-6|g06|mid|205|false","p4-7|g02|mid|135|false","p4-8|g03|mid|70|false","p4-9|g09|mid|85|false","p4-10|g02|mid|135|false","p4-11|g05|mid|65|false"],"draft_hero":"","boss_lane":"","undo":0},{"gold":366,"draft_gold":366,"ready":true,"earned":1451,"spent":1305,"next_seq":9,"roster":["p5-1|w06|bot|195","p5-2|w04|bot|230","p5-3|w07|bot|100","p5-4|w06|bot|195","p5-5|w02|bot|150","p5-6|w09|bot|90","p5-7|w06|bot|195"],"hero":"","bookings":[],"new_bookings":[],"draft_roster":["p5-1|w06|bot|195|false","p5-2|w04|bot|230|false","p5-3|w07|bot|100|false","p5-4|w06|bot|195|false","p5-5|w02|bot|150|false","p5-6|w09|bot|90|false","p5-7|w06|bot|195|false"],"draft_hero":"","boss_lane":"","undo":0}],"buildings":[7500.0,355.22419999999954,2223.154199999998,0.0,7024.199999999999,0.0,9000.0,9000.0,12000.0,7500.0,3643.2949999999964,7500.0,5979.6576,7500.0,1170.1655999999975,9000.0,9000.0,12000.0],"boss":{"next":1,"settled":10,"claim":""},"boss_log":[],"announcements":["champion|0|1|mid|ch_belagerung|0"],"settlement":{"round":10,"gains":[98,98,162,263,198,197],"income":106,"lost":["blau_mid_outer","blau_bot_outer"],"end_reason":"cleared","combat_time":72.14999999999804,"boss":"none","lane_kills":{"mid":12,"bot":13,"top":13},"xp":{}},"combat":{"round":10,"steps":1443,"elapsed":72.14999999999804,"finished":true,"end_reason":"cleared","destroyed":[],"grotto":"none|-1|-1|true","grotto_boss":"","grotto_boss_hp":0.0,"events":90,"mobile":[0,0,0]}},{"label":"round-11","phase":0,"round":12,"winner":-2,"end_note":"","players":[{"gold":270,"draft_gold":270,"ready":true,"earned":1610,"spent":1560,"next_seq":11,"roster":["p0-1|g04|top|220","p0-2|g06|top|205","p0-3|g02|top|135","p0-4|g09|top|85","p0-5|g03|top|70","p0-6|g07|top|95","p0-7|g06|top|205","p0-8|g02|top|135"],"hero":"h0-10|held_quellgeflecht|227|top|||260|false|","bookings":[],"new_bookings":[],"draft_roster":["p0-1|g04|top|220|false","p0-2|g06|top|205|false","p0-3|g02|top|135|false","p0-4|g09|top|85|false","p0-5|g03|top|70|false","p0-6|g07|top|95|false","p0-7|g06|top|205|false","p0-8|g02|top|135|false"],"draft_hero":"h0-10|held_quellgeflecht|227|top|||260|false|","boss_lane":"","undo":0},{"gold":325,"draft_gold":325,"ready":true,"earned":1610,"spent":1505,"next_seq":9,"roster":["p1-1|w04|mid|230","p1-2|w02|mid|150","p1-3|w06|mid|195","p1-4|w04|mid|230","p1-5|w07|mid|100","p1-6|w10|mid|270","p1-7|w02|mid|150"],"hero":"","bookings":[],"new_bookings":[],"draft_roster":["p1-1|w04|mid|230|false","p1-2|w02|mid|150|false","p1-3|w06|mid|195|false","p1-4|w04|mid|230|false","p1-5|w07|mid|100|false","p1-6|w10|mid|270|false","p1-7|w02|mid|150|false"],"draft_hero":"","boss_lane":"","undo":0},{"gold":264,"draft_gold":264,"ready":true,"earned":1674,"spent":1630,"next_seq":11,"roster":["p2-1|g04|bot|220","p2-2|g02|bot|135","p2-3|g06|bot|205","p2-4|g07|bot|95","p2-5|g04|bot|220","p2-6|g09|bot|85","p2-7|g02|bot|135","p2-8|g06|bot|205","p2-10|g03|bot|70"],"hero":"h2-9|held_ringborke|319|bot|||260|false|","bookings":[],"new_bookings":[],"draft_roster":["p2-1|g04|bot|220|false","p2-2|g02|bot|135|false","p2-3|g06|bot|205|false","p2-4|g07|bot|95|false","p2-5|g04|bot|220|false","p2-6|g09|bot|85|false","p2-7|g02|bot|135|false","p2-8|g06|bot|205|false","p2-10|g03|bot|70|false"],"draft_hero":"h2-9|held_ringborke|319|bot|||260|false|","boss_lane":"","undo":0},{"gold":413,"draft_gold":413,"ready":true,"earned":1868,"spent":1675,"next_seq":11,"roster":["p3-1|w04|top|230","p3-2|w06|top|195","p3-3|w02|top|150","p3-4|w04|top|230","p3-5|w07|top|100","p3-6|w09|top|90","p3-7|w06|top|195","p3-8|w03|top|75","p3-9|w02|top|150"],"hero":"h3-10|held_ringborke|159|top|||260|false|","bookings":[],"new_bookings":[],"draft_roster":["p3-1|w04|top|230|false","p3-2|w06|top|195|false","p3-3|w02|top|150|false","p3-4|w04|top|230|false","p3-5|w07|top|100|false","p3-6|w09|top|90|false","p3-7|w06|top|195|false","p3-8|w03|top|75|false","p3-9|w02|top|150|false"],"draft_hero":"h3-10|held_ringborke|159|top|||260|false|","boss_lane":"","undo":0},{"gold":495,"draft_gold":495,"ready":true,"earned":1870,"spent":1595,"next_seq":13,"roster":["p4-1|g02|mid|135","p4-2|g06|mid|205","p4-3|g03|mid|70","p4-4|g07|mid|95","p4-5|g02|mid|135","p4-6|g06|mid|205","p4-7|g02|mid|135","p4-8|g03|mid|70","p4-9|g09|mid|85","p4-10|g02|mid|135","p4-11|g05|mid|65"],"hero":"h4-12|held_funkenlanze|348|mid|||260|false|","bookings":[],"new_bookings":[],"draft_roster":["p4-1|g02|mid|135|false","p4-2|g06|mid|205|false","p4-3|g03|mid|70|false","p4-4|g07|mid|95|false","p4-5|g02|mid|135|false","p4-6|g06|mid|205|false","p4-7|g02|mid|135|false","p4-8|g03|mid|70|false","p4-9|g09|mid|85|false","p4-10|g02|mid|135|false","p4-11|g05|mid|65|false"],"draft_hero":"h4-12|held_funkenlanze|348|mid|||260|false|","boss_lane":"","undo":0},{"gold":382,"draft_gold":382,"ready":true,"earned":1802,"spent":1640,"next_seq":11,"roster":["p5-1|w06|bot|195","p5-2|w04|bot|230","p5-3|w07|bot|100","p5-4|w06|bot|195","p5-5|w02|bot|150","p5-6|w09|bot|90","p5-7|w06|bot|195","p5-10|w03|bot|75"],"hero":"h5-9|held_funkenlanze|326|bot|||260|false|","bookings":[],"new_bookings":[],"draft_roster":["p5-1|w06|bot|195|false","p5-2|w04|bot|230|false","p5-3|w07|bot|100|false","p5-4|w06|bot|195|false","p5-5|w02|bot|150|false","p5-6|w09|bot|90|false","p5-7|w06|bot|195|false","p5-10|w03|bot|75|false"],"draft_hero":"h5-9|held_funkenlanze|326|bot|||260|false|","boss_lane":"","undo":0}],"buildings":[0.0,0.0,1504.9041999999981,0.0,7024.199999999999,0.0,5416.529999999997,9000.0,12000.0,7500.0,3643.2949999999964,7500.0,5979.6576,4974.670000000001,0.0,9000.0,9000.0,12000.0],"boss":{"next":1,"settled":11,"claim":""},"boss_log":[],"announcements":[],"settlement":{"round":11,"gains":[148,148,148,241,308,241],"income":110,"lost":["blau_top_outer","rot_bot_outer","blau_top_inner"],"end_reason":"cleared","combat_time":114.74999999999562,"boss":"none","lane_kills":{"mid":13,"bot":12,"top":12},"xp":{"h4-12":348,"h5-9":326,"h2-9":319,"h0-10":227,"h3-10":159}},"combat":{"round":11,"steps":2295,"elapsed":114.74999999999562,"finished":true,"end_reason":"cleared","destroyed":[],"grotto":"none|-1|-1|true","grotto_boss":"","grotto_boss_hp":0.0,"events":97,"mobile":[0,0,0]}},{"label":"round-12","phase":2,"round":12,"winner":1,"end_note":"Ancient von Blau zerstört.","players":[{"gold":188,"draft_gold":50,"ready":true,"earned":1748,"spent":1780,"next_seq":13,"roster":["p0-1|g04|top|220","p0-2|g06|top|205","p0-3|g02|top|135","p0-4|g09|top|85","p0-5|g03|top|70","p0-6|g07|top|95","p0-7|g06|top|205","p0-8|g02|top|135","p0-12|g03|top|70"],"hero":"h0-10|held_quellgeflecht|486|top|||260|false|","bookings":["c0-11|ch_schutz|top|150|13"],"new_bookings":["c0-11|ch_schutz|top|150"],"draft_roster":["p0-1|g04|top|220|false","p0-2|g06|top|205|false","p0-3|g02|top|135|false","p0-4|g09|top|85|false","p0-5|g03|top|70|false","p0-6|g07|top|95|false","p0-7|g06|top|205|false","p0-8|g02|top|135|false","p0-12|g03|top|70|true"],"draft_hero":"h0-10|held_quellgeflecht|227|top|||260|false|","boss_lane":"","undo":0},{"gold":218,"draft_gold":65,"ready":true,"earned":1763,"spent":1765,"next_seq":10,"roster":["p1-1|w04|mid|230","p1-2|w02|mid|150","p1-3|w06|mid|195","p1-4|w04|mid|230","p1-5|w07|mid|100","p1-6|w10|mid|270","p1-7|w02|mid|150"],"hero":"h1-9|held_ringborke|332|mid|||260|false|","bookings":[],"new_bookings":[],"draft_roster":["p1-1|w04|grotto|230|false","p1-2|w02|mid|150|false","p1-3|w06|grotto|195|false","p1-4|w04|grotto|230|false","p1-5|w07|mid|100|false","p1-6|w10|grotto|270|false","p1-7|w02|mid|150|false"],"draft_hero":"h1-9|held_ringborke|0|grotto|||260|true|","boss_lane":"","undo":0},{"gold":164,"draft_gold":4,"ready":true,"earned":1834,"spent":1890,"next_seq":13,"roster":["p2-1|g04|bot|220","p2-2|g02|bot|135","p2-3|g06|bot|205","p2-4|g07|bot|95","p2-5|g04|bot|220","p2-6|g09|bot|85","p2-7|g02|bot|135","p2-8|g06|bot|205","p2-10|g04|bot|220","p2-11|g01|bot|45","p2-12|g05|bot|65"],"hero":"h2-9|held_ringborke|665|bot||borkenhaut|260|false|","bookings":[],"new_bookings":[],"draft_roster":["p2-1|g04|bot|220|false","p2-2|g02|bot|135|false","p2-3|g06|bot|205|false","p2-4|g07|bot|95|false","p2-5|g04|bot|220|false","p2-6|g09|bot|85|false","p2-7|g02|bot|135|false","p2-8|g06|bot|205|false","p2-10|g04|bot|220|false","p2-11|g01|bot|45|true","p2-12|g05|bot|65|true"],"draft_hero":"h2-9|held_ringborke|319|bot||borkenhaut|260|false|","boss_lane":"","undo":0},{"gold":358,"draft_gold":8,"ready":true,"earned":2218,"spent":2080,"next_seq":13,"roster":["p3-1|w04|top|230","p3-2|w06|top|195","p3-3|w02|top|150","p3-4|w04|top|230","p3-5|w07|top|100","p3-6|w09|top|90","p3-7|w06|top|195","p3-8|w03|top|75","p3-9|w02|top|150","p3-12|w03|top|75"],"hero":"h3-10|held_ringborke|340|top|basaltschild||260|false|","bookings":["c3-11|ch_schutz|top|150|13"],"new_bookings":["c3-11|ch_schutz|top|150"],"draft_roster":["p3-1|w04|top|230|false","p3-2|w06|top|195|false","p3-3|w02|top|150|false","p3-4|w04|top|230|false","p3-5|w07|top|100|false","p3-6|w09|top|90|false","p3-7|w06|top|195|false","p3-8|w03|top|75|false","p3-9|w02|top|150|false","p3-12|w03|top|75|true"],"draft_hero":"h3-10|held_ringborke|159|top|basaltschild||260|false|basaltschild","boss_lane":"","undo":0},{"gold":390,"draft_gold":40,"ready":true,"earned":2220,"spent":2050,"next_seq":15,"roster":["p4-1|g02|mid|135","p4-2|g06|mid|205","p4-3|g03|mid|70","p4-4|g07|mid|95","p4-5|g02|mid|135","p4-6|g06|mid|205","p4-7|g02|mid|135","p4-8|g03|mid|70","p4-9|g09|mid|85","p4-10|g02|mid|135","p4-11|g05|mid|65","p4-14|g07|mid|95"],"hero":"h4-12|held_funkenlanze|889|mid|glutklinge|splitterschuss|260|false|","bookings":["c4-13|ch_belagerung|mid|180|13"],"new_bookings":["c4-13|ch_belagerung|mid|180"],"draft_roster":["p4-1|g02|mid|135|false","p4-2|g06|mid|205|false","p4-3|g03|mid|70|false","p4-4|g07|mid|95|false","p4-5|g02|mid|135|false","p4-6|g06|mid|205|false","p4-7|g02|mid|135|false","p4-8|g03|mid|70|false","p4-9|g09|mid|85|false","p4-10|g02|mid|135|false","p4-11|g05|mid|65|false","p4-14|g07|mid|95|true"],"draft_hero":"h4-12|held_funkenlanze|348|mid|glutklinge|splitterschuss|260|false|glutklinge","boss_lane":"","undo":0},{"gold":377,"draft_gold":27,"ready":true,"earned":2152,"spent":1995,"next_seq":11,"roster":["p5-1|w06|bot|195","p5-2|w04|bot|230","p5-3|w07|bot|100","p5-4|w06|bot|195","p5-5|w02|bot|150","p5-6|w09|bot|90","p5-7|w06|bot|195","p5-10|w04|bot|230"],"hero":"h5-9|held_funkenlanze|615|bot|funkenfokus|durchschlag|260|false|","bookings":[],"new_bookings":[],"draft_roster":["p5-1|w06|bot|195|false","p5-2|w04|bot|230|false","p5-3|w07|bot|100|false","p5-4|w06|bot|195|false","p5-5|w02|bot|150|false","p5-6|w09|bot|90|false","p5-7|w06|bot|195|false","p5-10|w04|bot|230|false"],"draft_hero":"h5-9|held_funkenlanze|326|bot|funkenfokus|durchschlag|260|false|funkenfokus","boss_lane":"","undo":0}],"buildings":[0.0,0.0,0.0,0.0,7024.199999999999,0.0,0.0,0.0,0.0,7500.0,3643.2949999999964,7500.0,5979.6576,0.0,0.0,9000.0,7424.6132,12000.0],"boss":{"next":16,"settled":12,"claim":"0|12|13|1|mid"},"boss_log":["12|won|0||1"],"announcements":[],"settlement":{"round":12,"gains":[138,153,160,350,350,350],"income":114,"lost":["blau_mid_inner","blau_base_1","blau_base_2","rot_bot_inner","blau_ancient"],"end_reason":"core","combat_time":87.34999999999718,"boss":"won","lane_kills":{"mid":11,"bot":12,"top":9},"xp":{"h4-12":541,"h2-9":346,"h5-9":289,"h3-10":181,"h0-10":259,"h1-9":332}},"combat":{"round":12,"steps":1747,"elapsed":87.34999999999718,"finished":true,"end_reason":"core","destroyed":[0],"grotto":"success|0|0|true","grotto_boss":"false|false|113","grotto_boss_hp":0.0,"events":88,"mobile":[5,12,0]}}],"results":[]}}} \ No newline at end of file diff --git a/Assets/Luneraria/Tests/Core/Golden/scenarios.json b/Assets/Luneraria/Tests/Core/Golden/scenarios.json new file mode 100644 index 0000000..e0621b0 --- /dev/null +++ b/Assets/Luneraria/Tests/Core/Golden/scenarios.json @@ -0,0 +1,226 @@ +{ + "about": "Golden scenarios for the rules port. The Godot reference (tools/godot-golden/golden_scenarios.gd) and the C# core (GoldenSuite) interpret the same operations; Godot writes golden.json, C# compares its own snapshots with it (docs/port/U1-RULES.md). Uid references: $last: last roster entry, $roster::, $hero:, $booking:: (new bookings of the draft).", + "scenarios": [ + {"id": "start_three_lanes", "title": "Normaler Drei-Lane-Start: sechs Bots, Aufmarsch, erste Gefechte, Abrechnung", + "ops": [ + {"op": "setup", "seed": 4, "bunds": ["wurzelbund", "wurzelbund", "glutpakt", "glutpakt", "wurzelbund", "glutpakt"]}, + {"op": "bots"}, + {"op": "snapshot", "label": "planned"}, + {"op": "begin"}, + {"op": "snapshot", "label": "spawned", "units": true, "wave": true}, + {"op": "steps", "n": 200}, + {"op": "snapshot", "label": "t10", "units": true}, + {"op": "steps", "n": 400}, + {"op": "snapshot", "label": "t30", "units": true}, + {"op": "finish"}, + {"op": "snapshot", "label": "settled", "events": true} + ]}, + {"id": "lane_outer_lost", "title": "Lane verliert äußeren Turm: Bastion wird angreifbar, Marschgrenze rückt vor", + "ops": [ + {"op": "setup", "seed": 5}, + {"op": "building", "id": "blau_top_outer", "hp": 0}, + {"op": "round", "value": 6}, + {"op": "gold", "slot": 3, "add": 900}, + {"op": "bots"}, + {"op": "begin"}, + {"op": "steps", "n": 500}, + {"op": "snapshot", "label": "t25", "units": true}, + {"op": "finish"}, + {"op": "snapshot", "label": "settled", "events": true} + ]}, + {"id": "lane_both_lost", "title": "Lane verliert beide Türme: Basistürme angreifbar", + "ops": [ + {"op": "setup", "seed": 6}, + {"op": "building", "id": "blau_bot_outer", "hp": 0}, + {"op": "building", "id": "blau_bot_inner", "hp": 0}, + {"op": "round", "value": 8}, + {"op": "gold", "slot": 5, "add": 1500}, + {"op": "bots"}, + {"op": "begin"}, + {"op": "steps", "n": 700}, + {"op": "snapshot", "label": "t35", "units": true}, + {"op": "finish"}, + {"op": "snapshot", "label": "settled", "events": true} + ]}, + {"id": "base_tower_attack", "title": "Angriff auf Basistürme durch eine starke Rot-Armee", + "ops": [ + {"op": "setup", "seed": 7}, + {"op": "building", "id": "blau_mid_outer", "hp": 0}, + {"op": "building", "id": "blau_mid_inner", "hp": 0}, + {"op": "round", "value": 12}, + {"op": "gold", "slot": 3, "add": 6000}, + {"op": "gold", "slot": 4, "add": 6000}, + {"op": "gold", "slot": 5, "add": 6000}, + {"op": "bots"}, + {"op": "begin"}, + {"op": "steps", "n": 1200}, + {"op": "snapshot", "label": "t60", "units": true}, + {"op": "finish"}, + {"op": "snapshot", "label": "settled", "events": true} + ]}, + {"id": "ancient_destruction", "title": "Ancient-Zerstörung beendet die Partie", + "ops": [ + {"op": "setup", "seed": 8}, + {"op": "building", "id": "rot_top_outer", "hp": 0}, + {"op": "building", "id": "rot_top_inner", "hp": 0}, + {"op": "building", "id": "rot_base_1", "hp": 0}, + {"op": "building", "id": "rot_base_2", "hp": 0}, + {"op": "building", "id": "rot_ancient", "hp": 900}, + {"op": "round", "value": 12}, + {"op": "gold", "slot": 0, "add": 8000}, + {"op": "gold", "slot": 1, "add": 8000}, + {"op": "gold", "slot": 2, "add": 8000}, + {"op": "bots"}, + {"op": "begin"}, + {"op": "finish"}, + {"op": "snapshot", "label": "over", "events": true} + ]}, + {"id": "high_wave_21", "title": "Hohe Welle über 20: normale Welle, stärkere Monster", + "ops": [ + {"op": "setup", "seed": 9}, + {"op": "round", "value": 21}, + {"op": "gold_all", "add": 4000}, + {"op": "bots"}, + {"op": "begin"}, + {"op": "snapshot", "label": "spawned", "units": true, "wave": true}, + {"op": "steps", "n": 400}, + {"op": "snapshot", "label": "t20", "units": true}, + {"op": "finish"}, + {"op": "snapshot", "label": "settled", "events": true} + ]}, + {"id": "high_wave_137", "title": "Hohe Welle über 100: Werte, Belohnungen und Kampf bleiben endlich", + "ops": [ + {"op": "setup", "seed": 10}, + {"op": "round", "value": 137}, + {"op": "gold_all", "add": 40000}, + {"op": "bots"}, + {"op": "begin"}, + {"op": "snapshot", "label": "spawned", "wave": true}, + {"op": "finish"}, + {"op": "snapshot", "label": "settled", "events": true} + ]}, + {"id": "hero_levels", "title": "Heldenentwicklung über Runden: Anwerben, Erfahrung, Stufen, Talente, Items (Bots)", + "ops": [ + {"op": "setup", "seed": 12}, + {"op": "play", "rounds": 9} + ]}, + {"id": "item_purchase", "title": "Itemkauf: Plätze, Einzigartigkeit, Stufe, Rückgabe, Normale Einheiten ohne Items", + "ops": [ + {"op": "setup", "seed": 21, "bunds": ["glutpakt", "wurzelbund", "glutpakt", "wurzelbund", "glutpakt", "wurzelbund"]}, + {"op": "gold", "slot": 0, "add": 5000}, + {"op": "cmd", "slot": 0, "command": {"type": "hero_buy", "hero_id": "held_ringborke"}}, + {"op": "cmd", "slot": 0, "command": {"type": "buy", "type_id": "g01"}}, + {"op": "cmd", "slot": 0, "command": {"type": "item_buy", "item_id": "glutklinge", "uid": "$last:0"}}, + {"op": "cmd", "slot": 0, "command": {"type": "item_buy", "item_id": "glutklinge", "uid": "$hero:0"}}, + {"op": "cmd", "slot": 0, "command": {"type": "item_buy", "item_id": "glutklinge"}}, + {"op": "cmd", "slot": 0, "command": {"type": "item_buy", "item_id": "kristallsplitter"}}, + {"op": "cmd", "slot": 0, "command": {"type": "item_buy", "item_id": "rankenmantel"}}, + {"op": "cmd", "slot": 0, "command": {"type": "item_buy", "item_id": "basaltschild"}}, + {"op": "cmd", "slot": 0, "command": {"type": "item_buy", "item_id": "funkenfokus"}}, + {"op": "cmd", "slot": 0, "command": {"type": "item_sell", "item_id": "basaltschild"}}, + {"op": "cmd", "slot": 0, "command": {"type": "item_buy", "item_id": "basaltschild"}}, + {"op": "snapshot", "label": "planned"}, + {"op": "begin"}, + {"op": "snapshot", "label": "spawned", "units": true}, + {"op": "finish"}, + {"op": "cmd", "slot": 0, "command": {"type": "item_sell", "item_id": "basaltschild"}}, + {"op": "cmd", "slot": 0, "command": {"type": "hero_cancel"}}, + {"op": "snapshot", "label": "after_round"} + ]}, + {"id": "attack_champion", "title": "Angriffschampion: Buchung n, öffentliche Ankündigung, Einsatz n+1, Kopfgeld, Verbrauch", + "ops": [ + {"op": "setup", "seed": 24, "bunds": ["glutpakt", "wurzelbund", "glutpakt", "wurzelbund", "glutpakt", "wurzelbund"]}, + {"op": "gold", "slot": 0, "add": 1000}, + {"op": "cmd", "slot": 0, "command": {"type": "champion_book", "champion_id": "ch_belagerung", "lane": "bot"}}, + {"op": "cmd", "slot": 0, "command": {"type": "champion_book", "champion_id": "ch_druck", "lane": "top"}}, + {"op": "cmd", "slot": 0, "command": {"type": "champion_book", "champion_id": "ch_schutz", "lane": "top"}}, + {"op": "cmd", "slot": 0, "command": {"type": "champion_cancel", "uid": "$booking:0:1"}}, + {"op": "begin"}, + {"op": "finish"}, + {"op": "snapshot", "label": "announced"}, + {"op": "cmd", "slot": 0, "command": {"type": "champion_cancel", "uid": "c0-1"}}, + {"op": "begin"}, + {"op": "snapshot", "label": "deployed", "units": true}, + {"op": "steps", "n": 600}, + {"op": "snapshot", "label": "t30", "units": true}, + {"op": "finish"}, + {"op": "snapshot", "label": "settled", "events": true}, + {"op": "begin"}, + {"op": "snapshot", "label": "consumed"}, + {"op": "finish"} + ]}, + {"id": "boss_cycle", "title": "Bossversuch erfolgreich, Anspruch, Entsendung auf gewählter Lane, Boss getötet mit Kopfgeld, dreirundige Sperre, Wiederverfügbarkeit", + "ops": [ + {"op": "setup", "seed": 26, "bunds": ["glutpakt", "wurzelbund", "glutpakt", "wurzelbund", "glutpakt", "wurzelbund"]}, + {"op": "play", "rounds": 5, "bots": false}, + {"op": "expedition", "slot": 1, "types": [1, 1, 1, 0, 2, 2, 2], "hero": "held_ringborke"}, + {"op": "begin"}, + {"op": "snapshot", "label": "expedition", "units": true}, + {"op": "finish"}, + {"op": "snapshot", "label": "won", "events": true}, + {"op": "settle_boss"}, + {"op": "cmd", "slot": 4, "command": {"type": "boss_lane", "lane": "top"}}, + {"op": "cmd", "slot": 1, "command": {"type": "boss_lane", "lane": "top"}}, + {"op": "cmd", "slot": 1, "command": {"type": "assign", "uid": "$roster:1:0", "lane": "grotto"}}, + {"op": "cmd", "slot": 1, "command": {"type": "assign", "uid": "$roster:1:0", "lane": "mid"}}, + {"op": "snapshot", "label": "announced"}, + {"op": "begin"}, + {"op": "snapshot", "label": "deployed", "units": true}, + {"op": "steps", "n": 200}, + {"op": "snapshot", "label": "marching", "units": true}, + {"op": "unit_set", "select": {"kind": "boss", "zone": "lane"}, "hp": 0}, + {"op": "steps", "n": 1}, + {"op": "finish"}, + {"op": "snapshot", "label": "boss_killed", "events": true}, + {"op": "buildings_full"}, + {"op": "snapshot", "label": "locked_r8"}, + {"op": "play", "rounds": 1, "bots": false}, + {"op": "buildings_full"}, + {"op": "snapshot", "label": "locked_r9"}, + {"op": "play", "rounds": 1, "bots": false}, + {"op": "snapshot", "label": "open_r10"}, + {"op": "begin"}, + {"op": "snapshot", "label": "no_second_deployment", "units": true}, + {"op": "finish"} + ]}, + {"id": "boss_failure", "title": "Bossversuch gescheitert: keine Belohnung, keine Sperre, Boss beim nächsten Versuch voll", + "ops": [ + {"op": "setup", "seed": 27, "bunds": ["glutpakt", "wurzelbund", "glutpakt", "wurzelbund", "glutpakt", "wurzelbund"]}, + {"op": "gold", "slot": 2, "add": 200}, + {"op": "cmd", "slot": 2, "command": {"type": "buy", "type_id": "g01"}}, + {"op": "cmd", "slot": 2, "command": {"type": "assign", "uid": "$last:2", "lane": "grotto"}}, + {"op": "begin"}, + {"op": "snapshot", "label": "attempt", "units": true}, + {"op": "finish"}, + {"op": "snapshot", "label": "failed", "events": true}, + {"op": "cmd", "slot": 2, "command": {"type": "assign", "uid": "$roster:2:0", "lane": "grotto"}}, + {"op": "begin"}, + {"op": "snapshot", "label": "second_attempt", "units": true}, + {"op": "finish"}, + {"op": "snapshot", "label": "failed_again", "events": true} + ]}, + {"id": "grotto_contested", "title": "Umkämpfte Grotte: zwei Expeditionen, Boss ruht, erwacht unberührt, Sieger erhält Anspruch", + "ops": [ + {"op": "setup", "seed": 25, "bunds": ["glutpakt", "wurzelbund", "glutpakt", "wurzelbund", "glutpakt", "wurzelbund"]}, + {"op": "expedition", "slot": 1, "types": [1, 1, 0, 2]}, + {"op": "cmd", "slot": 1, "command": {"type": "buy", "type_id": "w01"}}, + {"op": "expedition", "slot": 4, "types": [1]}, + {"op": "begin"}, + {"op": "snapshot", "label": "dormant", "units": true}, + {"op": "steps", "n": 300}, + {"op": "snapshot", "label": "t15", "units": true}, + {"op": "finish"}, + {"op": "snapshot", "label": "settled", "events": true} + ]}, + {"id": "mirror_match", "title": "Spiegelpartie: gleicher Bund und gleiches Profil auf allen Plätzen bleibt exakt symmetrisch", + "ops": [ + {"op": "setup", "seed": 3, "bunds": ["glutpakt", "glutpakt", "glutpakt", "glutpakt", "glutpakt", "glutpakt"]}, + {"op": "play", "rounds": 8, "profile": "verteidigung"} + ]}, + {"id": "bot_match_1", "title": "Vollständige Bot-Partie Seed 1 bis zum Ancient-Fall", "ops": [{"op": "setup", "seed": 1}, {"op": "play", "rounds": 60}]}, + {"id": "bot_match_2", "title": "Vollständige Bot-Partie Seed 2 bis zum Ancient-Fall", "ops": [{"op": "setup", "seed": 2}, {"op": "play", "rounds": 60}]}, + {"id": "bot_match_3", "title": "Vollständige Bot-Partie Seed 3 bis zum Ancient-Fall", "ops": [{"op": "setup", "seed": 3}, {"op": "play", "rounds": 60}]}, + {"id": "bot_match_11", "title": "Vollständige Bot-Partie Seed 11 bis zum Ancient-Fall", "ops": [{"op": "setup", "seed": 11}, {"op": "play", "rounds": 60}]}, + {"id": "bot_match_28", "title": "Vollständige Bot-Partie Seed 28 (Bots mit Helden, Champions und Grotte)", "ops": [{"op": "setup", "seed": 28, "bunds": ["glutpakt", "wurzelbund", "glutpakt", "wurzelbund", "glutpakt", "wurzelbund"]}, {"op": "play", "rounds": 60}]} + ] +} diff --git a/Assets/Luneraria/Tests/Core/GoldenReplay.cs b/Assets/Luneraria/Tests/Core/GoldenReplay.cs new file mode 100644 index 0000000..f32760c --- /dev/null +++ b/Assets/Luneraria/Tests/Core/GoldenReplay.cs @@ -0,0 +1,325 @@ +using System; +using System.Collections.Generic; +using System.Linq; + +namespace Luneraria.Core.Tests +{ + /// + /// Runs the operations of Golden/scenarios.json against the C# core and records snapshots in + /// exactly the shape tools/godot-golden/golden_scenarios.gd writes for the Godot reference. + /// + public sealed class GoldenReplay + { + public LuneMatch State; + public readonly List Snapshots = new List(); + public readonly List Results = new List(); + + public void Apply(OrderedMap op) + { + switch (MiniJson.Str(op["op"])) + { + case "setup": + { + State = new LuneMatch(); + var options = new MatchOptions { Seed = MiniJson.Int(op["seed"]), HumanSlot = op.ContainsKey("human") ? MiniJson.Int(op["human"]) : -1 }; + if (op.ContainsKey("bunds")) + options.Bunds = MiniJson.Arr(op["bunds"]).Select(MiniJson.Str).ToList(); + if (op.ContainsKey("profiles")) + options.Profiles = MiniJson.Arr(op["profiles"]).Select(MiniJson.Str).ToList(); + State.Setup(options); + break; + } + case "building": + State.BuildingHp[MiniJson.Str(op["id"])] = MiniJson.Num(op["hp"]); + break; + case "buildings_full": + foreach (BuildingDef definition in State.Map.Buildings) + State.BuildingHp[definition.Id] = definition.MaxHp; + break; + case "round": + State.RoundNumber = MiniJson.Int(op["value"]); + break; + case "gold": + State.Players[MiniJson.Int(op["slot"])].Draft.Gold += MiniJson.Int(op["add"]); + break; + case "gold_all": + foreach (Player player in State.Players) + player.Draft.Gold += MiniJson.Int(op["add"]); + break; + case "cmd": + { + int slot = MiniJson.Int(op["slot"]); + Command command = Resolve(MiniJson.Obj(op["command"])); + CommandResult result = State.Submit(slot, command); + Results.Add(new List { "cmd", (long)slot, command.Type, result.Ok, result.Message }); + break; + } + case "bots": + for (int slot = 0; slot < 6; slot++) + LuneBot.Plan(State, slot, op.ContainsKey("profile") ? MiniJson.Str(op["profile"]) : ""); + break; + case "begin": + Results.Add(new List { "begin", -1L, "", State.BeginCombat(), "" }); + break; + case "steps": + for (int i = 0; i < MiniJson.Int(op["n"]); i++) + { + if (State.Phase != Phase.Combat) + break; + State.StepCombat(); + } + break; + case "finish": + State.FinishCombat(); + break; + case "unit_set": + { + var select = MiniJson.Obj(op["select"]); + foreach (LuneUnit unit in State.Combat.Units) + { + if (select.ContainsKey("kind") && unit.Kind != MiniJson.Str(select["kind"])) + continue; + if (select.ContainsKey("zone") && unit.Zone != MiniJson.Str(select["zone"])) + continue; + if (select.ContainsKey("team") && unit.Team != MiniJson.Int(select["team"])) + continue; + if (op.ContainsKey("hp")) + unit.Hp = MiniJson.Num(op["hp"]); + } + break; + } + case "settle_boss": + Results.Add(new List { "settle_boss", -1L, "", true, State.SettleBoss() }); + break; + case "expedition": + { + int slot = MiniJson.Int(op["slot"]); + State.Players[slot].Draft.Gold += 6000; + List ids = State.BaseIds(State.Players[slot].Bund); + foreach (object typeIndex in MiniJson.Arr(op["types"])) + { + Record(slot, Command.Buy(ids[MiniJson.Int(typeIndex)])); + RosterEntry entry = State.Players[slot].Draft.Roster[State.Players[slot].Draft.Roster.Count - 1]; + Record(slot, Command.Upgrade(entry.Uid)); + Record(slot, Command.Assign(entry.Uid, "grotto")); + } + if (op.ContainsKey("hero")) + { + Record(slot, Command.HeroBuy(MiniJson.Str(op["hero"]))); + Record(slot, Command.Assign(State.Players[slot].Draft.Hero.Uid, "grotto")); + } + break; + } + case "play": + { + bool bots = !op.ContainsKey("bots") || (bool)op["bots"]; + string profile = op.ContainsKey("profile") ? MiniJson.Str(op["profile"]) : ""; + for (int i = 0; i < MiniJson.Int(op["rounds"]); i++) + { + if (State.Phase == Phase.Over) + break; + if (bots) + { + for (int slot = 0; slot < 6; slot++) + LuneBot.Plan(State, slot, profile); + } + int fought = State.RoundNumber; + State.BeginCombat(); + State.FinishCombat(); + var label = new OrderedMap(); + label["label"] = "round-" + fought; + Snapshot(label); + } + break; + } + case "snapshot": + Snapshot(op); + break; + default: + throw new InvalidOperationException("unknown op " + MiniJson.Str(op["op"])); + } + } + + void Record(int slot, Command command) + { + CommandResult result = State.Submit(slot, command); + Results.Add(new List { "cmd", (long)slot, command.Type, result.Ok, result.Message }); + } + + Command Resolve(OrderedMap source) + { + var command = new Command { Type = MiniJson.Str(source["type"]) }; + foreach (KeyValuePair pair in source) + { + switch (pair.Key) + { + case "type_id": command.TypeId = MiniJson.Str(pair.Value); break; + case "lane": command.Lane = MiniJson.Str(pair.Value); break; + case "uid": command.Uid = ResolveUid(MiniJson.Str(pair.Value)); break; + case "hero_id": command.HeroId = MiniJson.Str(pair.Value); break; + case "item_id": command.ItemId = MiniJson.Str(pair.Value); break; + case "champion_id": command.ChampionId = MiniJson.Str(pair.Value); break; + case "tier": command.Tier = MiniJson.Int(pair.Value); break; + case "choice": command.Choice = MiniJson.Int(pair.Value); break; + } + } + return command; + } + + string ResolveUid(string uid) + { + if (!uid.StartsWith("$", StringComparison.Ordinal)) + return uid; + string[] parts = uid.Substring(1).Split(':'); + Player owner = State.Players[int.Parse(parts[1])]; + switch (parts[0]) + { + case "last": return owner.Draft.Roster[owner.Draft.Roster.Count - 1].Uid; + case "roster": return owner.Draft.Roster[int.Parse(parts[2])].Uid; + case "hero": return owner.Draft.Hero.Uid; + case "booking": return owner.Draft.NewBookings[int.Parse(parts[2])].Uid; + } + return uid; + } + + // ---------------------------------------------------------------- snapshot (same shape as the Godot tool) + static string Bool(bool value) { return value ? "true" : "false"; } + + void Snapshot(OrderedMap op) + { + var players = new List(); + foreach (Player player in State.Players) + { + var entry = new OrderedMap(); + entry["gold"] = (long)player.Gold; + entry["draft_gold"] = (long)player.Draft.Gold; + entry["ready"] = player.Ready; + entry["earned"] = (long)player.Earned; + entry["spent"] = (long)player.Spent; + entry["next_seq"] = (long)player.NextSeq; + entry["roster"] = Roster(player.Roster, false); + entry["hero"] = Hero(player.Hero); + entry["bookings"] = player.Bookings.Select(b => (object)(b.Uid + "|" + b.ChampionId + "|" + b.Lane + "|" + b.Cost + "|" + b.DeployRound)).ToList(); + entry["new_bookings"] = player.Draft.NewBookings.Select(b => (object)(b.Uid + "|" + b.ChampionId + "|" + b.Lane + "|" + b.Cost)).ToList(); + entry["draft_roster"] = Roster(player.Draft.Roster, true); + entry["draft_hero"] = Hero(player.Draft.Hero); + entry["boss_lane"] = player.Draft.BossLane; + entry["undo"] = (long)player.Undo.Count; + players.Add(entry); + } + var snap = new OrderedMap(); + snap["label"] = MiniJson.Str(op["label"]); + snap["phase"] = (long)(int)State.Phase; + snap["round"] = (long)State.RoundNumber; + snap["winner"] = (long)State.Winner; + snap["end_note"] = State.EndNote; + snap["players"] = players; + snap["buildings"] = State.Map.Buildings.Select(d => (object)State.BuildingHp[d.Id]).ToList(); + var boss = new OrderedMap(); + boss["next"] = (long)State.Boss.NextAvailableRound; + boss["settled"] = (long)State.Boss.SettledRound; + BossClaim claim = State.Boss.Claim; + boss["claim"] = claim == null ? "" : claim.Team + "|" + claim.WonRound + "|" + claim.DeployRound + "|" + claim.ChooserSlot + "|" + claim.Lane; + snap["boss"] = boss; + snap["boss_log"] = State.BossLog.Select(e => (object)(e.Round + "|" + e.Event + "|" + e.Team + "|" + e.Lane + "|" + e.Chooser)).ToList(); + snap["announcements"] = State.Announcements().Select(a => (object)(a.Kind + "|" + a.Team + "|" + a.Slot + "|" + a.Lane + "|" + a.ChampionId + "|" + a.Bounty)).ToList(); + snap["settlement"] = SettlementSnapshot(); + snap["combat"] = CombatSnapshot(); + if (op.ContainsKey("units") && (bool)op["units"] && State.Combat != null) + snap["units"] = State.Combat.Units.Select(u => (object)UnitSnapshot(u)).ToList(); + if (op.ContainsKey("events") && (bool)op["events"] && State.Combat != null) + { + snap["events"] = State.Combat.Events.Select(e => (object)new List { (long)e.Serial, (long)e.Step, e.Time, (long)e.Team, e.Lane, e.Zone, e.Kind, + (long)e.UnitId, e.DefId, (long)e.Bounty, e.BuildingId, (long)e.Xp, e.XpHeroes.Select(h => (object)h).ToList() }).ToList(); + } + if (op.ContainsKey("wave") && (bool)op["wave"]) + snap["wave"] = LuneWaves.Build(State.Balance, State.RoundNumber).Select(m => (object)new List { m.Id, m.MaxHp, m.Damage, (long)m.Bounty }).ToList(); + Snapshots.Add(snap); + } + + static List Roster(List roster, bool withFresh) + { + return roster.Select(e => (object)(e.Uid + "|" + e.TypeId + "|" + e.Lane + "|" + e.Invested + (withFresh ? "|" + Bool(e.Fresh) : ""))).ToList(); + } + + static string Hero(HeroState hero) + { + if (hero == null) + return ""; + return hero.Uid + "|" + hero.HeroId + "|" + hero.Xp + "|" + hero.Lane + "|" + string.Join("+", hero.Items) + "|" + string.Join("+", hero.Talents) + "|" + + hero.Invested + "|" + Bool(hero.Fresh) + "|" + string.Join("+", hero.FreshItems); + } + + object SettlementSnapshot() + { + Settlement s = State.LastSettlement; + if (s == null) + return null; + var result = new OrderedMap(); + result["round"] = (long)s.Round; + result["gains"] = s.Gains.Select(g => (object)(long)g).ToList(); + result["income"] = (long)s.Income; + result["lost"] = s.BuildingsLost.Select(b => (object)b).ToList(); + result["end_reason"] = s.EndReason; + result["combat_time"] = s.CombatTime; + result["boss"] = s.Boss; + var laneKills = new OrderedMap(); + foreach (KeyValuePair pair in s.LaneKills) + laneKills[pair.Key] = (long)pair.Value; + result["lane_kills"] = laneKills; + var xp = new OrderedMap(); + foreach (KeyValuePair pair in s.Xp) + xp[pair.Key] = (long)pair.Value; + result["xp"] = xp; + return result; + } + + object CombatSnapshot() + { + LuneCombat c = State.Combat; + if (c == null) + return null; + var result = new OrderedMap(); + result["round"] = (long)c.RoundNumber; + result["steps"] = (long)c.Steps; + result["elapsed"] = c.Elapsed; + result["finished"] = c.Finished; + result["end_reason"] = c.EndReason; + result["destroyed"] = c.DestroyedCores.Select(t => (object)(long)t).ToList(); + result["grotto"] = c.GrottoOutcome + "|" + c.GrottoClaimTeam + "|" + c.GrottoActiveTeam + "|" + Bool(c.GrottoResolved); + result["grotto_boss"] = c.GrottoBoss == null ? "" : Bool(c.GrottoBoss.Alive) + "|" + Bool(c.GrottoBoss.Dormant) + "|" + c.GrottoBoss.Id; + result["grotto_boss_hp"] = c.GrottoBoss != null ? c.GrottoBoss.Hp : 0.0; + result["events"] = (long)c.Events.Count; + result["mobile"] = new List { (long)c.MobileCount(0), (long)c.MobileCount(1), (long)c.MobileCount(2) }; + return result; + } + + static OrderedMap UnitSnapshot(LuneUnit unit) + { + var result = new OrderedMap(); + result["id"] = (long)unit.Id; + result["kind"] = unit.Kind; + result["team"] = (long)unit.Team; + result["lane"] = unit.Lane; + result["zone"] = unit.Zone; + result["slot"] = (long)unit.OwnerSlot; + result["uid"] = unit.PersistentUid; + result["def"] = unit.Def.Id; + result["alive"] = unit.Alive; + result["hp"] = unit.Hp; + result["max_hp"] = unit.MaxHp; + result["shield"] = unit.Shield; + result["x"] = (double)unit.Position.X; + result["y"] = (double)unit.Position.Y; + result["facing"] = unit.Facing; + result["progress"] = unit.Progress; + result["target"] = (long)(unit.Target != null ? unit.Target.Id : -1); + result["hits"] = (long)unit.HitCount; + result["reached"] = unit.ReachedBase; + result["dormant"] = unit.Dormant; + result["effects"] = unit.Effects.Select(p => (object)new List { p.Key, p.Value.Kind, p.Value.Amount, p.Value.Remaining }).ToList(); + result["dots"] = unit.Dots.Select(p => (object)new List { p.Key, p.Value.Damage, p.Value.Remaining, p.Value.NextTick, (long)p.Value.AttackType }).ToList(); + return result; + } + } +} diff --git a/Assets/Luneraria/Tests/Core/GoldenSuite.Compare.cs b/Assets/Luneraria/Tests/Core/GoldenSuite.Compare.cs new file mode 100644 index 0000000..285400a --- /dev/null +++ b/Assets/Luneraria/Tests/Core/GoldenSuite.Compare.cs @@ -0,0 +1,156 @@ +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; + +namespace Luneraria.Core.Tests +{ + /// + /// Golden replays: every scenario of Golden/scenarios.json runs on the C# core and each + /// snapshot is compared with the Godot reference (Golden/golden.json) field by field. + /// Integers, strings, flags, ids, ownership, purchases, targets and results must be equal; + /// numbers that pass through floating point use the tolerances below (docs/port/U1-RULES.md). + /// The largest deviation per category is noted in the report. + /// + public sealed partial class GoldenSuite + { + /// Tolerance categories: hit points (absolute, 0.01 HP or 1e-9 relative), positions and lane progress (1 mm), angles, times, effects. + static readonly Dictionary Tolerances = new Dictionary + { + { "hp", 0.01 }, { "position", 0.001 }, { "angle", 0.0001 }, { "time", 0.000001 }, { "effect", 0.000001 }, { "other", 0.000001 }, + }; + + readonly Dictionary _worst = new Dictionary(); + readonly Dictionary _counts = new Dictionary(); + int _compared; + + partial void RunScenarios() + { + var spec = MiniJson.Obj(MiniJson.Parse(File.ReadAllText(Path.Combine(GoldenDirectory, "scenarios.json")))); + var golden = MiniJson.Obj(MiniJson.Obj(MiniJson.Parse(File.ReadAllText(Path.Combine(GoldenDirectory, "golden.json"))))["scenarios"]); + foreach (object item in MiniJson.Arr(spec["scenarios"])) + { + var scenario = MiniJson.Obj(item); + string id = MiniJson.Str(scenario["id"]); + object reference; + if (!golden.TryGetValue(id, out reference)) + { + Check(false, id + ": no golden reference (run tools/godot-golden/run_golden.sh)"); + continue; + } + var replay = new GoldenReplay(); + foreach (object op in MiniJson.Arr(scenario["ops"])) + replay.Apply(MiniJson.Obj(op)); + var expected = MiniJson.Obj(reference); + List expectedSnapshots = MiniJson.Arr(expected["snapshots"]); + Check(expectedSnapshots.Count == replay.Snapshots.Count, string.Format("{0}: {1} snapshots like the reference ({2})", id, replay.Snapshots.Count, expectedSnapshots.Count)); + for (int i = 0; i < Math.Min(expectedSnapshots.Count, replay.Snapshots.Count); i++) + { + var problems = new List(); + string label = MiniJson.Str(MiniJson.Obj(expectedSnapshots[i])["label"]); + CompareValue(id + "/" + label, "", expectedSnapshots[i], replay.Snapshots[i], problems); + Check(problems.Count == 0, id + "/" + label + " matches the reference" + (problems.Count > 0 ? ": " + problems.Count + " differences, first " + string.Join("; ", problems.Take(6)) : "")); + } + var results = new List(); + CompareValue(id + "/results", "results", expected["results"], replay.Results, results); + Check(results.Count == 0, id + ": command results and messages match the reference" + (results.Count > 0 ? ": " + string.Join("; ", results.Take(6)) : "")); + } + Note(string.Format("golden values compared: {0}", _compared)); + foreach (KeyValuePair pair in _worst.OrderBy(p => p.Key)) + Note(string.Format("largest deviation {0}: {1:E2} over {2} values (tolerance {3:E0})", pair.Key, pair.Value, _counts[pair.Key], Tolerances[pair.Key])); + } + + static string Category(string key) + { + switch (key) + { + case "hp": + case "max_hp": + case "shield": + case "grotto_boss_hp": + case "buildings": + return "hp"; + case "x": + case "y": + case "progress": + return "position"; + case "facing": + return "angle"; + case "elapsed": + case "combat_time": + case "events": + return "time"; + case "effects": + case "dots": + return "effect"; + } + return "other"; + } + + void CompareValue(string path, string key, object expected, object actual, List problems) + { + if (expected == null || actual == null) + { + if (expected != actual) + problems.Add(path + ": " + Show(expected) + " != " + Show(actual)); + return; + } + if (IsNumber(expected) && IsNumber(actual)) + { + _compared++; + if (expected is long el && actual is long al) + { + if (el != al) + problems.Add(path + ": " + el + " != " + al); + return; + } + double e = MiniJson.Num(expected); + double a = MiniJson.Num(actual); + string category = Category(key); + double deviation = Math.Abs(e - a); + double tolerance = Math.Max(Tolerances[category], 1e-9 * Math.Abs(e)); + double worst; + if (!_worst.TryGetValue(category, out worst) || deviation > worst) + _worst[category] = deviation; + int count; + _counts.TryGetValue(category, out count); + _counts[category] = count + 1; + if (deviation > tolerance || double.IsNaN(a) != double.IsNaN(e)) + problems.Add(string.Format("{0}: {1:R} != {2:R}", path, e, a)); + return; + } + if (expected is OrderedMap em && actual is OrderedMap am) + { + if (!em.Keys.SequenceEqual(am.Keys)) + problems.Add(path + ": keys " + string.Join(",", em.Keys) + " != " + string.Join(",", am.Keys)); + foreach (KeyValuePair pair in em) + { + object other; + if (am.TryGetValue(pair.Key, out other)) + CompareValue(path + "." + pair.Key, pair.Key, pair.Value, other, problems); + } + return; + } + if (expected is List list && actual is List otherList) + { + if (list.Count != otherList.Count) + { + problems.Add(path + ": " + list.Count + " entries != " + otherList.Count); + return; + } + for (int i = 0; i < list.Count; i++) + CompareValue(path + "[" + i + "]", key, list[i], otherList[i], problems); + return; + } + _compared++; + if (!Equals(Normalize(expected), Normalize(actual))) + problems.Add(path + ": " + Show(expected) + " != " + Show(actual)); + } + + static bool IsNumber(object value) { return value is long || value is double; } + + static object Normalize(object value) { return value is bool b ? (object)b : MiniJson.Str(value); } + + static string Show(object value) { return value == null ? "null" : "'" + MiniJson.Str(value) + "'"; } + } +} diff --git a/Assets/Luneraria/Tests/Core/GoldenSuite.cs b/Assets/Luneraria/Tests/Core/GoldenSuite.cs new file mode 100644 index 0000000..2163119 --- /dev/null +++ b/Assets/Luneraria/Tests/Core/GoldenSuite.cs @@ -0,0 +1,15 @@ +namespace Luneraria.Core.Tests +{ + /// Golden replays against the Godot reference (implemented with the scenario files). + public sealed partial class GoldenSuite : CheckSuite + { + public override string Name { get { return "golden"; } } + + protected override void RunChecks() + { + RunScenarios(); + } + + partial void RunScenarios(); + } +} diff --git a/Assets/Luneraria/Tests/Core/Luneraria.Core.Tests.asmdef b/Assets/Luneraria/Tests/Core/Luneraria.Core.Tests.asmdef new file mode 100644 index 0000000..281adef --- /dev/null +++ b/Assets/Luneraria/Tests/Core/Luneraria.Core.Tests.asmdef @@ -0,0 +1,24 @@ +{ + "name": "Luneraria.Core.Tests", + "rootNamespace": "Luneraria.Core.Tests", + "references": [ + "Luneraria.Core", + "UnityEngine.TestRunner", + "UnityEditor.TestRunner" + ], + "includePlatforms": [ + "Editor" + ], + "excludePlatforms": [], + "allowUnsafeCode": false, + "overrideReferences": true, + "precompiledReferences": [ + "nunit.framework.dll" + ], + "autoReferenced": false, + "defineConstraints": [ + "UNITY_INCLUDE_TESTS" + ], + "versionDefines": [], + "noEngineReferences": false +} diff --git a/Assets/Luneraria/Tests/Core/M2RulesSuite.cs b/Assets/Luneraria/Tests/Core/M2RulesSuite.cs new file mode 100644 index 0000000..e7d51d2 --- /dev/null +++ b/Assets/Luneraria/Tests/Core/M2RulesSuite.cs @@ -0,0 +1,383 @@ +using System; +using System.Collections.Generic; +using System.Linq; + +namespace Luneraria.Core.Tests +{ + /// + /// Port of tests/luneraria/test_lune_m2.gd (73 checks in Godot): heroes (XP, talents, three + /// item slots), attack champions (book n, fight n + 1) and the boss grotto (contest, failure, + /// success, one deployment, lock, bounty). Gold granted below is a fixture on drafts only. + /// The Godot check "legacy phase, workers and sparks stay untouched" referred to Saumwacht + /// autoloads that do not exist in the port; it checks here that the core has no such types. + /// + public sealed class M2RulesSuite : CheckSuite + { + public override string Name { get { return "m2"; } } + + static LuneMatch NewMatch(int seed = 21) + { + var state = new LuneMatch(); + state.Setup(new MatchOptions { Seed = seed, HumanSlot = -1, Bunds = new List { "glutpakt", "wurzelbund", "glutpakt", "wurzelbund", "glutpakt", "wurzelbund" } }); + return state; + } + + static void Grant(LuneMatch state, int slot, int gold) + { + state.Players[slot].Draft.Gold += gold; + } + + static void RunRound(LuneMatch state, Action planner = null) + { + if (planner != null) + planner(state); + state.BeginCombat(); + state.FinishCombat(); + } + + protected override void RunChecks() + { + TestHeroesAndItems(); + TestXpAndPersistence(); + TestChampions(); + TestGrottoWithdrawalAndContest(); + TestBossSuccessLockAndDeployment(); + TestBossFailureRestores(); + TestBotsM2(); + TestNoLegacyEconomy(); + TestLaneLoss(); + } + + void TestHeroesAndItems() + { + LuneMatch state = NewMatch(); + Grant(state, 0, 5000); + int gold = state.GoldOf(0); + Check(state.Submit(0, Command.HeroBuy("held_ringborke")).Ok && state.GoldOf(0) == gold - 260, "hero costs exactly 260"); + Check(!state.Submit(0, Command.HeroBuy("held_funkenlanze")).Ok, "only one active hero per player"); + state.Submit(0, Command.Buy("g01")); + string troopUid = state.Players[0].Draft.Roster[0].Uid; + Check(!state.Submit(0, Command.ItemBuy("glutklinge", troopUid)).Ok, "normal troops carry no items"); + Check(typeof(RosterEntry).GetField("Items") == null, "troop entries have no inventory"); + string heroUid = state.Players[0].Draft.Hero.Uid; + Check(state.Submit(0, Command.ItemBuy("glutklinge", heroUid)).Ok, "hero buys an item"); + Check(!state.Submit(0, Command.ItemBuy("glutklinge")).Ok, "items are unique per hero"); + Check(!state.Submit(0, Command.ItemBuy("kristallsplitter")).Ok, "item requirement (level 3) enforced"); + Check(state.Submit(0, Command.ItemBuy("rankenmantel")).Ok && state.Submit(0, Command.ItemBuy("basaltschild")).Ok, "second and third slot"); + Check(!state.Submit(0, Command.ItemBuy("funkenfokus")).Ok, "three item slots at most"); + Check(!state.Submit(0, Command.Talent(0, 0)).Ok, "talent needs hero level 3"); + UnitDef definition = LuneContent.HeroDefinition(state.Players[0].Draft.Hero); + Check(GdMath.IsEqualApprox(definition.MaxHp, 2200.0 + 350.0) && GdMath.IsEqualApprox(definition.DamageBonus, 0.18) && GdMath.IsEqualApprox(definition.ReductionBonus, 0.10), "item bonuses stack into the hero definition"); + int goldBeforeSell = state.GoldOf(0); + state.Submit(0, Command.ItemSell("basaltschild")); + Check(state.GoldOf(0) == goldBeforeSell + 180, "item bought this planning refunds fully"); + state.Submit(0, Command.ItemBuy("basaltschild")); + state.BeginCombat(); + state.FinishCombat(); + HeroState hero = state.Players[0].Hero; + Check(hero.Items.SequenceEqual(new[] { "glutklinge", "rankenmantel", "basaltschild" }), "items persist after the round"); + goldBeforeSell = state.GoldOf(0); + state.Submit(0, Command.ItemSell("basaltschild")); + Check(state.GoldOf(0) == goldBeforeSell + 90, "committed item sells for 50 %"); + Check(!state.Submit(0, Command.HeroCancel()).Ok, "committed hero cannot be returned for gold"); + // Caps: two reduction sources plus a talent stay capped at 35 %. + var probe = new LuneUnit(); + probe.Def = new UnitDef { ReductionBonus = 0.40, Ability = "" }; + Check(GdMath.IsEqualApprox(probe.DamageReduction(), 0.35), "damage reduction capped at 35 %"); + probe.Def = new UnitDef { AttackSpeedBonus = 0.9 }; + Check(probe.AttackSpeedFactor() <= 1.5 + 0.0001, "attack tempo capped at +50 %"); + } + + void TestXpAndPersistence() + { + LuneMatch state = NewMatch(22); + Grant(state, 1, 3000); + state.Submit(1, Command.HeroBuy("held_quellgeflecht")); + for (int i = 0; i < 3; i++) + state.Submit(1, Command.Buy("w03")); + string heroUid = state.Players[1].Draft.Hero.Uid; + state.BeginCombat(); + LuneUnit spawned = state.Combat.Units.FirstOrDefault(u => u.PersistentUid == heroUid); + Check(spawned != null && spawned.Kind == "hero" && spawned.Lane == "mid", "hero fights on its lane as its own kind"); + state.FinishCombat(); + int participation = LuneContent.XpParticipation + LuneContent.XpPerRound * 1; + int xp = state.Players[1].Hero.Xp; + Check(xp > participation, string.Format("supporting hero near fights earns more than participation XP ({0} > {1})", xp, participation)); + // Kills are not needed: a hero far away from any death still earns the participation share. + LuneMatch lonely = NewMatch(23); + Grant(lonely, 0, 3000); + lonely.Submit(0, Command.HeroBuy("held_funkenlanze")); + lonely.BeginCombat(); + foreach (LuneUnit unit in lonely.Combat.Units) + { + if (unit.Kind == "hero") + unit.Position = new Vec2(-34.0, -34.0); + } + lonely.FinishCombat(); + Check(lonely.Players[0].Hero.Xp >= participation, "participation XP without any kill"); + // Level, talent and persistence across rounds. + state.Players[1].Hero.Xp = 290; + state.Players[1].Draft = state.Snapshot(state.Players[1]); + Check(LuneContent.LevelFor(290) == 3 && state.Submit(1, Command.Talent(0, 1)).Ok, "talent tier 1 at level 3"); + Check(!state.Submit(1, Command.Talent(0, 0)).Ok, "talent choice is final"); + Check(!state.Submit(1, Command.Talent(1, 0)).Ok, "tier 2 needs level 6"); + state.BeginCombat(); + bool healthy = false; + bool talentLive = false; + foreach (LuneUnit unit in state.Combat.Units) + { + if (unit.PersistentUid == heroUid) + { + healthy = unit.Hp == unit.MaxHp && unit.Def.Level == 3; + talentLive = unit.HasTalent("weite_quelle"); + unit.Hp = 0.0; + } + } + state.FinishCombat(); + Check(healthy && talentLive, "hero starts healed with level and talent"); + Check(state.Players[1].Hero.Talents.SequenceEqual(new[] { "weite_quelle" }) && state.Players[1].Hero.Xp >= 290, "hero keeps XP and talents after dying"); + LuneMatch fresh = NewMatch(22); + Check(fresh.Players[1].Hero == null && fresh.Players[1].Roster.Count == 0, "new match starts without heroes or XP"); + } + + void TestChampions() + { + LuneMatch state = NewMatch(24); + Grant(state, 0, 1000); + int gold = state.GoldOf(0); + Check(state.Submit(0, Command.ChampionBook("ch_belagerung", "bot")).Ok && state.GoldOf(0) == gold - 180, "booking costs the champion price"); + string bookingUid = state.Players[0].Draft.NewBookings[0].Uid; + state.Submit(0, Command.ChampionBook("ch_druck", "top")); + Check(!state.Submit(0, Command.ChampionBook("ch_schutz", "top")).Ok, "at most two bookings per round"); + state.Submit(0, Command.ChampionCancel(state.Players[0].Draft.NewBookings[1].Uid)); + Check(state.Players[0].Draft.NewBookings.Count == 1, "fresh booking can be cancelled"); + state.BeginCombat(); + int inRoundOne = state.Combat.Units.Count(u => u.Kind == "champion"); + Check(inRoundOne == 0, "a booking never fights in the round it was bought"); + state.FinishCombat(); + Check(state.RoundNumber == 2 && state.Announcements().Any(a => a.Kind == "champion" && a.Lane == "bot" && a.Team == 0), "booking is announced publicly for round 2"); + Check(!state.Submit(0, Command.ChampionCancel(bookingUid)).Ok, "committed booking cannot be moved or refunded"); + state.BeginCombat(); + List champions = state.Combat.Units.FindAll(u => u.Kind == "champion"); + Check(champions.Count == 1 && champions[0].Team == 0 && champions[0].Lane == "bot" && champions[0].Def.ChampionId == "ch_belagerung", "round 2 fields the champion for Blau on Bottom"); + // Kill it for a clean bounty check. + LuneUnit champion = champions[0]; + champion.Hp = 0.0; + state.Combat.Step(); + int bounty = LuneContent.ChampionBounty + LuneContent.ChampionBountyPerRound * 2; + List events = state.Combat.Events.FindAll(e => e.Kind == "champion"); + Check(events.Count == 1 && events[0].Bounty == bounty, "champion death recorded once with its bounty"); + state.FinishCombat(); + int rotGain = 0; + for (int slot = 3; slot < 6; slot++) + rotGain += state.LastSettlement.Gains[slot]; + Check(rotGain >= bounty, "defenders receive the champion bounty"); + Check(state.Players[0].Bookings.Count == 0, "champion is consumed after its round"); + state.BeginCombat(); + Check(state.Combat.Units.All(u => u.Kind != "champion"), "no champion in round 3"); + state.FinishCombat(); + // Siege focus: a siege champion next to a tower and a monster attacks the tower. + var map = new LuneMap(); + var combat = new LuneCombat(map, LuneBalance.Default(), 1); + LuneUnit tower = combat.AddBuilding(map.BuildingDef("rot_mid_outer"), 6000.0); + LuneUnit siege = combat.Spawn("champion", 0, "mid", LuneContent.ChampionDefinition("ch_belagerung", 1, LuneBalance.Default()), 1.0, 0.0); + siege.Position = tower.Position + new Vec2(-3.0, 0.0); + LuneUnit monster = combat.Spawn("monster", 1, "mid", DataCatalog.GetEnemy("e01"), 1.0, 0.0); + monster.Position = siege.Position + new Vec2(-1.5, 0.0); + // Targetless units search on their staggered step; four steps cover every offset. + for (int i = 0; i < LuneCombat.Retarget; i++) + combat.Step(); + Check(siege.Target == tower, "siege champion prefers the attackable tower"); + } + + static void Expedition(LuneMatch state, int slot, int[] types, string hero = "") + { + Grant(state, slot, 6000); + List ids = state.BaseIds(state.Players[slot].Bund); + foreach (int typeIndex in types) + { + state.Submit(slot, Command.Buy(ids[typeIndex])); + RosterEntry entry = state.Players[slot].Draft.Roster[state.Players[slot].Draft.Roster.Count - 1]; + state.Submit(slot, Command.Upgrade(entry.Uid)); + state.Submit(slot, Command.Assign(entry.Uid, "grotto")); + } + if (hero.Length > 0) + { + state.Submit(slot, Command.HeroBuy(hero)); + state.Submit(slot, Command.Assign(state.Players[slot].Draft.Hero.Uid, "grotto")); + } + } + + void TestGrottoWithdrawalAndContest() + { + LuneMatch state = NewMatch(25); + Expedition(state, 1, new[] { 1, 1, 0, 2 }); + state.Submit(1, Command.Buy("w01")); + Expedition(state, 4, new[] { 1 }); + state.BeginCombat(); + List grottoUnits = state.Combat.Units.FindAll(u => u.Zone == "grotto" && u.Team != 2); + List midTroops = state.Combat.Units.FindAll(u => u.Kind == "troop" && u.Team == 0 && u.Lane == "mid"); + Check(grottoUnits.Count == 5 && midTroops.Count == 1, "grotto troops leave the Mid lane (4 in grotto for Blau, 1 on Mid)"); + Check(state.Combat.GrottoBoss != null && state.Combat.GrottoBoss.Dormant, "boss waits while two expeditions are present"); + double bossHp = state.Combat.GrottoBoss.Hp; + int wokeStep = -1; + bool zonesStable = true; + while (state.Phase == Phase.Combat) + { + state.Combat.Step(); + foreach (LuneUnit unit in grottoUnits) + zonesStable = zonesStable && unit.Zone == "grotto"; + if (wokeStep < 0 && !state.Combat.GrottoBoss.Dormant) + { + wokeStep = state.Combat.Steps; + bool rotAlive = state.Combat.Units.Any(u => u.Alive && u.Zone == "grotto" && u.Team == 1); + Check(!rotAlive && GdMath.IsEqualApprox(state.Combat.GrottoBoss.Hp, bossHp), "boss wakes untouched once only one expedition survives"); + } + if (state.Combat.Finished) + state.Settle(); + } + Check(wokeStep > 0 && zonesStable, "expedition stays in the grotto for the whole combat phase"); + } + + void TestBossSuccessLockAndDeployment() + { + LuneMatch state = NewMatch(26); + for (int i = 0; i < 5; i++) + RunRound(state); + Check(state.RoundNumber == 6, "reached round 6"); + Expedition(state, 1, new[] { 1, 1, 1, 0, 2, 2, 2 }, "held_ringborke"); + state.BeginCombat(); + state.FinishCombat(); + Check(state.LastSettlement.Boss == "won", "strong expedition conquers the boss in round 6"); + BossClaim claim = state.Boss.Claim; + Check(claim != null && claim.Team == 0 && claim.WonRound == 6 && claim.DeployRound == 7 && claim.ChooserSlot == 1 && claim.Lane == "mid", "claim for Blau: deploy in 7, chooser is the contributing Mid player"); + Check(state.Boss.NextAvailableRound == 10, "grotto available again from round 10"); + string repeated = state.SettleBoss(); + Check(repeated == "repeat" && state.Boss.NextAvailableRound == 10 && state.Boss.Claim != null && state.Boss.Claim.DeployRound == 7, "repeating the settlement signal creates no second claim and keeps the first"); + Check(state.Announcements().Any(a => a.Kind == "boss" && a.Team == 0 && a.Lane == "mid"), "deployment announced with lane in the next planning"); + Check(!state.Submit(4, Command.BossLaneChoice("top")).Ok && !state.Submit(0, Command.BossLaneChoice("top")).Ok, "only the chooser may redirect the boss"); + Check(state.Submit(1, Command.BossLaneChoice("top")).Ok, "chooser redirects the boss to Top"); + string entryUid = state.Players[1].Roster[0].Uid; + Check(!state.Submit(1, Command.Assign(entryUid, "grotto")).Ok, "grotto locked in round 7"); + state.Submit(1, Command.Assign(entryUid, "mid")); + state.BeginCombat(); + List bosses = state.Combat.Units.FindAll(u => u.Kind == "boss"); + Check(bosses.Count == 1 && bosses[0].Team == 0 && bosses[0].Lane == "top" && bosses[0].Zone == "lane", "round 7: exactly one boss marches for Blau on Top"); + double startProgress = bosses[0].Progress; + for (int i = 0; i < 200; i++) + state.Combat.Step(); + Check(bosses[0].Progress > startProgress + 5.0 || !bosses[0].Alive, "the boss advances towards Rot's Ancient"); + bosses[0].Hp = 0.0; + state.Combat.Step(); + int bounty = LuneContent.BossBounty + LuneContent.BossBountyPerRound * 7; + state.FinishCombat(); + int[] gains = state.LastSettlement.Gains; + bool rotBossPart = gains[3] + gains[4] + gains[5] >= bounty && Math.Abs(gains[3] - gains[4]) <= 1 + 60 && bounty > 10 * 30; + Check(rotBossPart, string.Format("Rot receives the high boss bounty ({0}), split in the team", bounty)); + Check(state.Boss.Claim == null, "claim consumed after the deployment round"); + foreach (int lockedRound in new[] { 8, 9 }) + { + Check(state.RoundNumber == lockedRound && !state.GrottoAvailable(), string.Format("grotto locked in round {0}", lockedRound)); + // Fixture: keep all buildings standing so the strong test army cannot end the match early. + foreach (BuildingDef definition in state.Map.Buildings) + state.BuildingHp[definition.Id] = definition.MaxHp; + RunRound(state); + } + Check(state.RoundNumber == 10 && state.GrottoAvailable(), "grotto open again in round 10"); + state.BeginCombat(); + Check(state.Combat.Units.All(u => u.Kind != "boss"), "no second deployment"); + state.FinishCombat(); + } + + void TestBossFailureRestores() + { + LuneMatch state = NewMatch(27); + Grant(state, 2, 200); + state.Submit(2, Command.Buy("g01")); + state.Submit(2, Command.Assign(state.Players[2].Draft.Roster[0].Uid, "grotto")); + state.BeginCombat(); + double firstHp = state.Combat.GrottoBoss.MaxHp; + state.FinishCombat(); + Check(state.LastSettlement.Boss == "failed" && state.Boss.Claim == null && state.GrottoAvailable(), "weak expedition fails without reward or lock"); + state.Submit(2, Command.Assign(state.Players[2].Roster[0].Uid, "grotto")); + state.BeginCombat(); + Check(state.Combat.GrottoBoss.Hp == state.Combat.GrottoBoss.MaxHp && state.Combat.GrottoBoss.MaxHp >= firstHp, "next attempt faces a fully restored boss"); + state.FinishCombat(); + bool noGold = state.Combat.Events.Where(e => e.Zone == "grotto").All(e => e.Bounty == 0); + Check(noGold, "grotto deaths pay no gold"); + } + + void TestBotsM2() + { + LuneMatch state = NewMatch(28); + int heroes = 0; + int bookings = 0; + int grotto = 0; + for (int roundIndex = 0; roundIndex < 12; roundIndex++) + { + if (state.Phase == Phase.Over) + break; + for (int slot = 0; slot < 6; slot++) + LuneBot.Plan(state, slot); + foreach (Player player in state.Players) + { + bookings += player.Draft.NewBookings.Count; + grotto += player.Draft.Roster.Count(e => e.Lane == "grotto"); + } + state.BeginCombat(); + state.FinishCombat(); + } + heroes = state.Players.Count(p => p.Hero != null); + Check(heroes >= 3, string.Format("bots recruit heroes ({0})", heroes)); + Check(bookings >= 1, string.Format("bots book attack champions ({0})", bookings)); + Check(grotto >= 1, string.Format("a bot sends an expedition to the grotto ({0} troop assignments)", grotto)); + } + + void TestNoLegacyEconomy() + { + // Working assumption E of the reference: the Saumwacht worker/spark economy must not + // exist in this mode. The port carries no such types at all. + string[] legacy = { "GameState", "EconomyManager", "WaveManager" }; + bool clean = typeof(LuneMatch).Assembly.GetTypes().All(t => Array.IndexOf(legacy, t.Name) < 0); + LuneMatch state = NewMatch(29); + for (int i = 0; i < 3; i++) + { + for (int slot = 0; slot < 6; slot++) + LuneBot.Plan(state, slot); + state.BeginCombat(); + state.FinishCombat(); + } + Check(clean, "no legacy phase, worker or spark economy in the core"); + bool hasSparkFields = typeof(Player).GetField("Sparks") != null || typeof(Player).GetField("Workers") != null; + Check(!hasSparkFields, "Luneraria players have gold only, no sparks or workers"); + } + + void TestLaneLoss() + { + // A player whose lane is broken is not eliminated: they keep planning, defending and helping. + LuneMatch state = NewMatch(30); + state.BuildingHp["blau_top_outer"] = 0.0; + state.BuildingHp["blau_top_inner"] = 0.0; + state.Players[0].Draft = state.Snapshot(state.Players[0]); + Check(state.Submit(0, Command.Buy("g03")).Ok, "lane-less player can still buy"); + Check(state.Submit(0, Command.Assign(state.Players[0].Draft.Roster[0].Uid, "mid")).Ok, "and support another lane"); + state.Submit(0, Command.Buy("g01")); + state.BeginCombat(); + int top = 0; + int mid = 0; + foreach (LuneUnit unit in state.Combat.Units) + { + if (unit.OwnerSlot == 0) + { + top += unit.Lane == "top" ? 1 : 0; + mid += unit.Lane == "mid" ? 1 : 0; + } + } + Check(top == 1 && mid == 1, "troops fight on the broken lane and on the supported lane"); + Check(LuneMap.IsAttackable(state.Map.BuildingDef("blau_base_1"), state.Combat.AliveMap()), "the broken lane opens Blau's base towers"); + state.FinishCombat(); + Check(state.Phase != Phase.Over || state.Winner != LuneMatch.Ongoing, "the match continues or ends only by an Ancient"); + Check(state.Players[0].Roster.Count == 2 && state.LastSettlement.Income > 0, "lane-less player still owns troops and earns income"); + } + } +} diff --git a/Assets/Luneraria/Tests/Core/MiniJson.cs b/Assets/Luneraria/Tests/Core/MiniJson.cs new file mode 100644 index 0000000..02d8f13 --- /dev/null +++ b/Assets/Luneraria/Tests/Core/MiniJson.cs @@ -0,0 +1,194 @@ +using System; +using System.Collections.Generic; +using System.Globalization; +using System.Text; + +namespace Luneraria.Core.Tests +{ + /// + /// Minimal JSON reader for the golden files, without package dependencies (the same code + /// runs in Unity and in the .NET harness). Objects keep their key order; numbers without + /// fraction or exponent become long, all others double. + /// + public static class MiniJson + { + public static object Parse(string text) + { + int at = 0; + object value = ReadValue(text, ref at); + SkipSpace(text, ref at); + if (at != text.Length) + throw new FormatException("trailing characters at " + at); + return value; + } + + static void SkipSpace(string text, ref int at) + { + while (at < text.Length && char.IsWhiteSpace(text[at])) + at++; + } + + static object ReadValue(string text, ref int at) + { + SkipSpace(text, ref at); + char c = text[at]; + if (c == '{') + return ReadObject(text, ref at); + if (c == '[') + return ReadArray(text, ref at); + if (c == '"') + return ReadString(text, ref at); + if (text.Length - at >= 4 && string.CompareOrdinal(text, at, "true", 0, 4) == 0) + { + at += 4; + return true; + } + if (text.Length - at >= 5 && string.CompareOrdinal(text, at, "false", 0, 5) == 0) + { + at += 5; + return false; + } + if (text.Length - at >= 4 && string.CompareOrdinal(text, at, "null", 0, 4) == 0) + { + at += 4; + return null; + } + return ReadNumber(text, ref at); + } + + static OrderedMap ReadObject(string text, ref int at) + { + var result = new OrderedMap(); + at++; + SkipSpace(text, ref at); + if (text[at] == '}') + { + at++; + return result; + } + while (true) + { + SkipSpace(text, ref at); + string key = ReadString(text, ref at); + SkipSpace(text, ref at); + if (text[at] != ':') + throw new FormatException("expected ':' at " + at); + at++; + result[key] = ReadValue(text, ref at); + SkipSpace(text, ref at); + if (text[at] == ',') + { + at++; + continue; + } + if (text[at] == '}') + { + at++; + return result; + } + throw new FormatException("expected ',' or '}' at " + at); + } + } + + static List ReadArray(string text, ref int at) + { + var result = new List(); + at++; + SkipSpace(text, ref at); + if (text[at] == ']') + { + at++; + return result; + } + while (true) + { + result.Add(ReadValue(text, ref at)); + SkipSpace(text, ref at); + if (text[at] == ',') + { + at++; + continue; + } + if (text[at] == ']') + { + at++; + return result; + } + throw new FormatException("expected ',' or ']' at " + at); + } + } + + static string ReadString(string text, ref int at) + { + if (text[at] != '"') + throw new FormatException("expected string at " + at); + at++; + var builder = new StringBuilder(); + while (true) + { + char c = text[at++]; + if (c == '"') + return builder.ToString(); + if (c != '\\') + { + builder.Append(c); + continue; + } + char escape = text[at++]; + switch (escape) + { + case '"': builder.Append('"'); break; + case '\\': builder.Append('\\'); break; + case '/': builder.Append('/'); break; + case 'b': builder.Append('\b'); break; + case 'f': builder.Append('\f'); break; + case 'n': builder.Append('\n'); break; + case 'r': builder.Append('\r'); break; + case 't': builder.Append('\t'); break; + case 'u': + builder.Append((char)int.Parse(text.Substring(at, 4), NumberStyles.HexNumber, CultureInfo.InvariantCulture)); + at += 4; + break; + default: throw new FormatException("bad escape at " + at); + } + } + } + + static object ReadNumber(string text, ref int at) + { + int start = at; + bool fraction = false; + while (at < text.Length && "+-0123456789.eE".IndexOf(text[at]) >= 0) + { + if (text[at] == '.' || text[at] == 'e' || text[at] == 'E') + fraction = true; + at++; + } + string token = text.Substring(start, at - start); + if (!fraction) + { + long whole; + if (long.TryParse(token, NumberStyles.Integer, CultureInfo.InvariantCulture, out whole)) + return whole; + } + return double.Parse(token, NumberStyles.Float, CultureInfo.InvariantCulture); + } + + // ---------------------------------------------------------------- access helpers + public static OrderedMap Obj(object value) { return (OrderedMap)value; } + + public static List Arr(object value) { return (List)value; } + + public static double Num(object value) { return value is long l ? l : (double)value; } + + public static int Int(object value) { return value is long l ? (int)l : (int)(double)value; } + + public static string Str(object value) { return value == null ? "" : value.ToString(); } + + public static object Get(OrderedMap map, string key) + { + object value; + return map.TryGetValue(key, out value) ? value : null; + } + } +} diff --git a/Assets/Luneraria/Tests/Core/Unity/CoreSuiteTests.cs b/Assets/Luneraria/Tests/Core/Unity/CoreSuiteTests.cs new file mode 100644 index 0000000..5c73ba8 --- /dev/null +++ b/Assets/Luneraria/Tests/Core/Unity/CoreSuiteTests.cs @@ -0,0 +1,31 @@ +using System.IO; +using NUnit.Framework; +using UnityEngine; + +namespace Luneraria.Core.Tests +{ + /// + /// Runs the engine-independent core suites in Unity's Test Runner (EditMode). The same + /// suites run outside Unity through tools/dotnet/Luneraria.Core.Tests. + /// + public sealed class CoreSuiteTests + { + static string GoldenDirectory { get { return Path.Combine(Application.dataPath, "Luneraria/Tests/Core/Golden"); } } + + static void RunSuite(CheckSuite suite) + { + suite.GoldenDirectory = GoldenDirectory; + bool ok = suite.Run(); + foreach (string note in suite.Notes) + Debug.Log(suite.Name + ": " + note); + Assert.IsTrue(ok, suite.Name + ": " + suite.Failures.Count + " of " + suite.Checks + " checks failed:\n" + string.Join("\n", suite.Failures)); + Debug.Log(string.Format("LUNE_U1_PASS {0}: {1} checks", suite.Name, suite.Checks)); + } + + [Test] public void Content() { RunSuite(new ContentSuite()); } + [Test] public void CoreRules() { RunSuite(new CoreRulesSuite()); } + [Test] public void M2Rules() { RunSuite(new M2RulesSuite()); } + [Test] public void GoldenReplays() { RunSuite(new GoldenSuite()); } + [Test] public void Determinism() { RunSuite(new DeterminismSuite()); } + } +} diff --git a/README.md b/README.md new file mode 100644 index 0000000..3384835 --- /dev/null +++ b/README.md @@ -0,0 +1,24 @@ +# Champions of Luneraria · Unity + +Drei-Lane-Autobattler 3 gegen 3 (Mischung aus Dota 2 und Legion TD 2), portiert von Godot nach Unity. + +- Engine: Unity 6.3 LTS (6000.3.20f1), URP. +- Zielplattformen: Fedora 44, Windows 11. macOS ist die Entwicklungsplattform. +- Referenz: `../saumwacht-godot`, Zweig `luneraria/g3` (`1b540f2`). + +## Aufbau + +- `Assets/Luneraria/Core/`: Regelkern ohne Unity-Abhängigkeit (`Luneraria.Core`). +- `Assets/Luneraria/Tests/Core/`: Prüfsuiten mit Golden-Referenzen aus Godot; laufen im Unity Test Runner und mit dem .NET SDK. +- `tools/`: .NET-Projekte, Godot-Referenzwerkzeuge, Portwerkzeuge. +- `docs/port/`: Stand, Entscheidungen und QA je Meilenstein ([PORT-STATUS.md](docs/port/PORT-STATUS.md)). + +## Befehle + +```bash +sh tools/run_core_tests.sh +``` + +```bash +dotnet run -c Release --project tools/dotnet/Luneraria.Core.Bench +``` diff --git a/docs/port/PORT-QA.md b/docs/port/PORT-QA.md new file mode 100644 index 0000000..0f4699a --- /dev/null +++ b/docs/port/PORT-QA.md @@ -0,0 +1,19 @@ +# Port-QA + +Je Meilenstein: Tests, Bild, Leistung, bekannte Unterschiede, Commit. + +## U1 · C#-Simulation + +| Punkt | Ergebnis | +| --- | --- | +| Tests | `content` 75/75, `core` 91/91, `m2` 73/73, `golden` 157/157, `determinism` 6/6 = **402/402**; dreimal in getrennten Prozessen; Protokoll `logs/u1/core-tests.json` | +| Golden-Parität | 19 Szenarien, 120 Snapshots, 51.221 Werte; größte Abweichung 0 in allen Kategorien (Toleranzen siehe U1-RULES.md) | +| Bild | `screenshots/u1/replay-start_three_lanes-t10.png`, `replay-boss_cycle-marching.png`, `replay-grotto_contested-t15.png`: Godot-Positionen (Punkte) und C#-Positionen (Ringe) decken sich (31/31, 35/35, 15/15) | +| Leistung (Mac M5) | Simulationsschritt bei 120 Einheiten: Godot 1,587 ms, C#/.NET 8 0,259 ms; Bot-Partien pro Runde: 648 ms zu 36 ms (`logs/u1/sim-bench-*.json`) | +| Bekannte Unterschiede | technische Repräsentation (Klassen statt Dictionaries, stabile Sortierung, 32-Bit-int, kein ungenutzter Zufallsgenerator); Referenzfehler R1 bewusst übernommen | +| Offen | Lauf im Unity-Editor (Lizenz fehlt), Mono-Leistung, Kerntests auf Windows 11 und Fedora 44 | +| Commit | Zweig `luneraria/u1` | + +## U2 bis U5 + +Noch nicht begonnen. diff --git a/docs/port/PORT-STATUS.md b/docs/port/PORT-STATUS.md new file mode 100644 index 0000000..96d0a68 --- /dev/null +++ b/docs/port/PORT-STATUS.md @@ -0,0 +1,39 @@ +# Port-Status · Champions of Luneraria in Unity + +Stand: 30. September 2026. + +Referenz ist der Godot-Stand `luneraria/g3` (`1b540f2`) in `../saumwacht-godot`; er wird nicht mehr verändert. Engine: Unity 6.3 LTS (6000.3.20f1), Renderer URP. HDRP ist ausgeschlossen, bis ein Vergleich mit einer echten Szene etwas anderes nahelegt. + +Zielplattformen sind Fedora 44 und Windows 11; macOS ist die Entwicklungsplattform. + +| Meilenstein | Zustand | Nachweis | +| --- | --- | --- | +| U1 · C#-Simulation | **fertig außerhalb von Unity**: 402/402 Prüfungen, Golden-Parität mit Godot; Unity-Editor-Lauf offen (Lizenz) | [U1-RULES.md](U1-RULES.md) | +| U2 · Unity-Spielwelt | nicht begonnen; Voraussetzung: U1 grün und Unity-Lizenz aktiv | [U2-WORLD.md](U2-WORLD.md) | +| U3 · G3-HUD portieren | nicht begonnen | [U3-UI.md](U3-UI.md) | +| U4 · Netzwerk | nicht begonnen; M4-Umfang ist erfasst | [U4-NETWORK.md](U4-NETWORK.md) | +| U5 · Visuelle Neuausrichtung (Vertical Slice Mid-Lane) | nicht begonnen | [U5-VISUAL.md](U5-VISUAL.md) | + +QA je Meilenstein: [PORT-QA.md](PORT-QA.md). + +## Blocker + +- **Unity-Lizenz:** Unity startet im Batch-Modus, meldet aber „No valid Unity Editor license found“. Nötig ist eine Anmeldung im Unity Hub mit aktivierter Personal-Lizenz; das kann nur der Projektinhaber erledigen. +- Bis dahin gibt es keine `ProjectSettings/` und keine `.meta`-Dateien; Unity erzeugt sie beim ersten Öffnen. + +## Entscheidungen + +- **Regelkern ohne Unity** (`Luneraria.Core`, `noEngineReferences`). Unity wird Adapter und Präsentation. +- **Verhaltensgleichheit statt Bitgleichheit.** Verglichen wird mit dokumentierten Toleranzen; gemessen wurde auf dem Mac trotzdem Abweichung 0. +- **Tabellen** einmal aus Godot erzeugt (`tools/port/gen_content.py`); danach ist `ContentData.cs` die gepflegte Quelle. +- **Referenzfehler R1** im Bot-Gedächtnis ist bewusst übernommen (Parität) und für eine spätere Bot-Phase vorgemerkt. +- **Geplante Helden** (Lucy, Ghaliga, Siegfried, Feena) stehen im Datenmodell, sind aber inaktiv, bis eine Heldenphase ihre Regeln umsetzt. +- **Assets:** Blender-Quellen und Generatoren sind die Quelle. Ein zentraler, reproduzierbarer Blender-Export erzeugt FBX für Unity; GLB nur, wo keine bessere Quelle existiert (U2). + +## Arbeitsweise + +- Ein Zweig je Meilenstein: `luneraria/u1`, `luneraria/u2`, … Nach jedem Meilenstein kommen Tests, Bild, Leistung, bekannte Unterschiede und ein Commit. +- Werkzeuge: + - `tools/run_core_tests.sh` (Kern). + - `tools/godot-golden/run_godot.sh` (Godot-Referenz). + - `tools/dotnet/Luneraria.Core.Bench` (Leistung). diff --git a/docs/port/U1-RULES.md b/docs/port/U1-RULES.md new file mode 100644 index 0000000..3136291 --- /dev/null +++ b/docs/port/U1-RULES.md @@ -0,0 +1,170 @@ +# U1 · Regelkern in C# + +Stand: 30. September 2026 · Zweig `luneraria/u1` · Referenz: Godot-Stand `luneraria/g3` (`1b540f2`, Regeln unverändert seit G2). + +**Ergebnis:** Der vollständige, engineunabhängige Regelkern läuft in C#. Er ist deterministisch und reproduzierbar und verhält sich in allen geprüften Fällen wie die Godot-Referenz: 402 von 402 Prüfungen, darunter 157 Golden-Vergleiche mit 51.221 Einzelwerten. + +**Noch offen:** der Lauf im Unity-Editor. Die Unity-Lizenz fehlt noch; bis dahin baut und testet der .NET-8-SDK den Kern mit Unitys Sprach- und API-Stand (C# 9, .NET Standard 2.1). + +## Aufbau + +| Pfad | Inhalt | +| --- | --- | +| `Assets/Luneraria/Core/` | Assembly `Luneraria.Core`, `noEngineReferences: true` – keine Unity-Abhängigkeit | +| `Core/Model/` | `Vec2` (Bodenvektor), `GdMath` (Skalarfunktionen), `OrderedMap` (Map mit fester Reihenfolge) | +| `Core/Content/` | Tabellen (`ContentData.cs`, einmalig aus Godot erzeugt, seitdem gepflegte Quelle), Typen, `LuneBalance`, `LuneContent`, `LuneWaves`, `DataCatalog`, geplante Helden | +| `Core/Simulation/` | `LuneMap`, `LuneUnit`, `LuneCombat`, `LuneMatch` mit Partiemodell, `LuneBot` | +| `Assets/Luneraria/Tests/Core/` | Assembly `Luneraria.Core.Tests`: fünf Prüfsuiten, Golden-Dateien, Unity-Adapter (`Unity/CoreSuiteTests.cs`) | +| `tools/dotnet/` | .NET-Projekte: Kern als `netstandard2.1`, Testlauf, Leistungsmessung | +| `tools/godot-golden/` | Werkzeuge, die im Godot-Referenzprojekt laufen: Tabellenexport, Golden-Szenarien, Gleitkomma-Probe, Leistungsmessung | +| `tools/port/gen_content.py` | einmalige Erzeugung von `ContentData.cs` aus dem Godot-Export | + +Unity dient später nur als Adapter und Präsentationsschicht (U2): Er treibt `LuneMatch` im festen Takt an und liest den Zustand. + +## Portierter Umfang + +| Bereich | Umsetzung | Quelle in Godot | +| --- | --- | --- | +| Matchzustand, Phasen Planung/Kampf/Ende, sechs Plätze, zwei Teams | `LuneMatch`, `MatchModel.cs` | `lune_match.gd` | +| Private Planung mit Entwurf, Rückgängig, atomare Übernahme bei Kampfbeginn | `Submit`, `Undo`, `BeginCombat`, `DraftValid` | `lune_match.gd` | +| Gold, Käufe, Aufwertungen, Rückgabe (voll in derselben Planung, sonst 75 %) | `Apply` | `lune_match.gd` | +| Formation: Reihen zu viert, Lane-Besitzer vorn, Rollenreihenfolge | `SpawnArmies`, `Sorted` | `lune_match.gd` | +| Drei Lanes, Geometrie, Bottom so lang wie Top | `LuneMap` | `lune_map.gd` | +| Zwei Laneturme je Lane, zwei Basistürme, Ancient, Sperren | `LuneMap.IsAttackable`, `LuneCombat` | `lune_map.gd`, `lune_combat.gd` | +| Einheiten, Effekte, Schilde, Schaden über Zeit, Schadensmatrix | `LuneUnit` | `lune_unit.gd` | +| Kampf: Ziele, Marsch, Trennung, Angriffe, Fähigkeiten, Tode, Ende | `LuneCombat` | `lune_combat.gd` | +| Unbegrenzte Wellen mit steigender Stärke | `LuneWaves` | `lune_waves.gd` | +| Helden: Stufen, Erfahrung, drei Itemplätze, Talente | `LuneContent.HeroDefinition`, `Apply` | `lune_content.gd`, `lune_match.gd` | +| Normale Einheiten ohne Items | `item_buy` lehnt Truppen-IDs ab; `RosterEntry` hat kein Inventar | `lune_match.gd` | +| Angriffschampions: Buchung n, Einsatz n+1, Kopfgeld, Verbrauch | `SpawnChampions`, `Settle` | `lune_match.gd` | +| Bossgrotte: Expeditionen, ruhender Boss, Anspruch, Entsendung, Kopfgeld, dreirundige Sperre | `SpawnArmies`, `SettleBoss`, `LuneCombat.UpdateGrotto` | `lune_match.gd`, `lune_combat.gd` | +| Bots über dieselbe Befehlsschnittstelle | `LuneBot` | `lune_bot.gd` | +| Siegbedingung: nur Ancient-Zerstörung; zwei im selben Schritt = Unentschieden | `Settle` | `lune_match.gd` | + +Erhalten sind ausdrücklich: 3 gegen 3 auf drei Lanes, unbegrenzte Wellen, Partieende nur durch einen Ancient, zwei Laneturme je Lane und zwei Basistürme je Team, Heldenentwicklung, Angriffschampions, Bossgrotte mit Sperre. Die Architektur ist serverautoritativ: `LuneMatch` läuft nur beim Host; Clients senden `Command`-Absichten. Alte Saumwacht-Regeln (Arbeiter, Funken, Wellen der Kampagne) sind nicht portiert; ein Test prüft, dass der Kern keine solchen Typen enthält. + +## Determinismus + +- **Fester Takt:** `SimStep` 0,05 s. Die Simulation liest weder Uhr noch Bildrate; Unity treibt sie mit einem Akkumulator an. +- **Reihenfolgen:** Schleifen laufen nur über Listen in Spawnreihenfolge und über `OrderedMap` (Einfügereihenfolge, auch nach Entfernen stabil). `Dictionary` dient nur zum Nachschlagen; ein Codeaudit bestätigt, dass keine Regel darüber iteriert. +- **IDs:** Einheiten-IDs zählen je Kampf von 1 hoch; UIDs sind `p{Platz}-{Folge}`, `h…`, `c…`, `boss-{Runde}`. Keine Objektidentität, keine Hashwerte. +- **Sortierung:** Alle Vergleiche sind strenge Ordnungen auf eindeutigen Schlüsseln (Distanz, dann Einheiten-ID bzw. Rolle, dann Folge). Der Kern sortiert stabil per Einfügen. +- **Zufall:** kommt in den Regeln nicht vor (in Godot wurde der Zufallsgenerator nur initialisiert, nie benutzt). +- **Kein geteilter Zustand:** Zwei Partien im Wechsel liefern dasselbe wie einzeln. +- **Physik und Threads:** nicht beteiligt. + +Nachweis: Die Suite `determinism` spielt dieselben Partien doppelt und verschachtelt. Alle Suiten liefen in drei getrennten Prozessen grün; .NET streut die String-Hashwerte je Prozess neu. + +## Zahlen und Toleranzen + +Positionen sind Vektoren mit 32-Bit-Komponenten, alle anderen Größen 64 Bit, wie in der Referenz. `Vec2` rechnet wie Godots Vector2: einfache Einzelgenauigkeit ohne fusionierte Multiply-Add-Operationen. Die Probe `tools/godot-golden/float_probe.gd` zeigt 4.000 von 4.000 identischen Stichproben. + +Bitgleichheit ist **kein Ziel**. Verglichen wird fachlich: + +| Kategorie | Toleranz | Größte gemessene Abweichung (Mac, .NET 8) | +| --- | --- | --- | +| Ganzzahlen, Texte, Flags: Besitz, Gold, Käufe, Aufwertungen, Ziele (Einheiten-ID), Zustände, Gewinner, Befehlsergebnisse und Meldungen | exakt | – | +| Lebenspunkte, Schilde, Gebäude-HP | 0,01 HP bzw. 10⁻⁹ relativ | 0 (5.679 Werte) | +| Positionen, Lanefortschritt | 1 mm | 0 (3.420 Werte) | +| Blickrichtung | 10⁻⁴ rad | 0 (1.140 Werte) | +| Kampfzeit, Ereigniszeiten | 10⁻⁶ s | 0 (780 Werte) | +| Effektstärken und -dauern | 10⁻⁶ | 0 (264 Werte) | + +Auf anderen Laufzeiten (Unity-Mono, IL2CPP, Windows x64, Linux) sind winzige Rundungsunterschiede möglich; dafür sind die Toleranzen da. Weil der Host autoritativ rechnet, müssen Clients die Simulation nicht selbst nachrechnen. + +## Bewusst andere technische Repräsentation + +| Godot | C# | Warum gleichwertig | +| --- | --- | --- | +| Definitionen, Spieler, Entwürfe, Helden, Buchungen als `Dictionary` | Klassen (`UnitDef`, `Player`, `Draft`, `HeroState`, `Booking`, `BossClaim`) | Standardwerte entsprechen den `get(key, default)`-Fallbacks (z. B. `SiegeFactor = 1`) | +| leeres `{}` für „kein Held“ bzw. „kein Anspruch“ | `null` | – | +| Befehle als `Dictionary` | `Command` mit Fabrikmethoden; fehlende Felder = `null` (z. B. Kauf ohne Lane = eigene Lane) | Nachrichten und Ablehnungsgründe identisch (Golden-Vergleich) | +| `sort_custom` (Introsort, instabil) | stabile Einfügesortierung | bei strengen Ordnungen identisches Ergebnis | +| GDScript-`int` (64 Bit) | `int` (32 Bit) | Werte liegen weit darunter; Monsterkopfgeld wird zusätzlich begrenzt | +| Rückgängig über dieselbe `submit`-Funktion der Sitzung | `LuneMatch.Undo(slot)`; `Submit` kennt „undo“ nicht | wie in der Referenz, wo die Sitzung `undo()` direkt ruft | +| `rng` in `LuneMatch` | entfällt | wurde nie benutzt | +| Tabellen in `DataCatalog`/`LuneContent` | `ContentData.cs`, einmal erzeugt | Suite `content` vergleicht alles mit dem Godot-Export | + +## Referenzfehler R1 (übernommen) + +`lune_bot.gd`, `_plan_boss`: Ein Bot, dessen Gedächtnis nur eine Champion-Buchung enthält, liest die fehlenden Felder `bar` und `sent`. GDScript bricht die Funktion dann ab. Folge: Ein Bossjäger-Bot, der vorher einen Champion gebucht hat, schickt nie eine Expedition in die Grotte. Beim Erzeugen der Golden-Referenzen trat der Fehler in vier Szenarien auf (`Invalid access to property or key 'bar'`). + +Der Port bildet das Verhalten bewusst nach (`LuneBot.PlanBoss`, Kommentar R1), damit die Bots fachlich gleich bleiben. **Empfehlung:** in einer späteren Balance- oder Bot-Phase korrigieren, mit neuer Golden-Referenz. + +## Golden-Referenzen + +`Assets/Luneraria/Tests/Core/Golden/scenarios.json` beschreibt 19 Szenarien als Abfolge von Operationen. Operationen sind: Aufbau, Fixture wie Gold, Runde oder Gebäude-HP, Befehl, Bots, Kampfbeginn, Schritte, Kampfende, Zustandsaufnahme. `tools/godot-golden/golden_scenarios.gd` spielt sie mit den Godot-Regeln und schreibt `golden.json`; die Suite `golden` spielt sie in C# und vergleicht jeden Snapshot Feld für Feld. + +| Szenario | Deckt ab | +| --- | --- | +| `start_three_lanes` | normaler Drei-Lane-Start, Aufmarsch, Einheiten nach 10 und 30 s mit Zielen, Abrechnung | +| `lane_outer_lost` | Lane ohne äußeren Turm | +| `lane_both_lost` | Lane ohne beide Türme, Basis offen | +| `base_tower_attack` | Angriff auf Basistürme bis zum Fall des Ancients | +| `ancient_destruction` | Ancient-Zerstörung, Sieger, Partieende | +| `high_wave_21`, `high_wave_137` | Wellen über 20 und über 100: Zusammensetzung, Werte, Kampf, Belohnungen | +| `hero_levels` | Helden über neun Runden: Anwerben, Erfahrung, Stufen bis 6, Talente, Items | +| `item_purchase` | Itemkauf, Plätze, Einzigartigkeit, Stufenbedingung, Rückgabe, Truppen ohne Items | +| `attack_champion` | Buchung, Grenze, Rücknahme, Ankündigung, Einsatz, Kopfgeld, Verbrauch | +| `boss_cycle` | Bossversuch erfolgreich, Anspruch, Lane-Wahl, Entsendung, Boss getötet mit Kopfgeld, Sperre in Runde 8 und 9, wieder offen in Runde 10, keine zweite Entsendung | +| `boss_failure` | gescheiterter Bossversuch ohne Sperre, voller Boss beim nächsten Versuch | +| `grotto_contested` | umkämpfte Grotte, ruhender Boss, Sieger erhält Anspruch | +| `mirror_match` | exakte Symmetrie bei gleichen Bünden und Profilen | +| `bot_match_1/2/3/11/28` | fünf vollständige Bot-Partien bis zum Ancient-Fall | + +Verglichen werden je Snapshot: Phase, Runde, Gewinner, Endnotiz; je Platz Gold, Entwurfsgold, Bereitschaft, Einnahmen, Ausgaben, Armee, Held, Buchungen und Rückgängig-Tiefe; Gebäude-HP; Bosszustand, Bosslog und Ankündigungen; die Abrechnung (Gewinne, Einkommen, verlorene Gebäude, Endgrund, Kills je Lane, Erfahrung); Kampfzustand und Grotte. Optional kommen hinzu: jede Einheit mit ID, Art, Team, Lane, Zone, Besitz, Leben, Schild, Position, Blickrichtung, Fortschritt, Ziel, Trefferzahl, Effekten und Schaden über Zeit; jedes Ereignis; die Welle. Dazu das Ergebnis und die Meldung jedes Befehls. + +Beim ersten Vergleich zeigte sich ein Fehler im Exporter, nicht im Port: `Array(typed_array)` liefert in Godot dieselbe Referenz. Frühe Snapshots enthielten deshalb schon den späteren Ancient-Fall. Behoben mit `duplicate()`. + +Bildnachweis: `docs/port/screenshots/u1/replay-*.png` zeigt die Karte mit den Godot-Positionen (Punkte) und den C#-Positionen (weiße Ringe). In allen drei Bildern stehen alle lebenden Einheiten an der Referenzposition (31/31, 35/35, 15/15). + +## Tests + +| Suite | Prüfungen | Inhalt | +| --- | ---: | --- | +| `content` | 75 | alle Tabellen und die berechnete Karte gegen den Godot-Export; Geometrieabweichung 0 m | +| `core` | 91 | Port von `test_lune_core.gd` (91 in Godot) | +| `m2` | 73 | Port von `test_lune_m2.gd` (73 in Godot); die Saumwacht-Autoload-Prüfung ist durch „keine Altökonomie-Typen im Kern“ ersetzt | +| `golden` | 157 | 19 Szenarien, 120 Snapshots, 51.221 Werte | +| `determinism` | 6 | Wiederholung, Verschachtelung, IDs, fester Takt | +| **gesamt** | **402** | alle bestanden, dreimal in getrennten Prozessen | + +```bash +sh tools/run_core_tests.sh +``` + +Mit `REGENERATE_GOLDEN=1` werden vorher die Godot-Referenzen neu erzeugt. Das braucht `../saumwacht-godot`; das Referenz-Repository bleibt unverändert. Protokoll: `docs/port/logs/u1/core-tests.json`. Im Unity Test Runner laufen dieselben Suiten über `Luneraria.Core.Tests` (EditMode), sobald die Lizenz aktiv ist. + +## Leistung + +Gleiche Aufstellung wie die Godot-Benchmark-Probe: Runde 13, sechs Armeen am Versorgungslimit, 120 bewegliche Einheiten. Gemessen auf dem Mac (Apple M5). + +| | Godot 4.7.2 (GDScript) | C# (.NET 8, Release) | Faktor | +| --- | ---: | ---: | ---: | +| Simulationsschritt, Median aus 5 × 200 | 1,587 ms | 0,259 ms | 6,1 × | +| Bot-Partien Seeds 1–3 (32 Runden) | 20,7 s | 1,17 s | 17,8 × | + +Rohdaten: `docs/port/logs/u1/sim-bench-{godot,csharp}.json`. +- Unitys Editor läuft mit Mono; die Messung dort folgt mit U2. +- Der Faktor gegenüber Godot ist ein Anhaltspunkt, keine Zusage für den Player. + +## Geplante Helden + +Lucy, Ghaliga, Siegfried und Feena stehen als `PlannedHeroes` im Datenmodell: +- Volk, Rolle, Formationsreihe, Waffe, Aussehen, Ziel. +- Fähigkeit und Ultimate mit Auslöser (automatisch bzw. Command-Menü) und Wirkungsart. +- Balanceparameter wie Radius, Dauer, Stärke, Ziele, Abklingzeit und Betäubung; sie sind noch leer (`null` = nicht festgelegt). + +Sie sind nicht aktiv und nicht käuflich; die Partie bietet weiter nur die drei Referenzhelden, damit die Parität gilt. + +Für die Umsetzung sind neue Regeln nötig: +- Betäubung (Excalibur). +- Bindung/Aggro (Versteinerung). +- Ausnahme vom Tempodeckel (Turbopfeile). +- Kampfbefehle während der Kampfphase (Command-Menü; heute gibt es nur Planungsbefehle). + +## Offene Punkte + +- Unity-Lizenz aktivieren, dann Kern und Tests im Editor (Mono) laufen lassen und die Mono-Leistung messen. +- Kerntests auf Windows 11 und Fedora 44 ausführen (Zielplattformen). Der Kern ist plattformneutral, der Lauf dort steht aber aus. +- R1 später korrigieren (siehe oben). diff --git a/docs/port/U2-WORLD.md b/docs/port/U2-WORLD.md new file mode 100644 index 0000000..6e0e031 --- /dev/null +++ b/docs/port/U2-WORLD.md @@ -0,0 +1,51 @@ +# U2 · Unity-Spielwelt + +Stand: 30. September 2026 · **nicht begonnen**. + +Voraussetzungen: U1 grün (erfüllt außerhalb von Unity) und aktive Unity-Lizenz (fehlt). + +## Ziel + +Die bestehende Partie läuft sichtbar in Unity (URP). Das ist noch keine grafische Neugestaltung. + +Zuerst kommen: +- die G1-Drei-Lane-Karte, +- die G2-Türme (Grenzwacht, Bastion, Kernwacht), +- die G2-Ancients, +- die Bossgrotte und die Schlundkrone, +- repräsentative vorhandene Einheiten. + +## Vorgaben + +- **Adapter:** Unity treibt `LuneMatch` im festen Takt (0,05 s) über einen Akkumulator, unabhängig von der Bildrate. Ansichten lesen nur; sie schreiben nie in die Regeln. +- **Gemeinsames Materialsystem** (URP, Shader Graph oder HLSL): Stein, Metall, Holz, Vegetation, Kristall, Runen, Wasser. Die G2-Shader aus Godot (stone, metal, crystal, rune, cloth, vein, water_glow, hide) dienen als fachliche Vorlage. Automatische Materialkonvertierungen werden nicht ungeprüft übernommen. +- **Assets:** Quelle sind die Blender-Dateien und Generatoren im Referenz-Repository. Ein zentraler, reproduzierbarer Blender-Export erzeugt FBX für Unity; GLB nur, wo keine bearbeitbare Quelle existiert. + +## Bestand an Quellen (Godot-Referenz) + +| Gruppe | GLB | Blender-Quelle | +| --- | ---: | --- | +| Truppen, Monster, Sendungen (`assets/models`) | 59 | `assets-source/phase4/blend` (59 `.blend`) | +| Figuren mit Skelett (`assets/characters`) | 6 | `assets-source/phase10`–`phase19` (je ein `.blend` plus Generator) | +| G2-Bauwerke, Grotte, Schlundkrone (`assets/luneraria/g2`) | 6 | `assets-source/luneraria/g2` (`.blend` plus Generatoren) | +| Völker (`assets/luneraria/peoples`) | 7 | `assets-source/luneraria/peoples` | +| Umgebung, Vergleich, übrige | 11 | teilweise; wird im Exportinventar geklärt | + +## Prüfpunkte der Pipeline + +- Maßstab (1 Einheit = 1 m) und Achsen (Godot Y-oben/−Z-vorn gegenüber Unity Y-oben/+Z-vorn). +- Root Bone und Bone-Namen. +- Clip-Namen: idle, walk, attack_a, attack_b, hit, ability, death, roar, victory. +- Animation Events. +- Materialslots. +- Normalen und Tangenten. +- Blend Shapes, sofern vorhanden. + +## Abnahme + +- Die Partie läuft sichtbar. +- Die Kamera entspricht der Godot-Kamera. +- Screenshots neben den Godot-G2-Bildern mit vergleichbarer Kamera. +- Leistung gemessen, einschließlich Mono-Simulationszeit. +- Bekannte Unterschiede dokumentiert. +- Commit auf `luneraria/u2`. diff --git a/docs/port/U3-UI.md b/docs/port/U3-UI.md new file mode 100644 index 0000000..1fc8d37 --- /dev/null +++ b/docs/port/U3-UI.md @@ -0,0 +1,21 @@ +# U3 · G3-HUD portieren + +Stand: 30. September 2026 · **nicht begonnen**. + +Funktionale Referenz ist das G3-HUD aus Godot (`../saumwacht-godot/docs/luneraria/G3-HUD.md`, Commit `1b540f2`). Es wird übertragen, nicht neu erfunden. + +## Zu übertragen + +- Ancient-Anzeige, Welle und Phase, Gold. +- Drei Lanes mit Bedrohung und Türmen, Teammitglieder. +- Einheitenkarten, Armee. +- Held mit Stufe, Erfahrung, drei Itemslots und Talenten. +- Angriffschampions, nächste Welle, Bossstatus. +- Minimap, Bereit-Zustand, Tooltips, Ereignisse. +- Datenzugang über ein Sichtmodell mit denselben Privatsphäre-Regeln wie `LuneHudModel`. + +## Offene Entscheidung + +UI Toolkit oder uGUI: vor Beginn eine kurze technische Bewertung, dann **ein** System als Hauptlösung. + +Die geplanten Helden (`PlannedHeroes`) mit Command-Menü für Ultimates sind im Layout vorzusehen. diff --git a/docs/port/U4-NETWORK.md b/docs/port/U4-NETWORK.md new file mode 100644 index 0000000..d2ba647 --- /dev/null +++ b/docs/port/U4-NETWORK.md @@ -0,0 +1,27 @@ +# U4 · Netzwerk + +Stand: 30. September 2026 · **nicht begonnen**. Das Netzwerk folgt erst nach funktionierendem lokalen Spiel. + +Es wird keine neue Architektur erfunden. Übertragen wird der M4-Umfang (`lune_session.gd`, Protokoll 4), serverautoritativ: +- Clients senden Absichten. +- Der Host berechnet Gold, Käufe, Kampf, Schaden, Besitz, Boss und Sieg. + +## Erfasster M4-Umfang + +| Funktion | Verhalten in der Referenz | +| --- | --- | +| Rollen | offline (lokaler Host mit Bot-Plätzen), Host (ENet-Server, bis 5 Gäste), Gast | +| Sechs Plätze | ein Peer genau ein Platz; freie Plätze spielen Bots; Lobbyeinträge mit Name, Bereit, Bot | +| Beitritt | Hallo mit Protokollversion und Name; falsche Version wird abgelehnt; Namen gekürzt (24 Zeichen); volle Partie abgelehnt | +| Private Planung | ein Gast sendet Befehle für seinen Platz; fremde Plätze werden abgelehnt (Spoof-Schutz); der Zustand enthält nur den eigenen Entwurf | +| Bereit | nach Bereit ist die Planung verbindlich; alle bereit → Kampf; Bots planen einmal je Runde | +| Kampfsynchronisation | Kampfbeginn mit Einheitendatensätzen und Gebäude-HP; alle 0,05 s neue Einheiten und ein Frame (13 Werte je Einheit, ungeordnet-zuverlässig); Gast interpoliert, verspätete Frames werden verworfen | +| Abrechnung | Host sendet den öffentlichen Zustand nach dem Kampf | +| Disconnect | Platz geht an einen Bot, der in der Planung sofort plant; niemals Kernverlust | +| Wiedereinstieg | gleicher Name, solange der Platz bot-gehalten ist → Platz zurück, volle Synchronisation | +| Übernahme | ein neuer Mensch verwirft den unbestätigten Bot-Entwurf und muss selbst bereit melden | +| Revanche | Host startet neu, Plätze bleiben | +| Hostverlust | Gast kehrt mit Meldung ins Menü zurück | +| Tests | `test_lune_net` 43 Prüfungen, `net_rounds.py` Loopback mit zwei Prozessen 12 Prüfungen | + +Mindestumfang des Ports: Ready, private Planung, Bot-Übernahme, Wiedereinstieg, Snapshots, Revanche, Disconnect, sechs Plätze. diff --git a/docs/port/U5-VISUAL.md b/docs/port/U5-VISUAL.md new file mode 100644 index 0000000..6204354 --- /dev/null +++ b/docs/port/U5-VISUAL.md @@ -0,0 +1,22 @@ +# U5 · Visuelle Neuausrichtung + +Stand: 30. September 2026 · **nicht begonnen**. U5 ist die eigentliche Begründung für den Unity-Wechsel. + +## Vertical Slice + +Eine repräsentative Mid-Lane: +- beide Teamrichtungen, zwei Türme, mindestens ein Ancient sichtbar, +- Fluss/Wasser, Vegetation, Felsen, +- mehrere normale Einheiten, ein Held, ein Angriffschampion, +- die Bossgrotte in sichtbarer Nähe, Kampf-VFX. + +Nur diese Zone wird auf Zielqualität gebracht: +- Terrain, Wege, PBR-Materialien, Vegetation, +- Beleuchtung, Schatten, Himmel, Nebel, Wasser, +- Decals, Partikel, VFX, Color Grading. + +## Nachweis + +- Vorher/Nachher: Godot G3 gegenüber Unity U5 mit möglichst vergleichbarer Kamera. +- Leistung gemessen. +- Erst danach wird über das Qualitätsniveau der ganzen Karte entschieden. diff --git a/docs/port/logs/u1/core-tests.json b/docs/port/logs/u1/core-tests.json new file mode 100644 index 0000000..cbfe473 --- /dev/null +++ b/docs/port/logs/u1/core-tests.json @@ -0,0 +1,11 @@ +{ + "suites": [ + {"suite": "content", "checks": 75, "failures": 0, "seconds": 0.02, "failed": [], "notes": ["map geometry: largest deviation lanes 0.00E+000 m, buildings 0.00E+000 m"]}, + {"suite": "core", "checks": 91, "failures": 0, "seconds": 1.62, "failed": [], "notes": ["full match seed 2 -> Rot after 9 rounds"]}, + {"suite": "m2", "checks": 73, "failures": 0, "seconds": 0.38, "failed": [], "notes": []}, + {"suite": "golden", "checks": 157, "failures": 0, "seconds": 1.49, "failed": [], "notes": ["golden values compared: 51221", "largest deviation angle: 0.00E+000 over 1140 values (tolerance 1E-004)", "largest deviation effect: 0.00E+000 over 264 values (tolerance 1E-006)", "largest deviation hp: 0.00E+000 over 5679 values (tolerance 1E-002)", "largest deviation other: 0.00E+000 over 34 values (tolerance 1E-006)", "largest deviation position: 0.00E+000 over 3420 values (tolerance 1E-003)", "largest deviation time: 0.00E+000 over 780 values (tolerance 1E-006)"]}, + {"suite": "determinism", "checks": 6, "failures": 0, "seconds": 1.80, "failed": [], "notes": []} + ], + "runtime": ".NET 8.0.27", + "os": "Darwin 27.0.0 Darwin Kernel Version 27.0.0: Tue Aug 11 21:02:59 PDT 2026; root:xnu-13432.1.9~1/RELEASE_ARM64_T8142 Arm64" +} diff --git a/docs/port/logs/u1/sim-bench-csharp.json b/docs/port/logs/u1/sim-bench-csharp.json new file mode 100644 index 0000000..73d4a21 --- /dev/null +++ b/docs/port/logs/u1/sim-bench-csharp.json @@ -0,0 +1,10 @@ +{ + "runtime": ".NET 8.0.27", + "cpu": "Arm64", + "mobile_units_at_start": 120, + "sim_step_ms_median": 0.2590, + "step_blocks_ms": [0.2376, 0.2429, 0.2590, 0.2607, 0.2692], + "bot_matches_seeds_1_2_3_ms": 1165.8, + "bot_match_rounds": 32, + "ms_per_round": 36.43 +} diff --git a/docs/port/logs/u1/sim-bench-godot.json b/docs/port/logs/u1/sim-bench-godot.json new file mode 100644 index 0000000..6d9bfde --- /dev/null +++ b/docs/port/logs/u1/sim-bench-godot.json @@ -0,0 +1,15 @@ +{ + "bot_match_rounds": 32, + "bot_matches_seeds_1_2_3_ms": 20736.888, + "engine": "4.7.2-stable (official)", + "mobile_units_at_start": 120, + "ms_per_round": 648.02775, + "sim_step_ms_median": 1.586515, + "step_blocks_ms": [ + 1.580295, + 1.58385, + 1.586515, + 1.590605, + 1.595055 + ] +} \ No newline at end of file diff --git a/docs/port/screenshots/u1/replay-boss_cycle-marching.png b/docs/port/screenshots/u1/replay-boss_cycle-marching.png new file mode 100644 index 0000000..e5bd2cd Binary files /dev/null and b/docs/port/screenshots/u1/replay-boss_cycle-marching.png differ diff --git a/docs/port/screenshots/u1/replay-grotto_contested-t15.png b/docs/port/screenshots/u1/replay-grotto_contested-t15.png new file mode 100644 index 0000000..3dea16b Binary files /dev/null and b/docs/port/screenshots/u1/replay-grotto_contested-t15.png differ diff --git a/docs/port/screenshots/u1/replay-start_three_lanes-t10.png b/docs/port/screenshots/u1/replay-start_three_lanes-t10.png new file mode 100644 index 0000000..b8f51fd Binary files /dev/null and b/docs/port/screenshots/u1/replay-start_three_lanes-t10.png differ diff --git a/tools/dotnet/Directory.Build.props b/tools/dotnet/Directory.Build.props new file mode 100644 index 0000000..35edfd9 --- /dev/null +++ b/tools/dotnet/Directory.Build.props @@ -0,0 +1,7 @@ + + + + $(MSBuildThisFileDirectory)../../Temp/dotnet/obj/$(MSBuildProjectName)/ + $(MSBuildThisFileDirectory)../../Temp/dotnet/bin/$(MSBuildProjectName)/ + + diff --git a/tools/dotnet/Luneraria.Core.Bench/Program.cs b/tools/dotnet/Luneraria.Core.Bench/Program.cs new file mode 100644 index 0000000..7d20121 --- /dev/null +++ b/tools/dotnet/Luneraria.Core.Bench/Program.cs @@ -0,0 +1,74 @@ +using System; +using System.Collections.Generic; +using System.Diagnostics; +using System.IO; +using Luneraria.Core; + +/// +/// Measures the C# rules: one combat step at representative maximum occupation (round 13, +/// six armies at the supply cap, the same fixture as the Godot benchmark probe) and complete +/// bot matches. Usage: dotnet run -c Release --project tools/dotnet/Luneraria.Core.Bench [out.json] +/// +public static class Program +{ + public static int Main(string[] args) + { + var probe = new LuneMatch(); + probe.Setup(new MatchOptions { Seed = 5, HumanSlot = -1 }); + probe.RoundNumber = 13; + for (int slot = 0; slot < 6; slot++) + { + probe.Players[slot].Draft.Gold = 100000; + LuneBot.Plan(probe, slot, "ausgewogen"); + } + probe.BeginCombat(); + int units = probe.Combat.MobileCount(); + for (int i = 0; i < 50; i++) + probe.StepCombat(); + var samples = new List(); + for (int block = 0; block < 5; block++) + { + var fresh = new LuneMatch(); + fresh.Setup(new MatchOptions { Seed = 5, HumanSlot = -1 }); + fresh.RoundNumber = 13; + for (int slot = 0; slot < 6; slot++) + { + fresh.Players[slot].Draft.Gold = 100000; + LuneBot.Plan(fresh, slot, "ausgewogen"); + } + fresh.BeginCombat(); + var clock = Stopwatch.StartNew(); + for (int i = 0; i < 200; i++) + fresh.StepCombat(); + clock.Stop(); + samples.Add(clock.Elapsed.TotalMilliseconds / 200.0); + } + samples.Sort(); + double stepMs = samples[samples.Count / 2]; + var matchClock = Stopwatch.StartNew(); + int rounds = 0; + foreach (int seed in new[] { 1, 2, 3 }) + { + var match = new LuneMatch(); + match.Setup(new MatchOptions { Seed = seed, HumanSlot = -1 }); + while (match.Phase != Phase.Over && match.RoundNumber <= 60) + { + for (int slot = 0; slot < 6; slot++) + LuneBot.Plan(match, slot); + match.BeginCombat(); + match.FinishCombat(); + rounds++; + } + } + matchClock.Stop(); + string json = string.Format(System.Globalization.CultureInfo.InvariantCulture, + "{{\n \"runtime\": \"{0}\",\n \"cpu\": \"{1}\",\n \"mobile_units_at_start\": {2},\n \"sim_step_ms_median\": {3:0.0000},\n \"step_blocks_ms\": [{4}],\n \"bot_matches_seeds_1_2_3_ms\": {5:0.0},\n \"bot_match_rounds\": {6},\n \"ms_per_round\": {7:0.00}\n}}\n", + System.Runtime.InteropServices.RuntimeInformation.FrameworkDescription, System.Runtime.InteropServices.RuntimeInformation.OSArchitecture, + units, stepMs, string.Join(", ", samples.ConvertAll(s => s.ToString("0.0000", System.Globalization.CultureInfo.InvariantCulture))), + matchClock.Elapsed.TotalMilliseconds, rounds, matchClock.Elapsed.TotalMilliseconds / rounds); + Console.Write(json); + if (args.Length > 0) + File.WriteAllText(args[0], json); + return 0; + } +} diff --git a/tools/dotnet/Luneraria.Core.Tests/Program.cs b/tools/dotnet/Luneraria.Core.Tests/Program.cs new file mode 100644 index 0000000..209934b --- /dev/null +++ b/tools/dotnet/Luneraria.Core.Tests/Program.cs @@ -0,0 +1,72 @@ +using System; +using System.Collections.Generic; +using System.Diagnostics; +using System.IO; +using System.Text; + +namespace Luneraria.Core.Tests +{ + /// + /// Console runner: dotnet run --project tools/dotnet/Luneraria.Core.Tests -- [suite ...] + /// Writes docs/port/logs/u1/core-tests.json and exits non-zero on any failure. + /// + public static class Program + { + public static int Main(string[] args) + { + string root = FindRoot(); + string golden = Path.Combine(root, "Assets/Luneraria/Tests/Core/Golden"); + if (args.Length == 4 && args[0] == "--image") + return ReplayImage.Write(golden, args[1], args[2], Path.GetFullPath(args[3])); + var wanted = new HashSet(args); + var report = new StringBuilder("{\n \"suites\": [\n"); + int failures = 0; + bool first = true; + foreach (CheckSuite suite in CheckSuite.All()) + { + if (wanted.Count > 0 && !wanted.Contains(suite.Name)) + continue; + suite.GoldenDirectory = golden; + var clock = Stopwatch.StartNew(); + bool ok = suite.Run(); + clock.Stop(); + failures += suite.Failures.Count; + Console.WriteLine("LUNE_U1_{0} {1}: {2} checks; {3} failures ({4:0.0} s)", ok ? "PASS" : "FAIL", suite.Name, suite.Checks, suite.Failures.Count, clock.Elapsed.TotalSeconds); + foreach (string failure in suite.Failures) + Console.WriteLine(" FAIL " + failure); + foreach (string note in suite.Notes) + Console.WriteLine(" note " + note); + report.Append(first ? "" : ",\n"); + first = false; + report.AppendFormat(" {{\"suite\": \"{0}\", \"checks\": {1}, \"failures\": {2}, \"seconds\": {3:0.00}, \"failed\": [{4}], \"notes\": [{5}]}}", + suite.Name, suite.Checks, suite.Failures.Count, clock.Elapsed.TotalSeconds, Join(suite.Failures), Join(suite.Notes)); + } + report.Append("\n ],\n \"runtime\": \"" + System.Runtime.InteropServices.RuntimeInformation.FrameworkDescription + "\",\n"); + report.Append(" \"os\": \"" + System.Runtime.InteropServices.RuntimeInformation.OSDescription + " " + System.Runtime.InteropServices.RuntimeInformation.ProcessArchitecture + "\"\n}\n"); + if (wanted.Count == 0) + { + string logs = Path.Combine(root, "docs/port/logs/u1"); + Directory.CreateDirectory(logs); + File.WriteAllText(Path.Combine(logs, "core-tests.json"), report.ToString()); + } + Console.WriteLine(failures == 0 ? "LUNE_U1_TESTS_OK" : "LUNE_U1_TESTS_FAILED"); + return failures == 0 ? 0 : 1; + } + + static string Join(List values) + { + var parts = new List(); + foreach (string value in values) + parts.Add("\"" + value.Replace("\\", "\\\\").Replace("\"", "\\\"").Replace("\n", "\\n") + "\""); + return string.Join(", ", parts); + } + + static string FindRoot() + { + string dir = AppContext.BaseDirectory; + while (dir != null && !Directory.Exists(Path.Combine(dir, "Assets/Luneraria"))) + dir = Path.GetDirectoryName(dir); + return dir ?? Directory.GetCurrentDirectory(); + } + } +} diff --git a/tools/dotnet/Luneraria.Core.Tests/ReplayImage.cs b/tools/dotnet/Luneraria.Core.Tests/ReplayImage.cs new file mode 100644 index 0000000..216398d --- /dev/null +++ b/tools/dotnet/Luneraria.Core.Tests/ReplayImage.cs @@ -0,0 +1,191 @@ +using System; +using System.Collections.Generic; +using System.IO; +using System.IO.Compression; +using System.Linq; + +namespace Luneraria.Core.Tests +{ + /// + /// Visual evidence for U1: the map with lanes and buildings, the Godot reference positions of + /// every unit of a golden snapshot as filled dots (Blau blue, Rot red, grotto violet) and the + /// C# positions of the same snapshot as white rings. Identical positions show as ringed dots. + /// Usage: Luneraria.Core.Tests.dll --image <scenario> <label> <out.png> + /// + public static class ReplayImage + { + const int Size = 1100; + + public static int Write(string golden, string scenarioId, string label, string outPath) + { + var spec = MiniJson.Obj(MiniJson.Parse(File.ReadAllText(Path.Combine(golden, "scenarios.json")))); + var scenario = MiniJson.Arr(spec["scenarios"]).Select(MiniJson.Obj).First(s => MiniJson.Str(s["id"]) == scenarioId); + var replay = new GoldenReplay(); + foreach (object op in MiniJson.Arr(scenario["ops"])) + replay.Apply(MiniJson.Obj(op)); + var reference = MiniJson.Obj(MiniJson.Obj(MiniJson.Obj(MiniJson.Parse(File.ReadAllText(Path.Combine(golden, "golden.json"))))["scenarios"])[scenarioId]); + var expected = MiniJson.Arr(reference["snapshots"]).Select(MiniJson.Obj).First(s => MiniJson.Str(s["label"]) == label); + var actual = replay.Snapshots.Select(o => (OrderedMap)o).First(s => MiniJson.Str(s["label"]) == label); + var pixels = new byte[Size * Size * 3]; + Fill(pixels, 12, 16, 20); + LuneMap map = replay.State.Map; + foreach (LanePath path in map.LanePaths.Values) + { + for (int i = 1; i < path.Points.Length; i++) + Line(pixels, path.Points[i - 1], path.Points[i], 110, 100, 80); + } + foreach (BuildingDef building in map.Buildings) + Square(pixels, building.Position, building.Tier == "core" ? 9 : 6, building.Team == 0 ? (byte)70 : (byte)200, 90, building.Team == 0 ? (byte)200 : (byte)70); + int same = 0; + int total = 0; + List expectedUnits = MiniJson.Arr(expected["units"]); + List actualUnits = MiniJson.Arr(actual["units"]); + for (int i = 0; i < expectedUnits.Count; i++) + { + var unit = MiniJson.Obj(expectedUnits[i]); + if (!(bool)unit["alive"] || MiniJson.Str(unit["kind"]) == "tower" || MiniJson.Str(unit["kind"]) == "core") + continue; + int team = MiniJson.Int(unit["team"]); + var at = new Vec2(MiniJson.Num(unit["x"]), MiniJson.Num(unit["y"])); + Disc(pixels, at, 4, team == 0 ? (byte)90 : team == 1 ? (byte)255 : (byte)180, team == 0 ? (byte)170 : team == 1 ? (byte)110 : (byte)120, team == 0 ? (byte)255 : team == 1 ? (byte)90 : (byte)255); + var mine = MiniJson.Obj(actualUnits[i]); + var mineAt = new Vec2(MiniJson.Num(mine["x"]), MiniJson.Num(mine["y"])); + Ring(pixels, mineAt, 6, 255, 255, 255); + total++; + if (mineAt.DistanceTo(at) <= 0.001f) + same++; + } + WritePng(outPath, pixels); + Console.WriteLine("REPLAY_IMAGE {0}/{1}: {2} of {3} living units at the reference position -> {4}", scenarioId, label, same, total, outPath); + return same == total ? 0 : 1; + } + + static int Px(float world) { return (int)Math.Round((world + 40f) / 80f * (Size - 1)); } + + static void Set(byte[] pixels, int x, int y, byte r, byte g, byte b) + { + if (x < 0 || y < 0 || x >= Size || y >= Size) + return; + int at = (y * Size + x) * 3; + pixels[at] = r; + pixels[at + 1] = g; + pixels[at + 2] = b; + } + + static void Fill(byte[] pixels, byte r, byte g, byte b) + { + for (int i = 0; i < pixels.Length; i += 3) + { + pixels[i] = r; + pixels[i + 1] = g; + pixels[i + 2] = b; + } + } + + static void Line(byte[] pixels, Vec2 a, Vec2 b, byte r, byte g, byte bl) + { + int steps = Math.Max(1, (int)(a.DistanceTo(b) / 80f * Size * 2f)); + for (int i = 0; i <= steps; i++) + { + Vec2 p = a.Lerp(b, (double)i / steps); + for (int dx = -2; dx <= 2; dx++) + for (int dy = -2; dy <= 2; dy++) + Set(pixels, Px(p.X) + dx, Px(p.Y) + dy, r, g, bl); + } + } + + static void Square(byte[] pixels, Vec2 at, int half, byte r, byte g, byte b) + { + for (int dx = -half; dx <= half; dx++) + for (int dy = -half; dy <= half; dy++) + Set(pixels, Px(at.X) + dx, Px(at.Y) + dy, r, g, b); + } + + static void Disc(byte[] pixels, Vec2 at, int radius, byte r, byte g, byte b) + { + for (int dx = -radius; dx <= radius; dx++) + for (int dy = -radius; dy <= radius; dy++) + if (dx * dx + dy * dy <= radius * radius) + Set(pixels, Px(at.X) + dx, Px(at.Y) + dy, r, g, b); + } + + static void Ring(byte[] pixels, Vec2 at, int radius, byte r, byte g, byte b) + { + for (int i = 0; i < 48; i++) + { + double angle = Math.PI * 2.0 * i / 48.0; + Set(pixels, Px(at.X) + (int)Math.Round(Math.Cos(angle) * radius), Px(at.Y) + (int)Math.Round(Math.Sin(angle) * radius), r, g, b); + } + } + + // ---------------------------------------------------------------- minimal PNG writer (RGB, no dependencies) + static void WritePng(string path, byte[] rgb) + { + Directory.CreateDirectory(Path.GetDirectoryName(path)); + var raw = new MemoryStream(); + for (int y = 0; y < Size; y++) + { + raw.WriteByte(0); + raw.Write(rgb, y * Size * 3, Size * 3); + } + byte[] data = raw.ToArray(); + var zlib = new MemoryStream(); + zlib.WriteByte(0x78); + zlib.WriteByte(0x9C); + using (var deflate = new DeflateStream(zlib, CompressionLevel.Optimal, true)) + deflate.Write(data, 0, data.Length); + uint adler = Adler32(data); + zlib.WriteByte((byte)(adler >> 24)); + zlib.WriteByte((byte)(adler >> 16)); + zlib.WriteByte((byte)(adler >> 8)); + zlib.WriteByte((byte)adler); + using (FileStream file = File.Create(path)) + { + file.Write(new byte[] { 137, 80, 78, 71, 13, 10, 26, 10 }, 0, 8); + var header = new List(); + header.AddRange(BigEndian(Size)); + header.AddRange(BigEndian(Size)); + header.AddRange(new byte[] { 8, 2, 0, 0, 0 }); + Chunk(file, "IHDR", header.ToArray()); + Chunk(file, "IDAT", zlib.ToArray()); + Chunk(file, "IEND", new byte[0]); + } + } + + static byte[] BigEndian(int value) { return new[] { (byte)(value >> 24), (byte)(value >> 16), (byte)(value >> 8), (byte)value }; } + + static void Chunk(Stream stream, string type, byte[] data) + { + byte[] kind = System.Text.Encoding.ASCII.GetBytes(type); + stream.Write(BigEndian(data.Length), 0, 4); + stream.Write(kind, 0, 4); + stream.Write(data, 0, data.Length); + byte[] both = kind.Concat(data).ToArray(); + stream.Write(BigEndian((int)Crc32(both)), 0, 4); + } + + static uint Crc32(byte[] data) + { + uint crc = 0xFFFFFFFF; + foreach (byte value in data) + { + crc ^= value; + for (int k = 0; k < 8; k++) + crc = (crc & 1) != 0 ? 0xEDB88320 ^ (crc >> 1) : crc >> 1; + } + return ~crc; + } + + static uint Adler32(byte[] data) + { + uint a = 1; + uint b = 0; + foreach (byte value in data) + { + a = (a + value) % 65521; + b = (b + a) % 65521; + } + return (b << 16) | a; + } + } +} diff --git a/tools/godot-golden/content_export.gd b/tools/godot-golden/content_export.gd new file mode 100644 index 0000000..62b5c64 --- /dev/null +++ b/tools/godot-golden/content_export.gd @@ -0,0 +1,63 @@ +extends Node +## Exports every rule table of the Godot reference as JSON (insertion order kept, doubles at +## full precision): DataCatalog units, enemies and sends, LuneContent, LuneBot profiles, the +## default LuneBalance and the lane geometry. tools/port/gen_content.py turns it into +## Assets/Luneraria/Core/Content/ContentData.cs once; the C# file is maintained from then on. +## Run: sh tools/godot-golden/run_godot.sh content_export --out=/tmp/lune_content.json + +func _ready() -> void: + var out: String = "/tmp/lune_content.json" + for arg: String in OS.get_cmdline_user_args(): + if arg.begins_with("--out="): + out = arg.substr(6) + var balance := LuneBalance.default_balance() + var balance_values: Dictionary = {} + for property: Dictionary in balance.get_property_list(): + if property.usage & PROPERTY_USAGE_SCRIPT_VARIABLE: + var value: Variant = balance.get(property.name) + balance_values[property.name] = Array(value) if value is PackedStringArray else value + var map := LuneMap.new(balance) + var lanes: Dictionary = {} + for lane: String in LuneMap.LANES: + var path: LuneMap.LanePath = map.lanes[lane] + var points: Array = [] + for p: Vector2 in path.points: + points.append([p.x, p.y]) + lanes[lane] = {"length": path.length, "points": points, "cumulative": Array(path.cumulative)} + var buildings: Array = [] + for definition: Dictionary in map.buildings: + var copy: Dictionary = definition.duplicate() + copy.position = [definition.position.x, definition.position.y] + buildings.append(copy) + var data: Dictionary = { + "engine": Engine.get_version_info().string, + "units": _plain(DataCatalog.UNITS), "enemies": _plain(DataCatalog.ENEMIES), "sends": _plain(DataCatalog.SENDS), + "faction_names": DataCatalog.FACTION_NAMES, "armor_names": DataCatalog.ARMOR_NAMES, "damage_names": DataCatalog.DAMAGE_NAMES, + "heroes": LuneContent.HEROES, "level_xp": LuneContent.LEVEL_XP, "talent_levels": LuneContent.TALENT_LEVELS, + "talents": LuneContent.TALENTS, "items": LuneContent.ITEMS, "champions": LuneContent.CHAMPIONS, + "content_constants": {"HP_PER_LEVEL": LuneContent.HP_PER_LEVEL, "DAMAGE_PER_LEVEL": LuneContent.DAMAGE_PER_LEVEL, + "XP_PARTICIPATION": LuneContent.XP_PARTICIPATION, "XP_PER_ROUND": LuneContent.XP_PER_ROUND, "XP_RADIUS": LuneContent.XP_RADIUS, + "ITEM_SLOTS": LuneContent.ITEM_SLOTS, "ITEM_REFUND": LuneContent.ITEM_REFUND, "CHAMPION_HP": LuneContent.CHAMPION_HP, + "CHAMPION_DAMAGE": LuneContent.CHAMPION_DAMAGE, "CHAMPION_BOUNTY": LuneContent.CHAMPION_BOUNTY, + "CHAMPION_BOUNTY_PER_ROUND": LuneContent.CHAMPION_BOUNTY_PER_ROUND, "MAX_BOOKINGS": LuneContent.MAX_BOOKINGS, + "BOSS_MODEL": LuneContent.BOSS_MODEL, "BOSS_GROTTO_HP": LuneContent.BOSS_GROTTO_HP, "BOSS_GROTTO_DAMAGE": LuneContent.BOSS_GROTTO_DAMAGE, + "BOSS_DEPLOY_HP": LuneContent.BOSS_DEPLOY_HP, "BOSS_DEPLOY_DAMAGE": LuneContent.BOSS_DEPLOY_DAMAGE, "BOSS_BOUNTY": LuneContent.BOSS_BOUNTY, + "BOSS_BOUNTY_PER_ROUND": LuneContent.BOSS_BOUNTY_PER_ROUND, "BOSS_LOCK_ROUNDS": LuneContent.BOSS_LOCK_ROUNDS, + "BOSS_XP": LuneContent.BOSS_XP, "BUILDING_XP": LuneContent.BUILDING_XP}, + "match_roles": LuneMatch.ROLES, "hero_roles": LuneMatch.HERO_ROLES, "row_order": LuneMatch.ROW_ORDER, "bot_names": LuneMatch.BOT_NAMES, + "bot_profiles": LuneBot.PROFILES, "bot_constants": {"BOSS_BAR": LuneBot.BOSS_BAR, "BOSS_BAR_STEP": LuneBot.BOSS_BAR_STEP}, + "waves_melee": LuneWaves.MELEE, "balance": balance_values, "lanes": lanes, "buildings": buildings} + var file := FileAccess.open(out, FileAccess.WRITE) + file.store_string(JSON.stringify(data, "\t", false, true)) + file.close() + print("CONTENT_EXPORT ", out) + get_tree().quit() + +## Colours are presentation data; everything else is copied as is. +func _plain(table: Dictionary) -> Dictionary: + var result: Dictionary = {} + for key: String in table: + var entry: Dictionary = (table[key] as Dictionary).duplicate(true) + entry.erase("color") + result[key] = entry + return result diff --git a/tools/godot-golden/float_probe.gd b/tools/godot-golden/float_probe.gd new file mode 100644 index 0000000..c9126fd --- /dev/null +++ b/tools/godot-golden/float_probe.gd @@ -0,0 +1,29 @@ +extends SceneTree +## Float calibration: how does this Godot binary compute Vector2 math (float32, FMA or not)? +## Writes inputs and results as raw float32 bits so the C# port can match them exactly. +## Run: godot --headless --path ../saumwacht-godot --script -- + +func _init() -> void: + var out: String = OS.get_cmdline_user_args()[0] if not OS.get_cmdline_user_args().is_empty() else "/tmp/float_probe.json" + var state: int = 12345 + var rows: Array = [] + for i: int in range(4000): + var values: Array[float] = [] + for k: int in range(5): + state = (state * 1103515245 + 12345) % 2147483648 + values.append((float(state) / 2147483648.0 - 0.5) * 80.0) + var a := Vector2(values[0], values[1]) + var b := Vector2(values[2], values[3]) + var w: float = absf(values[4]) / 40.0 + var s: float = values[4] + var f := PackedFloat32Array([a.x, a.y, b.x, b.y, w, s, + a.length(), a.length_squared(), a.distance_to(b), a.distance_squared_to(b), a.dot(b), + a.normalized().x, a.normalized().y, a.lerp(b, w).x, a.lerp(b, w).y, + a.limit_length(0.9).x, a.limit_length(0.9).y, (a * s).x, (a / s).y, (a - b).normalized().x]) + var d := PackedFloat64Array([atan2(a.x, a.y), clampf(s, -3.0, 3.0), float(a.x) * s + float(b.y)]) + rows.append([f.to_byte_array().hex_encode(), d.to_byte_array().hex_encode()]) + var file := FileAccess.open(out, FileAccess.WRITE) + file.store_string(JSON.stringify({"engine": Engine.get_version_info().string, "rows": rows})) + file.close() + print("FLOAT_PROBE ", rows.size(), " -> ", out) + quit() diff --git a/tools/godot-golden/golden_scenarios.gd b/tools/godot-golden/golden_scenarios.gd new file mode 100644 index 0000000..19a1fda --- /dev/null +++ b/tools/godot-golden/golden_scenarios.gd @@ -0,0 +1,210 @@ +extends Node +## Golden references for the C# port: interprets Assets/Luneraria/Tests/Core/Golden/scenarios.json +## with the Godot rules (luneraria/g3, 1b540f2) and writes the domain state after every +## "snapshot" operation plus the result of every command (Golden/golden.json). The C# core +## (GoldenSuite) runs the same operations and compares its own snapshots field by field. +## Run: sh tools/godot-golden/run_godot.sh golden_scenarios --in= --out= [--only=id,...] + +var state: LuneMatch +var snapshots: Array = [] +var results: Array = [] + +func _ready() -> void: + var source: String = "" + var out: String = "/tmp/lune_golden.json" + var only: PackedStringArray = [] + for arg: String in OS.get_cmdline_user_args(): + if arg.begins_with("--in="): + source = arg.substr(5) + elif arg.begins_with("--out="): + out = arg.substr(6) + elif arg.begins_with("--only="): + only = arg.substr(7).split(",") + var spec: Dictionary = JSON.parse_string(FileAccess.get_file_as_string(source)) + var scenarios: Dictionary = {} + for scenario: Dictionary in spec.scenarios: + if not only.is_empty() and not only.has(scenario.id): + continue + var started: int = Time.get_ticks_msec() + snapshots = [] + results = [] + for operation: Dictionary in scenario.ops: + _apply(operation) + scenarios[scenario.id] = {"title": scenario.title, "snapshots": snapshots, "results": results} + print("GOLDEN %s: %d snapshots, %d results, %d ms" % [scenario.id, snapshots.size(), results.size(), Time.get_ticks_msec() - started]) + var file := FileAccess.open(out, FileAccess.WRITE) + file.store_string(JSON.stringify({"engine": Engine.get_version_info().string, "reference": "luneraria/g3 1b540f2", "scenarios": scenarios}, "", false, true)) + file.close() + print("GOLDEN_DONE ", out) + get_tree().quit() + +# ---------------------------------------------------------------- operations +func _apply(op: Dictionary) -> void: + match str(op.op): + "setup": + state = LuneMatch.new() + var options: Dictionary = {"seed": int(op.seed), "human_slot": int(op.get("human", -1))} + if op.has("bunds"): + options.bunds = op.bunds + if op.has("profiles"): + options.profiles = op.profiles + state.setup(options) + "building": + state.building_hp[str(op.id)] = float(op.hp) + "buildings_full": + for definition: Dictionary in state.map.buildings: + state.building_hp[definition.id] = float(definition.max_hp) + "round": + state.round_number = int(op.value) + "gold": + state.players[int(op.slot)].draft.gold = int(state.players[int(op.slot)].draft.gold) + int(op.add) + "gold_all": + for player: Dictionary in state.players: + player.draft.gold = int(player.draft.gold) + int(op.add) + "cmd": + var command: Dictionary = _resolve(int(op.slot), op.command) + var result: Dictionary = state.submit(int(op.slot), command) + results.append(["cmd", int(op.slot), str(command.type), bool(result.ok), str(result.message)]) + "bots": + for slot: int in range(6): + LuneBot.plan(state, slot, str(op.get("profile", ""))) + "begin": + results.append(["begin", -1, "", state.begin_combat(), ""]) + "steps": + for i: int in range(int(op.n)): + if state.phase != LuneMatch.Phase.COMBAT: + break + state.step_combat() + "finish": + state.finish_combat() + "unit_set": + var select: Dictionary = op.select + for unit: LuneUnit in state.combat.units: + if select.has("kind") and unit.kind != str(select.kind): + continue + if select.has("zone") and unit.zone != str(select.zone): + continue + if select.has("team") and unit.team != int(select.team): + continue + if op.has("hp"): + unit.hp = float(op.hp) + "settle_boss": + results.append(["settle_boss", -1, "", true, state._settle_boss()]) + "expedition": + var slot: int = int(op.slot) + state.players[slot].draft.gold = int(state.players[slot].draft.gold) + 6000 + var ids: Array[String] = state.base_ids(state.players[slot].bund) + for type_index: Variant in op.types: + _record(slot, {"type": "buy", "type_id": ids[int(type_index)]}) + var entry: Dictionary = state.players[slot].draft.roster[-1] + _record(slot, {"type": "upgrade", "uid": entry.uid}) + _record(slot, {"type": "assign", "uid": entry.uid, "lane": "grotto"}) + if op.has("hero"): + _record(slot, {"type": "hero_buy", "hero_id": str(op.hero)}) + _record(slot, {"type": "assign", "uid": state.players[slot].draft.hero.uid, "lane": "grotto"}) + "play": + for i: int in range(int(op.rounds)): + if state.phase == LuneMatch.Phase.OVER: + break + if bool(op.get("bots", true)): + for slot: int in range(6): + LuneBot.plan(state, slot, str(op.get("profile", ""))) + var fought: int = state.round_number + state.begin_combat() + state.finish_combat() + _snapshot({"label": "round-%d" % fought}) + "snapshot": + _snapshot(op) + _: + push_error("unknown op " + str(op.op)) + +func _record(slot: int, command: Dictionary) -> void: + var result: Dictionary = state.submit(slot, command) + results.append(["cmd", slot, str(command.type), bool(result.ok), str(result.message)]) + +## Uid references: $last:, $roster::, $hero:, $booking::. +func _resolve(slot: int, command: Dictionary) -> Dictionary: + var copy: Dictionary = command.duplicate(true) + if copy.has("uid") and str(copy.uid).begins_with("$"): + var parts: PackedStringArray = str(copy.uid).substr(1).split(":") + var owner: Dictionary = state.players[int(parts[1])] + match parts[0]: + "last": copy.uid = str(owner.draft.roster[-1].uid) + "roster": copy.uid = str(owner.draft.roster[int(parts[2])].uid) + "hero": copy.uid = str(owner.draft.hero.uid) + "booking": copy.uid = str(owner.draft.new_bookings[int(parts[2])].uid) + if copy.has("tier"): + copy.tier = int(copy.tier) + if copy.has("choice"): + copy.choice = int(copy.choice) + return copy + +# ---------------------------------------------------------------- snapshot +func _snapshot(op: Dictionary) -> void: + var players: Array = [] + for player: Dictionary in state.players: + players.append({"gold": int(player.gold), "draft_gold": int(player.draft.gold), "ready": bool(player.ready), "earned": int(player.earned), + "spent": int(player.spent), "next_seq": int(player.next_seq), "roster": _roster(player.roster, false), "hero": _hero(player.hero), + "bookings": player.bookings.map(func(b: Dictionary) -> String: return "%s|%s|%s|%d|%d" % [b.uid, b.champion_id, b.lane, int(b.cost), int(b.get("deploy_round", 0))]), + "new_bookings": (player.draft.new_bookings as Array).map(func(b: Dictionary) -> String: return "%s|%s|%s|%d" % [b.uid, b.champion_id, b.lane, int(b.cost)]), + "draft_roster": _roster(player.draft.roster, true), "draft_hero": _hero(player.draft.hero), "boss_lane": str(player.draft.boss_lane), + "undo": (player.undo as Array).size()}) + var claim: Dictionary = state.boss.get("claim", {}) + var snap: Dictionary = {"label": str(op.label), "phase": state.phase, "round": state.round_number, "winner": state.winner, "end_note": state.end_note, + "players": players, "buildings": state.map.buildings.map(func(d: Dictionary) -> float: return float(state.building_hp[d.id])), + "boss": {"next": int(state.boss.next_available_round), "settled": int(state.boss.get("settled_round", 0)), + "claim": "" if claim.is_empty() else "%d|%d|%d|%d|%s" % [int(claim.team), int(claim.won_round), int(claim.deploy_round), int(claim.chooser_slot), claim.lane]}, + "boss_log": state.boss_log.map(func(e: Dictionary) -> String: return "%d|%s|%d|%s|%d" % [int(e.round), e.event, int(e.get("team", -1)), str(e.get("lane", "")), int(e.get("chooser", -1))]), + "announcements": state.announcements().map(func(a: Dictionary) -> String: return "%s|%d|%d|%s|%s|%d" % [a.kind, int(a.team), int(a.slot), a.lane, str(a.get("champion_id", "")), int(a.get("bounty", 0))]), + "settlement": _settlement(), "combat": _combat()} + if bool(op.get("units", false)) and state.combat != null: + snap.units = state.combat.units.map(_unit) + if bool(op.get("events", false)) and state.combat != null: + snap.events = state.combat.events.map(func(e: Dictionary) -> Array: return [int(e.serial), int(e.step), float(e.time), int(e.team), str(e.lane), str(e.zone), str(e.kind), + int(e.unit_id), str(e.def_id), int(e.bounty), str(e.get("building_id", "")), int(e.xp), e.xp_heroes]) + if bool(op.get("wave", false)): + snap.wave = LuneWaves.build(state.balance, state.round_number).map(func(m: Dictionary) -> Array: return [str(m.id), float(m.max_hp), float(m.damage), int(m.bounty)]) + snapshots.append(snap) + +func _roster(roster: Array, with_fresh: bool) -> Array: + return roster.map(func(e: Dictionary) -> String: return "%s|%s|%s|%d%s" % [e.uid, e.type_id, e.lane, int(e.invested), ("|%s" % str(bool(e.get("fresh", false))).to_lower()) if with_fresh else ""]) + +func _hero(hero: Dictionary) -> String: + if hero.is_empty(): + return "" + return "%s|%s|%d|%s|%s|%s|%d|%s|%s" % [hero.uid, hero.hero_id, int(hero.xp), hero.lane, "+".join(hero.items), "+".join(hero.talents), int(hero.invested), + str(bool(hero.get("fresh", false))).to_lower(), "+".join(hero.get("fresh_items", []))] + +func _settlement() -> Variant: + var s: Dictionary = state.last_settlement + if s.is_empty(): + return null + return {"round": int(s.round), "gains": (s.gains as Array).map(func(g: int) -> int: return g), "income": int(s.income), "lost": s.buildings_lost, + "end_reason": str(s.end_reason), "combat_time": float(s.combat_time), "boss": str(s.boss), "lane_kills": s.lane_kills, "xp": s.xp} + +func _combat() -> Variant: + var c: LuneCombat = state.combat + if c == null: + return null + var boss: String = "" + if c.grotto_boss != null: + boss = "%s|%s|%s" % [str(c.grotto_boss.alive).to_lower(), str(c.grotto_boss.dormant).to_lower(), str(c.grotto_boss.id)] + return {"round": c.round_number, "steps": c.steps, "elapsed": c.elapsed, "finished": c.finished, "end_reason": c.end_reason, + "destroyed": c.destroyed_cores.duplicate(), "grotto": "%s|%d|%d|%s" % [c.grotto_outcome, c.grotto_claim_team, c.grotto_active_team, str(c.grotto_resolved).to_lower()], + "grotto_boss": boss, "grotto_boss_hp": c.grotto_boss.hp if c.grotto_boss != null else 0.0, "events": c.events.size(), + "mobile": [c.mobile_count(0), c.mobile_count(1), c.mobile_count(2)]} + +func _unit(unit: LuneUnit) -> Dictionary: + var effects: Array = [] + for family: String in unit.effects: + var effect: Dictionary = unit.effects[family] + effects.append([family, str(effect.kind), float(effect.amount), float(effect.remaining)]) + var dots: Array = [] + for family: String in unit.dots: + var dot: Dictionary = unit.dots[family] + dots.append([family, float(dot.damage), float(dot.remaining), float(dot.next_tick), int(dot.attack_type)]) + return {"id": unit.id, "kind": unit.kind, "team": unit.team, "lane": unit.lane, "zone": unit.zone, "slot": unit.owner_slot, "uid": unit.persistent_uid, + "def": str(unit.def.get("id", "")), "alive": unit.alive, "hp": unit.hp, "max_hp": unit.max_hp, "shield": unit.shield, + "x": unit.position.x, "y": unit.position.y, "facing": unit.facing, "progress": unit.progress, + "target": unit.target.id if unit.target != null else -1, "hits": unit.hit_count, "reached": unit.reached_base, "dormant": unit.dormant, + "effects": effects, "dots": dots} diff --git a/tools/godot-golden/run_godot.sh b/tools/godot-golden/run_godot.sh new file mode 100755 index 0000000..e158cbd --- /dev/null +++ b/tools/godot-golden/run_godot.sh @@ -0,0 +1,27 @@ +#!/bin/sh +# Runs a tool of tools/godot-golden as a scene inside the Godot reference project, so the +# project's autoloads (DataCatalog, ...) exist; `godot --script` would not load them. +# The tool is copied to /.port_tmp/ for the run and removed afterwards; the +# reference repository stays unchanged. +# Usage: sh tools/godot-golden/run_godot.sh [tool arguments ...] +set -u +HERE="$(cd "$(dirname "$0")" && pwd)" +GODOT_PROJECT="${GODOT_PROJECT:-$HERE/../../../saumwacht-godot}" +GODOT="${GODOT:-godot}" +NAME="$1" +shift +TMP="$GODOT_PROJECT/.port_tmp" +mkdir -p "$TMP" +cp "$HERE/$NAME.gd" "$TMP/$NAME.gd" +cat > "$TMP/$NAME.tscn" < + +func _ready() -> void: + var out: String = "" + for arg: String in OS.get_cmdline_user_args(): + if arg.begins_with("--out="): + out = arg.substr(6) + var samples: Array[float] = [] + var units: int = 0 + for block: int in range(5): + var fresh := LuneMatch.new() + fresh.setup({"seed": 5, "human_slot": -1}) + fresh.round_number = 13 + for slot: int in range(6): + fresh.players[slot].draft.gold = 100000 + LuneBot.plan(fresh, slot, "ausgewogen") + fresh.begin_combat() + units = fresh.combat.mobile_count() + var started: int = Time.get_ticks_usec() + for i: int in range(200): + fresh.step_combat() + samples.append((Time.get_ticks_usec() - started) / 1000.0 / 200.0) + samples.sort() + var match_started: int = Time.get_ticks_usec() + var rounds: int = 0 + for seed: int in [1, 2, 3]: + var state := LuneMatch.new() + state.setup({"seed": seed, "human_slot": -1}) + while state.phase != LuneMatch.Phase.OVER and state.round_number <= 60: + for slot: int in range(6): + LuneBot.plan(state, slot) + state.begin_combat() + state.finish_combat() + rounds += 1 + var match_ms: float = (Time.get_ticks_usec() - match_started) / 1000.0 + var report := {"engine": Engine.get_version_info().string, "mobile_units_at_start": units, "sim_step_ms_median": samples[samples.size() / 2], + "step_blocks_ms": samples, "bot_matches_seeds_1_2_3_ms": match_ms, "bot_match_rounds": rounds, "ms_per_round": match_ms / rounds} + print("SIM_BENCH ", JSON.stringify(report)) + if not out.is_empty(): + var file := FileAccess.open(out, FileAccess.WRITE) + file.store_string(JSON.stringify(report, "\t")) + file.close() + get_tree().quit() diff --git a/tools/port/gen_content.py b/tools/port/gen_content.py new file mode 100644 index 0000000..4e45bbb --- /dev/null +++ b/tools/port/gen_content.py @@ -0,0 +1,158 @@ +#!/usr/bin/env python3 +"""Generates Assets/Luneraria/Core/Content/ContentData.cs from the Godot content export +(tools/godot-golden/content_export.gd). One-time bootstrap of the port: after generation the +C# file is the maintained source; a test compares it with the exported reference +(Assets/Luneraria/Tests/Core/Golden/content.json). +Usage: python3 tools/port/gen_content.py /tmp/lune_content.json +""" +import json +import sys +from pathlib import Path + +ROOT = Path(__file__).resolve().parents[2] +OUT = ROOT / "Assets/Luneraria/Core/Content/ContentData.cs" + + +def s(value): + return '"' + str(value).replace("\\", "\\\\").replace('"', '\\"') + '"' + + +def d(value): + text = repr(float(value)) + return text if ("." in text or "e" in text or "inf" in text) else text + ".0" + + +UNIT_FIELDS = [("id", "Id", s), ("display_name", "DisplayName", s), ("cost", "Cost", int), ("upgrade_id", "UpgradeId", s), + ("max_hp", "MaxHp", d), ("damage", "Damage", d), ("attack_type", "AttackType", int), ("armor_type", "ArmorType", int), + ("attack_range", "AttackRange", d), ("speed", "Speed", d), ("ability", "Ability", s), ("leak_value", "LeakValue", int), + ("bounty", "Bounty", int), ("ability_description", "AbilityDescription", s), ("is_boss", "IsBoss", lambda v: "true" if v else "false"), + ("income_gain", "IncomeGain", int)] + + +def unit_def(entry, indent): + parts = [] + for key, name, fmt in UNIT_FIELDS: + if key in entry: + parts.append(f"{name} = {fmt(entry[key])}") + unknown = set(entry) - {k for k, _, _ in UNIT_FIELDS} + if unknown: + raise SystemExit(f"unknown unit keys {unknown}") + return "new UnitDef { " + ", ".join(parts) + " }" + + +def table(name, entries): + lines = [f" public static readonly OrderedMap {name} = Map("] + rows = [f" {unit_def(entry, 12)}" for entry in entries.values()] + lines.append(",\n".join(rows)) + lines.append(" );") + return "\n".join(lines) + + +def main(): + data = json.loads(Path(sys.argv[1]).read_text(encoding="utf-8")) + out = [] + out.append("// by tools/port/gen_content.py from the Godot reference (luneraria/g3, 1b540f2).") + out.append("// Since the port this file is the maintained source of the rule tables; ContentTests compares it") + out.append("// with the exported reference in Assets/Luneraria/Tests/Core/Golden/content.json.") + out.append("using System.Collections.Generic;") + out.append("") + out.append("namespace Luneraria.Core") + out.append("{") + out.append(" /// Rule tables of Champions of Luneraria: troops, monsters, sends, heroes, items, champions, bots.") + out.append(" public static partial class ContentData") + out.append(" {") + out.append(table("Units", data["units"]) + "\n") + out.append(table("Enemies", data["enemies"]) + "\n") + out.append(table("Sends", data["sends"]) + "\n") + # Heroes + out.append(" public static readonly OrderedMap Heroes = Ordered(") + rows = [] + for hero_id, hero in data["heroes"].items(): + base = hero["def"] + rows.append(" new HeroSpec { " + ", ".join([f"Id = {s(hero_id)}", f"Name = {s(hero['name'])}", f"Title = {s(hero['title'])}", + f"Model = {s(hero['model'])}", f"Cost = {int(hero['cost'])}", f"RoleText = {s(hero['role'])}", + f"Provisional = {'true' if hero.get('provisional') else 'false'}", f"Summary = {s(hero['summary'])}", + "Base = " + unit_def(base, 16)]) + " }") + out.append(",\n".join(rows)) + out.append(" );\n") + out.append(" public static readonly int[] LevelXp = { " + ", ".join(str(v) for v in data["level_xp"]) + " };") + out.append(" public static readonly int[] TalentLevels = { " + ", ".join(str(v) for v in data["talent_levels"]) + " };\n") + out.append(" /// Per hero: tiers of two mutually exclusive choices.") + out.append(" public static readonly Dictionary Talents = new Dictionary") + out.append(" {") + rows = [] + for hero_id, tiers in data["talents"].items(): + tier_rows = [] + for tier in tiers: + options = ", ".join(f"new TalentOption({s(o['id'])}, {s(o['name'])}, {s(o['text'])})" for o in tier) + tier_rows.append(" new[] { " + options + " }") + rows.append(" { " + s(hero_id) + ", new[]\n {\n" + ",\n".join(tier_rows) + "\n } }") + out.append(",\n".join(rows)) + out.append(" };\n") + # Items + out.append(" public static readonly OrderedMap Items = Ordered(") + rows = [] + known = {"name", "cost", "text", "hp_flat", "damage", "reduction", "attack_speed", "regen", "splash", "min_level"} + for item_id, item in data["items"].items(): + if set(item) - known: + raise SystemExit(f"unknown item keys {set(item) - known}") + parts = [f"Id = {s(item_id)}", f"Name = {s(item['name'])}", f"Cost = {int(item['cost'])}", f"Text = {s(item['text'])}"] + for key, name in [("hp_flat", "HpFlat"), ("damage", "Damage"), ("reduction", "Reduction"), ("attack_speed", "AttackSpeed"), ("regen", "Regen"), ("splash", "Splash")]: + if key in item: + parts.append(f"{name} = {d(item[key])}") + if "min_level" in item: + parts.append(f"MinLevel = {int(item['min_level'])}") + rows.append(" new ItemSpec { " + ", ".join(parts) + " }") + out.append(",\n".join(rows)) + out.append(" );\n") + # Champions + out.append(" public static readonly OrderedMap Champions = Ordered(") + rows = [] + known = {"name", "role", "model", "cost", "base", "text", "priority", "siege_factor", "view_scale"} + for champion_id, spec in data["champions"].items(): + if set(spec) - known: + raise SystemExit(f"unknown champion keys {set(spec) - known}") + parts = [f"Id = {s(champion_id)}", f"Name = {s(spec['name'])}", f"RoleText = {s(spec['role'])}", f"Model = {s(spec['model'])}", + f"Cost = {int(spec['cost'])}", f"Base = {s(spec['base'])}", f"Text = {s(spec['text'])}", f"ViewScale = {d(spec['view_scale'])}"] + if "priority" in spec: + parts.append(f"Priority = {s(spec['priority'])}") + if "siege_factor" in spec: + parts.append(f"SiegeFactor = {d(spec['siege_factor'])}") + rows.append(" new ChampionSpec { " + ", ".join(parts) + " }") + out.append(",\n".join(rows)) + out.append(" );\n") + # Roles, rows, names + out.append(" /// Base troop id to role; iteration order matters for RoleOf (first match).") + out.append(" public static readonly OrderedMap MatchRoles = Pairs(" + ", ".join(f"{s(k)}, {s(v)}" for k, v in data["match_roles"].items()) + ");") + out.append(" public static readonly OrderedMap HeroRoles = Pairs(" + ", ".join(f"{s(k)}, {s(v)}" for k, v in data["hero_roles"].items()) + ");") + out.append(" public static readonly string[] RowOrder = { " + ", ".join(s(v) for v in data["row_order"]) + " };") + out.append(" public static readonly string[] BotNames = { " + ", ".join(s(v) for v in data["bot_names"]) + " };") + out.append(" public static readonly string[] WavesMelee = { " + ", ".join(s(v) for v in data["waves_melee"]) + " };") + out.append(" public static readonly string[] ArmorNames = { " + ", ".join(s(v) for v in data["armor_names"]) + " };") + out.append(" public static readonly string[] DamageNames = { " + ", ".join(s(v) for v in data["damage_names"]) + " };") + out.append(" public static readonly OrderedMap FactionNames = Pairs(" + ", ".join(f"{s(k)}, {s(v)}" for k, v in data["faction_names"].items()) + ");\n") + # Bot profiles + out.append(" /// Bot profiles in the reference order (the seed rotation depends on it).") + out.append(" public static readonly OrderedMap BotProfiles = Ordered(") + rows = [] + for name, p in data["bot_profiles"].items(): + parts = [f"Name = {s(name)}", f"Front = {d(p['front'])}", f"Melee = {d(p['melee'])}", f"Ranged = {d(p['ranged'])}", + f"Splash = {d(p['splash'])}", f"Support = {d(p['support'])}", f"UpgradeFrom = {int(p['upgrade_from'])}", + f"SupportLane = {d(p['support_lane'])}", f"Hero = {s(p['hero'])}", f"HeroRound = {int(p['hero_round'])}", + "Items = new[] { " + ", ".join(s(i) for i in p["items"]) + " }", + "TalentChoices = new[] { " + ", ".join(str(int(t)) for t in p["talents"]) + " }", f"Champion = {s(p['champion'])}"] + if "boss_from" in p: + parts.append(f"BossFrom = {int(p['boss_from'])}") + parts.append(f"BossTroops = {int(p['boss_troops'])}") + rows.append(" new BotProfile { " + ", ".join(parts) + " }") + out.append(",\n".join(rows)) + out.append(" );") + out.append(" }") + out.append("}") + OUT.parent.mkdir(parents=True, exist_ok=True) + OUT.write_text("\n".join(out) + "\n", encoding="utf-8") + print("written", OUT, sum(1 for _ in OUT.open(encoding="utf-8")), "lines") + + +if __name__ == "__main__": + main() diff --git a/tools/run_core_tests.sh b/tools/run_core_tests.sh new file mode 100755 index 0000000..886485b --- /dev/null +++ b/tools/run_core_tests.sh @@ -0,0 +1,13 @@ +#!/bin/sh +# U1 core tests outside Unity: builds the rules (netstandard2.1, C# 9 = Unity's level) and runs +# every suite with the .NET SDK. Writes docs/port/logs/u1/core-tests.json. +# Optional: REGENERATE_GOLDEN=1 re-creates the Godot references first (needs ../saumwacht-godot). +set -eu +cd "$(dirname "$0")/.." +if [ "${REGENERATE_GOLDEN:-0}" = "1" ]; then + sh tools/godot-golden/run_godot.sh content_export --out="$PWD/Assets/Luneraria/Tests/Core/Golden/content.json" + sh tools/godot-golden/run_godot.sh golden_scenarios --in="$PWD/Assets/Luneraria/Tests/Core/Golden/scenarios.json" --out="$PWD/Assets/Luneraria/Tests/Core/Golden/golden.json" +fi +dotnet build tools/dotnet/Luneraria.Core/Luneraria.Core.csproj -c Release -nologo -v q +dotnet build tools/dotnet/Luneraria.Core.Tests/Luneraria.Core.Tests.csproj -c Release -nologo -v q +dotnet Temp/dotnet/bin/Luneraria.Core.Tests/Release/net8.0/Luneraria.Core.Tests.dll "$@"